Lazarus

Programming => General => Topic started by: maurobio on September 16, 2021, 10:01:42 pm

Title: [SOLVED] Access violation in JSON data
Post by: maurobio on September 16, 2021, 10:01:42 pm
Dear ALL,

Could someone explain to me why the piece of code below fail with a dreadful 'Access violation' message? The JSON data it gets is valid (see attached zip file).

Code: Pascal  [Select][+][-]
  1. program test_gbif;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses SysUtils, fphttpclient, fpjson, jsonparser;
  6.  
  7. const
  8.         url = 'https://api.gbif.org/v1/species?name=';
  9.         searchStr = 'Myrcia lingua';
  10.  
  11. var
  12.   jData, jItem, jItems: TJSONData;
  13.   scientificname, status, valid_name, taxon_list: string;
  14.  
  15. begin
  16.   jData := GetJSON(TFPHTTPClient.SimpleGet(url + StringReplace(searchStr, ' ', '%20', [rfReplaceAll])));
  17.   jItems := jData.FindPath('results');
  18.   jItem := jItems.Items[0]; // Just want the first result
  19.   scientificname := jItem.FindPath('scientificname').AsString;
  20.   status := jItem.FindPath('taxonomicStatus').AsString;
  21.   valid_name := jItem.FindPath('accepted').AsString;
  22.   taxon_list := jItem.FindPath('kingdom').AsString + '; ' +
  23.         jItem.FindPath('phylum').AsString + '; ' +
  24.         jItem.FindPath('class').AsString + '; ' +
  25.         jItem.FindPath('order').AsString + '; ' +
  26.         jItem.FindPath('family').AsString;
  27.   jData.Free;
  28. end.
  29.  
  30.  
Thanks in advance for any assistance you can provide.

With best wishes,
Title: Re: Access violantion in JSON data
Post by: Gustavo 'Gus' Carreno on September 16, 2021, 10:20:58 pm
Boas Maurobio,

I don't know if you're aware, but if FindPath doesn't find the path you asked for, it will return a nil.

Instead of blindly just assume that all the paths that you are seeking exist, you should first test if the result of FindPath is not nil.

I haven't tested with the specific data you presented, but I'm assuming that the Access Violation error is because you're trying to do something with a variable that contains nil.

Hope this helps!!

Grande abraço,
Gus
Title: Re: Access violantion in JSON data
Post by: maurobio on September 16, 2021, 10:33:00 pm
@Gus,

Thanks for your answer. Sure, I had presumed that the access violation is because a nil value is being returned - but why, that's my question! :o The JSON data returned is perfectly valid (and in fact relatively simple).

With best wishes,
Title: Re: Access violantion in JSON data
Post by: maurobio on September 16, 2021, 10:47:10 pm
Hi,

Just to present a possible solution...

The piece of code below, which uses the JsonTools library (https://www.getlazarus.org/json/ (https://www.getlazarus.org/json/)) works fine:

Code: Pascal  [Select][+][-]
  1. program gbif_example;
  2.  
  3. uses SysUtils, fphttpclient, JsonTools;
  4.  
  5. const
  6.         url = 'https://api.gbif.org/v1/species?name=';
  7.         searchName = 'Myrcia lingua';
  8.  
  9. var
  10.   rawJson: AnsiString;
  11.   JsonData: TJsonNode;
  12.   scientificname, status, valid_name, taxon_list: string;
  13.  
  14. begin
  15.   WriteLn('Searching for: ' + searchName);
  16.   // Get the JSON data
  17.   JsonData := TJsonNode.Create;
  18.   rawJson := TFPHTTPClient.SimpleGet(url + StringReplace(searchName, ' ', '%20', [rfReplaceAll]));
  19.   JsonData.Parse(rawJson);
  20.   scientificname := JsonData.Find('results/0/scientificName').AsString;
  21.   status := JsonData.Find('results/0/taxonomicStatus').AsString;
  22.   valid_name := JsonData.Find('results/0/accepted').AsString;
  23.   taxon_list := JsonData.Find('results/0/kingdom').AsString + '; ' +
  24.         JsonData.Find('results/0/phylum').AsString + '; ' +
  25.         JsonData.Find('results/0/class').AsString + '; ' +
  26.         JsonData.Find('results/0/order').AsString + '; ' +
  27.         JsonData.Find('results/0/family').AsString;    
  28.   JsonData.Free;
  29.   WriteLn(scientificname);
  30.   WriteLn(status);
  31.   WriteLn(valid_name);
  32.   WriteLn(taxon_list);
  33. end.
  34.  
In general, I have been using JsonTools instead of the JSON parsing libraries included with FPC/Lazarus. According to comparisons presented by its author (https://www.getlazarus.org/json/tests/ (https://www.getlazarus.org/json/tests/)), that library is even more efficient.

With best wishes,
Title: Re: Access violantion in JSON data
Post by: Gustavo 'Gus' Carreno on September 16, 2021, 10:47:40 pm
Boas Maurobio,

I had a look at the JSON returned from the link in your code and I think I know the issue:

The member in the returned JSON is scientificName but you're asking for scientificname.

I might be wrong, cuz I haven't confirmed it with code, but if I'm not mistaken, JSON is case sensitive, well, at least the fpjson implementation.

So if you make sure that all the members are correctly capitalized, I'm guessing that your code will run without a hitch ;)

In order to minimize these issues and to make simple changes easier, I tend to have all the member names in constants:
Code: Pascal  [Select][+][-]
  1. const
  2.   cJSONScientificName = 'scientificName';
  3.  
  4. scientificname := jItem.FindPath(cJSONScientificName).AsString;

This way if I have to use the same member more than once, I don't have to make sure if I made a typo, cuz I'll use the auto-completion of Lazarus to complete the constant name.

Grande abraço,
Gus
Title: Re: Access violantion in JSON data
Post by: Gustavo 'Gus' Carreno on September 16, 2021, 10:52:48 pm
Boas Maurobio,

Code: Pascal  [Select][+][-]
  1. program gbif_example;
  2.   scientificname := JsonData.Find('results/0/scientificName').AsString;
  3. end.

You've just confirmed my suspicions of the case sensitive nature of JSON!!!

If you look at the piece of code above, you have the correct capitalization of scientificName, but you have the wrong one on the piece of code on your first post.

Try to use string constants for the members, instead of string literals. For me the ability to use the auto-complete on Lazarus is really worth it for these small bugs!!

Hope this solves your problem!!

Grande abraço,
Gus
Title: Re: Access violantion in JSON data
Post by: Bart on September 16, 2021, 11:02:04 pm
After fixing the casing in scientificName I get:
valid_name=Myrcia guianensis (Aubl.) DC.
taxon_list=Plantae; Tracheophyta; Magnoliopsida; Myrtales; Myrtaceae

Hope this is what you expected.

Bart
Title: Re: [SOLVED] Access violation in JSON data
Post by: maurobio on September 16, 2021, 11:25:37 pm
@Gus, @Bart,

That is it! I did not pay attention to the fact that JSON is, in fact, case-sensitive.

Thank you very much for your time and patience!

With best wishes,
Title: Re: [SOLVED] Access violation in JSON data
Post by: Gustavo 'Gus' Carreno on September 16, 2021, 11:31:57 pm
Boas Maurobio,

Thank you very much for your time and patience!

You're more than welcome!!

Grande abraço,
Gus
TinyPortal © 2005-2018