direktor05 2 Posted November 20, 2022 Hello, How do I parse this Json: {"result": [{ "animals": [{ "id":1, "name": So.... I parse Json first: jsonobject := TJsonObject.ParseJSONValue(RestResponse.Content) as TJsonObject; Then I get to "animals":[{"id".... now here gets complicated. How do I parse further to get ID and name? Parse Json further or parse Json Array? Can someone help with some example code please? Share this post Link to post
direktor05 2 Posted November 20, 2022 Full Json: {"result": [{ "animals": [{ "id":1, "name":"pig", } ] } ] } Share this post Link to post
ertank 27 Posted November 20, 2022 (edited) Hello, Your "complete" json is not valid. You should edit your post and fix it. There are more than one way to solve this. Below is an example with a lot of error checks. type TAnimal = record id: Integer; name: string; end; TAnimalList = TArray<TAnimal>; //----------------------------------- implementation //----------------------------------- uses System.JSON, System.Generics.Collections; const JsonString = '{"result":[{"animals":[{"id":1,"name":"pig"}]}]}'; function ParseAnimalsJson(const Json: string; out AnimalList: TAnimalList): Boolean; var LTestJsonValue: TJSONValue; LJson: TJSONValue; LJsonArrayResult: TJSONArray; LJsonArrayAnimals: TJSONArray; I: Integer; begin LTestJsonValue := TJSONObject.ParseJSONValue(Json, False, False); if LTestJsonValue = nil then begin Exit(False); end; try LJson := LTestJsonValue.FindValue('result'); if LJson = nil then Exit(False); if not (LJson is TJSONArray) then Exit(False); LJsonArrayResult := LJson as TJSONArray; if LJsonArrayResult.Count = 0 then Exit(False); LJson := LJsonArrayResult[0].FindValue('animals'); if LJson = nil then Exit(False); if not (LJson is TJSONArray) then Exit(False); LJsonArrayAnimals := LJson as TJSONArray; SetLength(AnimalList, LJsonArrayAnimals.Count); for I := 0 to LJsonArrayAnimals.Count-1 do begin LJson := LJsonArrayAnimals[I].FindValue('id'); if LJson = nil then Exit(False); AnimalList[I].id := LJson.AsType<Integer>; LJson := LJsonArrayAnimals[I].FindValue('name'); if LJson = nil then Exit(False); AnimalList[I].name := LJson.AsType<string>; end; finally LTestJsonValue.Free(); end; Result := True; end; procedure TForm1.Button1Click(Sender: TObject); var List: TAnimalList; begin if ParseAnimalsJson(JsonString, List) then begin ShowMessage('Parse completed'); end else begin ShowMessage('Parse failed!'); end; end; Edited November 20, 2022 by ertank Share this post Link to post
p-samuel 2 Posted November 20, 2022 (edited) Do you know about https://jsontodelphi.com/ website? If you are in a hurry then go there generate your classes dto's. Copy and past your json string and they will generate a dto boilerplate for you. The only problem is that this boilerplate uses generics and cannot be implemented in old versions of Delphi. Otherwise, check out Super Object in github project that is aimed for these cases. Edited November 20, 2022 by p-samuel Share this post Link to post
aehimself 396 Posted November 20, 2022 15 hours ago, direktor05 said: Then I get to "animals":[{"id".... now here gets complicated. How do I parse further to get ID and name? Parse Json further or parse Json Array? Can someone help with some example code please? Let's say you have a TJSONObject variable which holds the inmost object only (id and name) named innerjson: if innerjson.GetValue('id') <> null then fid := (innerjson.GetValue('id') As TJSONNumber).AsLargeInt; if innerjson.GetValue('name') <> null then fname := (innerjson.GetValue('name') As TJSONString).Value; if you are sure that these will always be present, you can discard the nullcheck. Share this post Link to post
David Schwartz 427 Posted November 21, 2022 If you create a class for this, then there's a method that can theoretically create an instance of it and fill it from a chunk of JSON data: var data_obj := TJson.JsonToObject<TMyObj>( req.Response ); In this case, the JSON data would go into a class TMyObj, which is the type returned in data_obj. I've used it for simple objects, but I'm not sure how it would handle lists and arrays. BTW, that JSON has an error in it -- a dangling comma Share this post Link to post
Lars Fosdal 1792 Posted November 21, 2022 On 11/20/2022 at 1:00 PM, p-samuel said: Do you know about https://jsontodelphi.com/ website? That is interesting code. How is the performance? Share this post Link to post
Clément 148 Posted November 21, 2022 There are a few things to resolve before getting to "animal id". This is just an example using Delphi 11, but older version should work too. (Might need to remove the inline variable). This is how I would do it: unit Unit94; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.JSON; type TForm94 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } const _JSON = ' {"result": [{ "animals": [{ "id":1, "name":"pig" } ] } ] }'; public { Public declarations } end; var Form94: TForm94; implementation {$R *.dfm} procedure TForm94.Button1Click(Sender: TObject); var lJsResult : TJsonObject; lJsResultArray : TJsonArray; lJsAnimals : TJsonObject; lJsAnimalArray : TJsonArray; lJsAnimal : TJsonObject; lId : Integer; lname : String; begin lJsResult := TJSONObject.ParseJSONValue(_JSON) as TJsonObject; try if lJsResult.TryGetValue<TJsonArray>('result', lJsResultArray) then begin for var r := 0 to lJsResultArray.Count-1 do begin lJsAnimals := lJsResultArray.Items[r] as TJsonObject; lJsAnimalArray := lJsAnimals.GetValue<TJsonArray>('animals'); for var i := 0 to lJsAnimalArray.Count-1 do begin lJsAnimal := lJsAnimalArray.Items[i] as TJSONObject; if not lJsAnimal.TryGetValue<Integer>('id', lId ) then raise Exception.Create('No "ID" Field'); if not lJsAnimal.TryGetValue<String>('name', lname) then raise Exception.Create('No "name" Field'); // DO something with lId, and name end; end; end finally lJsResult.Free; end; end; Share this post Link to post
eddie Alves 0 Posted November 21, 2022 (edited) use this object, very simple: https://github.com/hgourvest/superobject Ex: Function ... var jsonPedido : ISuperObject; begin jsonPedido := SO(aPedido); if jsonPedido.Count > 0 then begin idPedido := jsonPedido.S['codigo']; merchanId := IntToStr(jsonPedido.I['idLoja']); totalPrice := jsonPedido.F['valorCorrigido']; pedidoCreatAt := jsonPedido.D['data']; idContato := IntToStr(jsonPedido.O['cliente'].I['id']); end; end; Edited November 21, 2022 by eddie Alves Share this post Link to post