I’m trying to use Gnatcoll.Json
to parse a JSON document. I discovered that I can do the following to parse JSON (which is pretty great) (i.e., the following parses the sPDX license list as an example):
with Gnatcoll.JSON; use Gnatcoll.JSON;
-- ...
procedure Build_License_List is new Gen_Map_JSON_Object(License_List);
procedure Build_License_List_Data is new Gen_Map_JSON_Object(License_List_Data);
Then you can parse the JSON like so:
procedure Construct_License_List_Data(data: in out License_List_Data; Name: UTF8_String; Value: Json_Value);
procedure Construct_License_List(list: in out License_List; Name: UTF8_String; Value: Json_Value) is
Tmp_License: aliased License_List_Data;
begin
if Name = "licenseListVersion" then
list.Version := Value.Get;
elsif name = "licenses" then
Build_License_List_Data(Value, Construct_License_List_Data'Access, Tmp_License);
list.licenses.append(tmp_license);
else
return;
end if;
end Construct_License_List;
procedure Construct_License_List_Data(data: in out License_List_Data; Name: UTF8_String; Value: Json_Value) is
begin
if name = "reference" then
data.Reference := Value.Get;
elsif name = "isDeprecatedLicenseId" then
data.Deprecated := Value.Get;
elsif name = "detailsUrl" then
data.details_url := Value.Get;
elsif name = "referenceNumber" then
Data.Reference_Number := Value.Get;
elsif name = "name" then
data.Name := value.get;
elsif name = "licenseId" then
data.id := value.get;
elsif name = "seeAlso" then
for link in 1 .. Gnatcoll.Json.Length(value.get) loop
data.see_also.append(get(value.get, link).get);
end loop;
elsif name = "isOsiApproved" then
data.osi_approved := value.get;
else
return;
end if;
end Construct_License_List_Data;
Then you build the root by calling Build_License_List(value, Construct_License_List'Access, Licenses_object)
. The problem is that I’m getting a constraint error when I run this app:
raised CONSTRAINT_ERROR : gnatcoll-json.adb:1802 discriminant check failed
[test.exe]
0x7ff60b0c5123 gnatcoll__json__utility__escape_string at ???
0x7ff60b64ae66 Test.Build_License_List.Internal at gnatcoll-json.adb:1833
0x7ff60b64b047 Test.Build_License_List.Internal at nvpm.adb:43
0x7ff60b64ae09 Test.Build_License_List.Internal at gnatcoll-json.adb:1829
0x7ff60b0c5003 gnatcoll__json__utility__escape_string at ???
0x7ff60b64add6 Test.B2215b at gnatcoll-json.adb:1833
0x7ff60b648ff1 Test at test.adb:88
0x7ff60b64a8dc Test at b__test.adb:1354
0x7ff60b0b133e __tmainCRTStartup at ???
0x7ff60b0b1144 mainCRTStartup at ???
[C:\Windows\System32\KERNEL32.DLL]
0x7ffe9bb77372
[C:\Windows\SYSTEM32\ntdll.dll]
0x7ffe9bcbcc8f
This is really weird, because the code looks fine to me when I look at the generic code:
---------------------
-- Map_JSON_Object --
---------------------
procedure Map_JSON_Object
(Val : JSON_Value;
CB : access procedure (Name : UTF8_String; Value : JSON_Value))
is
use Object_Items_Pkg;
C : Cursor := Val.Data.Obj_Value.Vals.First;
begin
while Has_Element (C) loop
CB (To_String (Key (C)), Element (C));
Next (C);
end loop;
end Map_JSON_Object;
---------------------
-- Map_JSON_Object --
---------------------
procedure Gen_Map_JSON_Object
(Val : JSON_Value;
CB : access procedure
(User_Object : in out Mapped;
Name : UTF8_String;
Value : JSON_Value);
User_Object : in out Mapped)
is
procedure Internal (Name : UTF8_String; Value : JSON_Value);
--------------
-- Internal --
--------------
procedure Internal (Name : UTF8_String; Value : JSON_Value) is
begin
CB (User_Object, Name, Value);
end Internal;
begin
Map_JSON_Object (Val, Internal'Access);
end Gen_Map_JSON_Object;
Is this a bug in Gnat, a bug in gnatcoll (I’m using version 24) or am I doing something wrong? Am I not supposed to use this API?