【问题标题】:Delphi - Access Violation on Parsing JSON Data @ Run TimeDelphi - 在运行时解析 JSON 数据时访问冲突
【发布时间】:2013-11-04 23:52:39
【问题描述】:

论坛新手,如果我的帖子格式不正确或未遵循指南,敬请见谅。我会很快“明白”的。所以这是我的问题。看看下面的代码。我已经删除了几乎所有无关的部分,以将注意力集中在一个关键行上 --

LParts:=LJsonObj.Get('parts').JsonValue;

我在顶部 (Const) 上有一些 JSON 格式的数据,这些数据经过测试是有效的。当我尝试解析它时,它在运行时失败(编译时很好)。我已将所有这些简化为更小且更易于处理的东西。

当我在调试器中启动它时,这一切似乎都是有效的,但即使为 Nil 值添加了测试也不会在我对问题的理解中产生太多效果。

我希望有人知道问题可能是什么。这是sn-p的代码:

program ReadJSONConsoleApp;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  DBXJSON,
  System.SysUtils;


Const
StrJson=
'{' +
'    "response": {' +
'        "distributor": {' +
'            "id": 1538,' +
'            "name": "Arrow Electronics",' +
'            "authorized": true,' +
'            "logoUrl": "this is normally a URL but I cut it out"' +
'        },' +
'        "parts": [' +
'            {' +
'                "manufacturer": "National Semiconductor",' +
'                "part": "LM741WG/883",' +
'                "description": "OP Amp Single GP ±22V 10-Pin CFPAK Tray",' +
'                "price": [' +
'                    {' +
'                        "quantity": 0,' +
'                        "price": 65,' +
'                        "currency": "USD"' +
'                    }' +
'                ],' +
'                "stock": 88,' +
'                "lastUpdated": "2013-11-04 18:27:16 UTC"' +
'            },' +
'            {' +
'                "manufacturer": "National Semiconductor",' +
'                "part": "LM741W/883",' +
'                "description": "OP Amp Single GP ±22V 10-Pin CPAK Rail",' +
'                "price": [' +
'                    {' +
'                        "quantity": 0,' +
'                        "price": 40.5,' +
'                        "currency": "USD"' +
'                    }' +
'                ],' +
'                "stock": 1464,' +
'                "lastUpdated": "2013-11-04 18:27:16 UTC"' +
'            },' +
'            {' +
'                "manufacturer": "Texas Instruments",' +
'                "part": "LM741CH",' +
'                "description": "OP Amp Single GP ±18V 8-Pin TO-99 Box",' +
'                "price": [' +
'                    {' +
'                        "quantity": 0,' +
'                        "price": 5.22,' +
'                        "currency": "USD"' +
'                    }' +
'                ],' +
'                "stock": 95,' +
'                "lastUpdated": "2013-11-04 18:27:16 UTC"' +
'            }' +
'        ]' +
'    }' +
'}';

procedure ParseJson;
var
  LJsonObj  : TJSONObject;
  LJPair    : TJSONPair;
  LParts    : TJSONValue;
  LPart     : TJSONValue;
  LItem     : TJSONValue;
  LIndex    : Integer;
  LSize     : Integer;
begin
    LJsonObj    := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(StrJson),0) as TJSONObject;
  try
     LParts:=LJsonObj.Get('parts').JsonValue;
     {LSize:=TJSONArray(LParts).Size;
     for LIndex:=0 to LSize-1 do
     begin
      LPart := TJSONArray(LParts).Get(LIndex);
      LJPair   := TJSONPair(LPart);
      Writeln(Format('Part Name %s',[LJPair.JsonString.Value]));
        for LItem in TJSONArray(LJPair.JsonValue) do
        begin
           if TJSONPair(LItem).JsonValue is TJSONFalse then
            Writeln(Format('  %s : %s',[TJSONPair(LItem).JsonString.Value, 'false']))
           else
           if TJSONPair(LItem).JsonValue is TJSONTrue then
            Writeln(Format('  %s : %s',[TJSONPair(LItem).JsonString.Value, 'true']))
           else
            Writeln(Format('  %s : %s',[TJSONPair(LItem).JsonString.Value, TJSONPair(LItem).JsonValue.Value]));
        end;
     end; }
  finally
     LJsonObj.Free;
  end;
end;

begin
  try
    ParseJson;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

再次感谢您,感谢您对我的耐心。

亲切的问候,

EEJoe

【问题讨论】:

  • 失败在哪一行?你在顶部单挑的那个?你确定 ParseJSONValue 和 Get('parts') 没有返回 null 吗?
  • 顶级对象没有parts 属性,因此Get('parts') 可能返回nil。改用LJsonObj.Get('response').Get('parts') 之类的方法。

标签: json delphi parsing delphi-xe2


【解决方案1】:

您用于解析 JSON 响应的代码与 JSON 字符串的结构无关。首先推荐阅读JSON documentation,很容易理解。

用 cmets 试试这个示例代码

uses
  DBXJSON,
  System.SysUtils;


Const
StrJson=
'{' +
'    "response": {' +
'        "distributor": {' +
'            "id": 1538,' +
'            "name": "Arrow Electronics",' +
'            "authorized": true,' +
'            "logoUrl": "this is normally a URL but I cut it out"' +
'        },' +
'        "parts": [' +
'            {' +
'                "manufacturer": "National Semiconductor",' +
'                "part": "LM741WG/883",' +
'                "description": "OP Amp Single GP ±22V 10-Pin CFPAK Tray",' +
'                "price": [' +
'                    {' +
'                        "quantity": 0,' +
'                        "price": 65,' +
'                        "currency": "USD"' +
'                    }' +
'                ],' +
'                "stock": 88,' +
'                "lastUpdated": "2013-11-04 18:27:16 UTC"' +
'            },' +
'            {' +
'                "manufacturer": "National Semiconductor",' +
'                "part": "LM741W/883",' +
'                "description": "OP Amp Single GP ±22V 10-Pin CPAK Rail",' +
'                "price": [' +
'                    {' +
'                        "quantity": 0,' +
'                        "price": 40.5,' +
'                        "currency": "USD"' +
'                    }' +
'                ],' +
'                "stock": 1464,' +
'                "lastUpdated": "2013-11-04 18:27:16 UTC"' +
'            },' +
'            {' +
'                "manufacturer": "Texas Instruments",' +
'                "part": "LM741CH",' +
'                "description": "OP Amp Single GP ±18V 8-Pin TO-99 Box",' +
'                "price": [' +
'                    {' +
'                        "quantity": 0,' +
'                        "price": 5.22,' +
'                        "currency": "USD"' +
'                    }' +
'                ],' +
'                "stock": 95,' +
'                "lastUpdated": "2013-11-04 18:27:16 UTC"' +
'            }' +
'        ]' +
'    }' +
'}';

procedure ParseJson;
var
  LJsonObj  : TJSONObject;
  LRoot, LParts    : TJSONValue;
  LPart     : TJSONValue;
  LItem, LPrice     : TJSONValue;
  LIndex    : Integer;
  LSize     : Integer;
begin
    LJsonObj    := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(StrJson),0) as TJSONObject;
  try
     //get the root element
     LRoot:=LJsonObj.Get('response').JsonValue;
     // get the "parts" element
     LParts:=TJSONObject(LRoot).Get('parts').JsonValue;


     LSize:=TJSONArray(LParts).Size;
     //iterate over the "parts"
     for LIndex:=0 to LSize-1 do
     begin
      //extract the value of each pair
      LPart    := TJSONArray(LParts).Get(LIndex);
      LItem:=TJSONObject(LPart).Get('manufacturer').JsonValue;
      Writeln(Format('%s : %s',['manufacturer', LItem.Value]));
      LItem:=TJSONObject(LPart).Get('part').JsonValue;
      Writeln(Format('%s : %s',['part', LItem.Value]));
      LItem:=TJSONObject(LPart).Get('description').JsonValue;
      Writeln(Format('%s : %s',['description', LItem.Value]));

      //the price is an array, so we need a little more of work
      LItem:=TJSONObject(LPart).Get('price').JsonValue;
      LPrice:=TJSONObject(TJSONArray(LItem).Get(0)).Get('quantity').JsonValue;
      Writeln(Format('  %s : %s',['quantity', LPrice.Value]));

      LPrice:=TJSONObject(TJSONArray(LItem).Get(0)).Get('price').JsonValue;
      Writeln(Format('  %s : %s',['price', LPrice.Value]));

      LPrice:=TJSONObject(TJSONArray(LItem).Get(0)).Get('currency').JsonValue;
      Writeln(Format('  %s : %s',['currency', LPrice.Value]));

      LItem:=TJSONObject(LPart).Get('stock').JsonValue;
      Writeln(Format('%s : %s',['stock', LItem.Value]));
      LItem:=TJSONObject(LPart).Get('lastUpdated').JsonValue;
      Writeln(Format('%s : %s',['lastUpdated', LItem.Value]));
      Writeln;
     end;
  finally
     LJsonObj.Free;
  end;
end;

begin
  try
    ParseJson;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

【讨论】:

  • 谢谢谢谢!你是完全正确的,这完全有效。用完其他人怀疑的问题也是正确的...我试图在不遍历 JSON 对象的层次结构的情况下获取数据 此代码很好地解释了问题所在,并且很有效!我欠你一个喜力的伙伴。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多