0

How do I parse the following Json in Delphi?

This is my first post, and I've taken care to search as much as I can before asking this question, so please kindly let me know if I posted wrongly in any way.

I would like to get the value of "name_of_centre" in the "records" array

Thank you for any kind assistance.

procedure TForm1.Button1Click(Sender: TObject);
var
  i : integer;
  jsonRoot: TJSONValue;
  jsonObj: TJSONObject;
  jsonArr: TJSONArray;
begin
  jsonRoot := TJSONObject.ParseJSONValue(memo2.Lines.text);
  try
    jsonObj := jsonRoot as TJSONObject;
    jsonObj := jsonObj.GetValue('result') as TJSONObject;
    jsonArr := jsonObj.GetValue('records') as TJSONArray;
    showmessage( jsonArr.Count.ToString );  // works ok

    for i := 0 to jsonArr.Count - 1 do
    begin
      jsonObj := jsonArr.Items[i] as TJSONObject;
      showmessage( jsonObj.GetValue('name_of_centre').Value );   // error here
    end;
  finally
    jsonRoot.Free;
  end;
end;

I've checked out Delphi parsing a Json with multiple array types?

How to parse this json data in Delphi 10 Seattle? (especially this one)

and a few other links... but the JSON format seems different.

Any advice?

{
    "help": "testing",
    "success": true,
    "result": {
        "resource_id": "data_resource",
        "fields": [
            {
                "type": "int4",
                "id": "_id"
            },
            {
                "type": "text",
                "id": "name_of_centre"
            },
            {
                "type": "text",
                "id": "location_of_centre"
            },
            {
                "type": "text",
                "id": "type_of_centre"
            },
            {
                "type": "text",
                "id": "owner"
            },
            {
                "type": "numeric",
                "id": "no_of_outlets"
            },
            {
                "type": "numeric",
                "id": "no_of_branches"
            }
        ],
        "records": [
            {
                "location_of_centre": "Kings Road",
                "no_of_outlets": "12",
                "no_of_branches": "0",
                "name_of_centre": "Kings Road Centre",
                "type_of_centre": "HC",
                "owner": "Private",
                "_id": 1
            },
            {
                "location_of_centre": "Queens",
                "no_of_outlets": "14",
                "no_of_branches": "1",
                "name_of_centre": "Queens Centre",
                "type_of_centre": "HC",
                "owner": "Public",
                "_id": 2
            }
        ],
        "_links": {
            "start": "ignore",
            "next": "ignore2"
        },
        "limit": 2,
        "total": 10
    }
}
6
  • 1
    "error here" Would be nice to know what error you're geting. Commented Jun 3, 2020 at 16:07
  • Have you tried GetValue / TryGetValue? It accepts a path to the value. jsonRoot.GetValue<string>('result.records[0].name_of_centre'). But this will get you only single value though. Commented Jun 3, 2020 at 16:09
  • You need to cast to TJSONString before you can access the Value property. Commented Jun 3, 2020 at 16:16
  • @Olivier no, you don't. Value() is a virtual method in the TJSONAncestor base class, and jsonObj.GetValue() returns a TJSONValue that derives from TJSONAncestor. Commented Jun 3, 2020 at 18:38
  • 1
    @PeterWolf I see nothing wrong with this JSON or your code, so it should not be crashing. You are just going to have to debug it to find out what is really happening. Chances are, jsonObj.GetValue('name_of_centre') is returning a nil pointer when it shouldn't be. Commented Jun 3, 2020 at 18:38

1 Answer 1

0

Thanks for the many replies.

Olivier : I've included the error in this amended code.

Peter : I tried using jsonRoot.GetValue('result.records[0].name_of_centre') and it does give me the value of name_of_centre. Good start. But I'm hoping to get this code to give me the number of items in Array and I iterate the array, instead of hard-code. Thanks.

Remy : strangely though, it works today. It doesn't get Invalid Typecast at showmessage( jsonObj.GetValue('name_of_centre').Value );

fpiette : I use Delphi 10.3 RIO.

Thanks to everyone for replying.

Is there a need to use jsonRoot.Free; -- i saw this in a posting on stackoverflow.com... How about jsonObj.Free?

jsonRoot := TJSONObject.ParseJSONValue(memo2.Lines.text);
try
  jsonObj := jsonRoot as TJSONObject;
  jsonObj := jsonObj.GetValue('result') as TJSONObject;
  showmessage( jsonObj.ToString );

  jsonArr := jsonObj.GetValue('records') as TJSONArray;

  showmessage( jsonArr.Count.ToString );

  for i := 0 to jsonArr.Count - 1 do
  begin
    jsonObj := jsonArr.Items[i] as TJSONObject;
    if jsonObj .GetValue('name_of_centre').Value = null then
      showmessage('null');

// previously had an Invalid Typecast showmessage( jsonObj.GetValue('name_of_centre').Value ); end; finally jsonRoot.Free; end;

Sign up to request clarification or add additional context in comments.

2 Comments

"Is there a need to use jsonRoot.Free" - yes. You need to free the TJSONValue that ParseJSONValue() returns when you are done using it. "How about jsonObj.Free?" - no, because it is owned by jsonRoot and will be freed automatically when jsonRoot is freed
Remy, noted with thanks! Much appreciated for all the kind help from everyone.

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.