Recent

Author Topic: Pegar itens de objeto dentro do json  (Read 3156 times)

Johnny Walker Junior

  • New member
  • *
  • Posts: 7
Pegar itens de objeto dentro do json
« on: April 27, 2024, 03:24:05 am »
Alguém poderia fala-me como poderia resolver a questão de pegar um elemento de outro objeto dentro do json?

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button22Click(Sender: TObject);
  2. var
  3.    Data, Result, Return: TJSONData;
  4.    I: Integer;
  5. begin
  6.    // json validado
  7.    Data := GetJSON('{"success":true,"message":"returned sucess","data":"[{\"id\":1, \"cpf\":\"99999890667\", \"name\":\"johnny\"}]"}');
  8.  
  9.    // access violation
  10.    //Result := Data.findpath('data').Items[0].FindPath('id');
  11.    // consigo recuperar o objeto de data
  12.    // {\"id\":1, \"cpf\":\"99999890667\", \"name\":\"johnny\"}]"}
  13.    Result := Data.FindPath('data');
  14.    try
  15.      if Assigned(Result) then
  16.      begin
  17.         //Return := Result.Items[0].FindPath('id');
  18.         Return := Result.Items[0];
  19.         if Return <> nil then;
  20.         begin
  21.            // access violation
  22.            //Result.FindPath('id').AsString;
  23.            //Return.FindPath('data[0].id').AsString;
  24.            Memo1.Clear;
  25.            Memo1.Text :=  Result.AsJSON;
  26.         end;
  27.      end;
  28.    finally
  29.      Data.Free;
  30.    end;
  31. end;  
       


Como vêm, consigo recuperar o objeto data, mas não estou compreendendo pegar os elementos internos a ele e seus respectivos valores.


bye

TRon

  • Hero Member
  • *****
  • Posts: 2801
Re: Pegar itens de objeto dentro do json
« Reply #1 on: April 27, 2024, 04:58:11 am »
Apologies for replying in English (my Portuguese is non-existent).

First of all there is an issue with your original JSON string, at least when reviewing how you tried to access the individual fields. The data item is 'defined' in the JSON as a string while your code seem to suggest it is an array which contains a single object that has individual items.

On top of that the quotes inside that string are escaped. I suspect that something did go wrong with the conversion of the retrieved JSON converting it to a string.

Code: Pascal  [Select][+][-]
  1. procedure dodo;
  2. var
  3.   JSON, DataArray, DataItem: TJSONData;
  4.   id: integer;
  5.   cpf: string;
  6.   ids: string;
  7. begin
  8. // comment out wrong escaped JSON string
  9. //  JSON := GetJSON('{"success":true,"message":"returned sucess","data":"[{\"id\":1, \"cpf\":\"99999890667\", \"name\":\"johnny\"}]"}');
  10.  
  11.   JSON := GetJSON('{"success":true,"message":"returned sucess","data": [ { "id":1, "cpf": "99999890667", "name":"johnny" } ]}');
  12.   try
  13.     // retrieve array
  14.     DataArray := JSON.FindPath('data');
  15.     // retrieve first item in the array
  16.     DataItem  := DataArray.Items[0];
  17.     // or directly, using:
  18.     DataItem  := JSON.FindPath('data[0]');
  19.  
  20.     id := DataItem.Items[0].Value;
  21.     cpf := DataItem.Items[1].Value;
  22.     // or directly using:
  23.     id := JSON.FindPath('data[0].id').Value;
  24.     cpf := JSON.FindPath('data[0].cpf').Value;
  25.     // to convert:
  26.     ids := JSON.FindPath('data[0].id').AsString;
  27.   finally
  28.     JSON.Free;
  29.   end;
  30. end;
  31.  

PS: Note that even when the items inside the data entry are wrongly defined as a string, that you can work around it by reading the string and feeding that to the GetJSON function again. However, that really isn't how JSON is suppose to work.
« Last Edit: April 27, 2024, 05:32:59 am by TRon »

Johnny Walker Junior

  • New member
  • *
  • Posts: 7
Re: Pegar itens de objeto dentro do json
« Reply #2 on: April 27, 2024, 03:27:48 pm »
Thank you very much friend, as I had been scratching my head about this for some time.
I even thought about using a TJSONArray type, but I couldn't find an example that satisfied this curiosity.
Usually, I use json4delphi in lazarus, but I was learning the native json.


Could you tell-me if exist a setting to avoid json come escaped ?

bye
« Last Edit: April 27, 2024, 03:56:22 pm by Johnny Walker Junior »

TRon

  • Hero Member
  • *****
  • Posts: 2801
Re: Pegar itens de objeto dentro do json
« Reply #3 on: April 27, 2024, 04:26:03 pm »
Could you tell-me if exist a setting to avoid json come escaped ?
How did you retrieve that JSON string ? e.g. where does it originates from ?

If the JSON string is a result of some use of API (whether it be local or internet) then something did go wrong with the use of that API.

In case it is you yourself who created that string (using fpjson or otherwise) then the string was (also) not generates as JSON intended it to be.

Ergo, without knowing the origin of the JSON string it is hard to tell what can be done to actually try and 'fix' it.

Johnny Walker Junior

  • New member
  • *
  • Posts: 7
Re: Pegar itens de objeto dentro do json
« Reply #4 on: April 27, 2024, 08:36:29 pm »
I use Horse framework to do the API.
From this link:
https://github.com/HashLoad/horse

TRon

  • Hero Member
  • *****
  • Posts: 2801
Re: Pegar itens de objeto dentro do json
« Reply #5 on: April 28, 2024, 08:43:54 am »
I use Horse framework to do the API.
Thank you for the link.

As far as I am able to tell Horse uses the standard (free Pascal) fpjson units. I am unable to detect where this might have gone wrong.

Are you perhaps able to share an example that produces that resulting JSON string for you ?

At first glance (of the original issue) it seems that someone is trying to merge two different JSON strings (or objects) into one and which went wrong somehow. Do note that I am aware that some servers are able to provide a similar JSON response string but in such case they are also using JSON in a manner that isn't suppose to be used that way :)


edit:
A small example that is hopefully be able to show how things can go wrong (note that it is a console program but it can easily be adapted to work with a GUI application with Lazarus just remove/replace the writeln's or start Lazarus from a terminal window):
Code: Pascal  [Select][+][-]
  1. program produce;
  2.  
  3. {$mode objfpc}{$h+}
  4.  
  5. uses
  6.   classes, fpjson;
  7.  
  8. procedure dodo;
  9. var
  10.   Root : TJSONObject;
  11.   Data : TJSOnArray;
  12.   Item : TJSONObject;
  13.   done_wrong: boolean = true;
  14.  
  15.   item_as_string : string;
  16.   data_as_string : string;
  17.   root_as_string : string;
  18. begin
  19.   // create root node
  20.   Root := TJSONObject.Create;
  21.  
  22.   // add some items to root node
  23.   Root.Add('success', true);
  24.   Root.Add('message', 'returned success');
  25.  
  26.   // create data array
  27.   Data := TJSONArray.Create;
  28.  
  29.   // create array item
  30.   Item := TJSONObject.Create;
  31.   // add items to object item
  32.   Item.Add('id', 1);
  33.   Item.Add('cpf', '99999890667');
  34.   Item.Add('name', 'Johnny');
  35.   writeStr(item_as_string, 'item = ', Item.AsJSON);
  36.  
  37.   // add array item to array
  38.   if done_wrong
  39.     then Data.Add(Item.AsJSON)          // <--- this is wrong (add Item as JSON string)
  40.     else Data.Add(Item);                // <--- this is good (add item as JSON array)
  41.   writeStr(data_as_string, 'data = ', Data.AsJSON);
  42.  
  43.   // add data array to root node
  44.   Root.Add('data', Data);
  45.   writeStr(root_as_string, 'root = ', Root.AsJSON);
  46.  
  47.   if done_wrong then Item.Free;
  48.   Root.Free;
  49.  
  50.   // if on console: (else replace with writing to a memo or set caption of labels)
  51.   writeln(item_as_string);
  52.   writeln(data_as_string);
  53.   writeln(root_as_string);
  54. end;
  55.  
  56. begin
  57.   dodo;
  58. end.
  59.  

When gone_wrong boolean is set to true:
Code: [Select]
item = { "id" : 1, "cpf" : "99999890667", "name" : "Johnny" }
data = ["{ \"id\" : 1, \"cpf\" : \"99999890667\", \"name\" : \"Johnny\" }"]
root = { "success" : true, "message" : "returned success", "data" : ["{ \"id\" : 1, \"cpf\" : \"99999890667\", \"name\" : \"Johnny\" }"] }

Also note that even if this comes close to your original JSON string this examples does not (even) encapsulate the array itself between quotes.

When gone_wrong boolean is set to false:
Code: [Select]
item = { "id" : 1, "cpf" : "99999890667", "name" : "Johnny" }
data = [{ "id" : 1, "cpf" : "99999890667", "name" : "Johnny" }]
root = { "success" : true, "message" : "returned success", "data" : [{ "id" : 1, "cpf" : "99999890667", "name" : "Johnny" }] }
Which is how the JSON string should look like.
« Last Edit: April 28, 2024, 09:42:44 am by TRon »

Johnny Walker Junior

  • New member
  • *
  • Posts: 7
Re: Pegar itens de objeto dentro do json
« Reply #6 on: April 28, 2024, 11:08:23 pm »
I was using this YouTube channel below to learn about this framework, it has English subtitles, so there is no problem understanding what the person is saying.
In the case of the server in console mode, there is no problem, I also run it in console.

https://www.youtube.com/@Alexandre_amds/videos

Thank you very much my friend


bye

TRon

  • Hero Member
  • *****
  • Posts: 2801
Re: Pegar itens de objeto dentro do json
« Reply #7 on: April 29, 2024, 04:38:24 pm »
I was using this YouTube channel below to learn about this framework, it has English subtitles, so there is no problem understanding what the person is saying.
Unfortunately the only subtitle language I am able to see are Portuguese  :'(

But... it is currently unclear to me if you still have this problem or that you were able to get it solved.

Johnny Walker Junior

  • New member
  • *
  • Posts: 7
Re: Pegar itens de objeto dentro do json
« Reply #8 on: April 29, 2024, 09:53:20 pm »
My friend it's possible to translate to English, just turn on "subtitles/cc" and "automatically translate" to the specified language.


bye

TRon

  • Hero Member
  • *****
  • Posts: 2801
Re: Pegar itens de objeto dentro do json
« Reply #9 on: April 30, 2024, 02:48:09 am »
My friend it's possible to translate to English, just turn on "subtitles/cc" and "automatically translate" to the specified language.
Yes, I am aware of that but are you aware how terrible auto-translate works (or actually not works  :) ) ?

But it is also a bit besides the point.

I had a look at the framework and I understand the concepts that are used as well as the implementation.

The part were things seem to go wrong is when the framework is applied in practice. Ergo, the end-user who made use of the framework made a mistake somewhere along the line which resulted in that JSON string.

I am unable to replicate that because I am not the person who created the code and I will not be able to make that exact same mistake because I understand how JSON works (famous last words  :) ).

That is why I posted an example using fpjson (which the Horse Framework can use as well) that is able to produce such 'faulty' JSON strings. I did that in the hopes that you perhaps are able to recognize the (faulty) pattern so that you are able to figure out where things go wrong for you.

It is also (still) unclear for me if you are creating the 'faulty' JSON string yourself and if so whether or not that was done locally or if the faulty JSON string is produced by a server (and in case the latter if you coded the server yourself or if you retrieved that faulty JSON string from an external server that is written by someone else)

So, I actually have more questions than I have answers, I am afraid...    :-\

Johnny Walker Junior

  • New member
  • *
  • Posts: 7
Re: Pegar itens de objeto dentro do json
« Reply #10 on: May 01, 2024, 04:50:12 pm »
Unfortunately the translation is not accurate, but at least you can understand the context. I watch a lot of videos in English and I know that sometimes the translation gets completely lost.

The framework does not restrict you from using json, it works with middlewares that does this, but you are not obliged to have them, as you can work natively.
The good thing is that this framework works in both Lazarus and Delphi.

Here's an example that you might find interesting:
Here's the developer's github:
https://github.com/IagooCesaar/horse-store

Hasload horse developers channel:
https://www.youtube.com/@HashLoad
« Last Edit: May 01, 2024, 05:23:04 pm by Johnny Walker Junior »

TRon

  • Hero Member
  • *****
  • Posts: 2801
Re: Pegar itens de objeto dentro do json
« Reply #11 on: May 01, 2024, 07:19:16 pm »
Unfortunately the translation is not accurate, but at least you can understand the context. I watch a lot of videos in English and I know that sometimes the translation gets completely lost.
Yes, i do understand the context but i got the same from reading the code (which is much faster than watching video's  ;D )

[quote
The framework does not restrict you from using json, it works with middlewares that does this, but you are not obliged to have them, as you can work natively.
[/quote]
Yes, I am also aware of that but I was/am focusing on the JSON part(s) as that is where your issue seem to originate from.

As I like to say: not guts, no glory  :) (meaning that I can only help when there is some actual code)

Johnny Walker Junior

  • New member
  • *
  • Posts: 7
Re: Pegar itens de objeto dentro do json
« Reply #12 on: May 01, 2024, 08:48:00 pm »
Don't worry my friend, your last code was very enlightening, because I understood the reason for my error, which was I used the json object as a string type and that was precisely what caused the problem.
In this case, I just have to thank you.

 

TinyPortal © 2005-2018