4

New to the forums so apologies if my posts are not well formatted or following the guidelines. I'll 'get it' quickly. So here's my issue. Have a look at the code below. I have removed almost all of the extranneous bits to focus attention on one key line --

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

I have some JSON formatted data along the top (Const) that has been tested to be valid. When I attempt to parse it, it fails at run time (compile time is fine). I've reduced all of this to something smaller and more manageable to deal with.

When I launch this in the debugger, it all seems valid, yet even having added tests for Nil values doesn't yield much in my understanding of the problem.

I'm hoping someone knows what the issue might be. Here's the code snippet:

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.

Thank you again and thanks for being patient with me.

Kind Regards,

EEJoe

2
  • What line does it fail on? The one you singled out at the top? Are you sure ParseJSONValue and Get('parts') didn't return null? Commented Nov 5, 2013 at 0:00
  • 1
    The top level object doesn't have a parts property so Get('parts') is likely returning nil. Try something like LJsonObj.Get('response').Get('parts') instead. Commented Nov 5, 2013 at 0:06

1 Answer 1

4

The code which you are using to parse the JSON response is not related to the structure of your JSON string. First recommendation is read the JSON documentation, is very easy to understand.

Try this sample code with comments

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.
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you thank you! You're completely right and this totally works. It runs out that what others suspected was the issue is also right...I was trying to get data without traversing the hierarchy of the JSON objects This code does a great job of explaining where that issue was and works a treat! I owe you a Heineken mate. Many thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.