Delphi / REST / JSON - json

I'm using Delphi Tokyo 10.2 Update 1 and the RESTRequest, RESTResponse and RESTClient components to communicate with a REST server. This is my first attempt with REST/JSON.
I have successfully sent a login request (POST) and received the response expected (a GUID). I then use the GUID to do various other requests (GET). Two of the requests that are made send back an empty file and document JSON template which I then have to populate. This is where I'm stuck. I'm not sure of the best way to update property values in the JSON object.
Here is the empty JSON file template I'm getting back:
{
"boxId": 0,
"changedBy": 0,
"customSort": "",
"dateChanged": "1990-01-01T00:00:00",
"dateStarted": "1990-01-01T00:00:00",
"destruction": "1990-01-01T00:00:00",
"documentCount": 0,
"documents": {
"TotalCount": 0,
"Collection": [
]
},
"extraData": {
"TotalCount": 0,
"Collection": [
]
},
"fieldDefs": {
"TotalCount": 0,
"Collection": null
},
"field": [
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
""
],
"fileId": 0,
"filePtr": 0,
"id": 0,
"isIndexed": false,
"keyValue": "",
"keyVisualValue": "",
"labelPrinted": "1990-01-01T00:00:00",
"lineItems": {
"TotalCount": 0,
"Collection": [
]
},
"notes": "",
"objectType": 5,
"projectId": 0,
"routeInfo": null,
"routingDoc": null,
"remoteId": 0,
"saveNotesOnly": false,
"saveStyle": -999,
"status": 1,
"syncFlag": 0,
"totalDocumentCount": 0,
"viewerContext": 0
}
In Python to populate the first two values in the field property array I simply would do:
inc_filetemplate = json.loads(requests.get(NEWFILE_string).text)
inc_doctemplate = json.loads(requests.get(NEWDOC_string).text)
filetemplate = inc_filetemplate
doctemplate = inc_doctemplate
filetemplate['field'][1] = dcn
filetemplate['field'][2] = batchname
EASY!!!! ;)
What is the best way to do this with Delphi?
I can get the values from the "field" array (first two items in this example which happen to be empty). Just not sure the best way to set the values for those items.
This is what I have started:
procedure PopulateFileTemplate(const AFileTemplate: String);
var
JO: TJSONObject;
JOPair: TJSONPair;
JOArray: TJSONArray;
FieldDCN: String;
FieldBatchName: String;
begin
JO := TJSONObject.ParseJSONValue(AFileTemplate) as TJSONObject;
try
if JO = nil then
begin
MessageDlg('Unable to parse JSON file template.', mtError, [mbOK], 0);
Exit;
end;
JOArray := JO.Get('field').JsonValue as TJSONArray;
FieldDCN := JOArray.Items[0].Value;
FieldBatchName := JOArray.Items[1].Value;
Memo1.Lines.Add('The old value of DCN is: ' + FieldDCN);
Memo1.Lines.Add('The old value of BatchName is: ' + FieldBatchName);
// Best way to set Values here???????
Memo1.Lines.Add('The new value of DCN is: ' + FieldDCN);
Memo1.Lines.Add('The new value of BatchName is: ' + FieldBatchName);
finally
JO.Free;
end;
end;

The TJSONArray.Items[] property returns a TJSONValue, which in your example are TJSONString objects since fields an array of strings.
TJSONArray is actually not designed to allow modifying existing objects in the array. You can add new objects to the end of the array, and remove arbitrary objects from the array, but you cannot insert new objects at arbitrary indexes, or replace existing objects with new objects.
The closest you can get to that kind of functionality is to construct a TList<TJSONValue> with the desired objects in it, and then pass it to TJSONArray.SetElements(). Not ideal.
And TJSONString does not have any methods or properties for editing its string value (except for TJSONString.AddChar()).
You could try using an accessor/helper class to gain access to the protected TJSONString.FStrBuffer member and then edit its content as needed:
type
TJSONStringAccess = class(TJSONString)
end;
procedure SetJSONStringValue(JSONValue: TJSONString; const S: string);
begin
with TJSONStringAccess(JSONValue) do
begin
FStrBuffer.Clear;
FStrBuffer.Append(S);
end;
end;
procedure PopulateFileTemplate(const AFileTemplate: String);
var
JO: TJSONObject;
JOPair: TJSONPair;
JOArray: TJSONArray;
FieldDCN: TJSONString;
FieldBatchName: TJSONString;
begin
JO := TJSONObject.ParseJSONValue(AFileTemplate) as TJSONObject;
if JO = nil then
begin
MessageDlg('Unable to parse JSON file template.', mtError, [mbOK], 0);
Exit;
end;
try
JOArray := JO.Get('field').JsonValue as TJSONArray;
FieldDCN := JOArray.Items[0] as TJSONString;
FieldBatchName := JOArray.Items[1] as TJSONString;
Memo1.Lines.Add('The old value of DCN is: ' + FieldDCN.Value);
Memo1.Lines.Add('The old value of BatchName is: ' + FieldBatchName.Value);
SetJSONStringValue(FieldDCN, '...');
SetJSONStringValue(FieldBatchName, '...');
Memo1.Lines.Add('The new value of DCN is: ' + FieldDCN.Value);
Memo1.Lines.Add('The new value of BatchName is: ' + FieldBatchName.Value);
finally
JO.Free;
end;
end;
type
TJSONStringHelper = helper class for TJSONString
procedure SetValue(const S: string);
end;
procedure TJSONStringHelper.SetValue(const S: string);
begin
Self.FStrBuffer.Clear;
Self.FStrBuffer.Append(S);
end;
procedure PopulateFileTemplate(const AFileTemplate: String);
var
JO: TJSONObject;
JOPair: TJSONPair;
JOArray: TJSONArray;
FieldDCN: TJSONString;
FieldBatchName: TJSONString;
begin
JO := TJSONObject.ParseJSONValue(AFileTemplate) as TJSONObject;
if JO = nil then
begin
MessageDlg('Unable to parse JSON file template.', mtError, [mbOK], 0);
Exit;
end;
try
JOArray := JO.Get('field').JsonValue as TJSONArray;
FieldDCN := JOArray.Items[0] as TJSONString;
FieldBatchName := JOArray.Items[1] as TJSONString;
Memo1.Lines.Add('The old value of DCN is: ' + FieldDCN.Value);
Memo1.Lines.Add('The old value of BatchName is: ' + FieldBatchName.Value);
FieldDCN.SetValue('...');
FieldBatchName.SetValue('...');
Memo1.Lines.Add('The new value of DCN is: ' + FieldDCN.Value);
Memo1.Lines.Add('The new value of BatchName is: ' + FieldBatchName.Value);
finally
JO.Free;
end;
end;
Otherwise, consider switching to a 3rd party JSON library that natively supports editing values. Such as SuperObject.

Related

Parse JSON using lkJSON

I have a JSON file which I need to parse and extract one value.
{
"user": {
"pk": 25025320,
"username": "instagram",
"full_name": "Instagram",
"is_private": false,
"profile_pic_url": "https://instagram.fmad3-5.fna.fbcdn.net/vp/295f9e76d3c26fdf613d7856e7b43348/5B4F495B/t51.2885-19/s150x150/14719833_310540259320655_1605122788543168512_a.jpg",
"profile_pic_id": "1360316971354486387_25025320",
"is_verified": true,
"has_anonymous_profile_picture": false,
"media_count": 5164,
"follower_count": 233901016,
"following_count": 187,
"biography": "Discovering — and telling — stories from around the world.",
"external_url": "",
"usertags_count": 144,
"hd_profile_pic_versions": [
{
"width": 320,
"height": 320,
"url": "https://instagram.fmad3-5.fna.fbcdn.net/vp/893534d61bdc5ea6911593d3ee0a1922/5B6363AB/t51.2885-19/s320x320/14719833_310540259320655_1605122788543168512_a.jpg"
}
],
"hd_profile_pic_url_info": {
"url": "https://instagram.fmad3-5.fna.fbcdn.net/vp/8ae8a89c80ff4722eeab592b685276cb/5B5D40A1/t51.2885-19/14719833_310540259320655_1605122788543168512_a.jpg",
"width": 320,
"height": 320
},
"has_highlight_reels": true,
"auto_expand_chaining": false
},
"status": "ok"
}
I want to extract and send the value of hd_profile_pic_url_info.url to Memo2 using the lkJSON library, Instagram API and code below to achievie this result.
var
sJSON: string;
js, Items, Item: TlkJSONbase;
I, J: Integer;
begin
sJSON := Memo1.text;
js := TlkJSON.ParseText(sJSON);
for I := 0 to Pred(js.Count) do
begin
Items := js.Child[I].Field['user'];
for J := 0 to Pred(Items.Count) do
begin
Item := Items.Child[J];
Memo2.Lines.Add(VarToStr(Item.Field['hd_profile_pic_url_info'].Value));
end;
end;
end;
You forgot that hd_profile_pic_url_info is another object containing url, width, and height, so you need to go down one more time. Here is an example of how this should be done properly.
var
js : TlkJSONbase;
begin
js := TlkJSON.ParseText(Memo1.Text);
if Assigned(js) then
begin
js := js.Field['user'];
if Assigned(js) then
begin
js := js.Field['hd_profile_pic_url_info'];
if Assigned(js) then
begin
js := js.Field['url'];
if Assigned(js) then
Memo2.Lines.Add(VarToStr(js.Value));
end;
end;
end;
end;
i use this function :
function ChildValueStr(AChild: TlkJSONbase; const Name: string; DefaultValue:
AnsiString = ''): {$IF CompilerVersion>=26}WideString{$ELSE}AnsiString{$IFEND};
var
tmpIndex: integer;
tmpStr: {$IF CompilerVersion>=26}WideString{$ELSE}AnsiString{$IFEND};
begin
Result:= DefaultValue;
if IsNil(AChild) then exit;
tmpStr:= (AChild as TlkJSONobject).{$IF CompilerVersion>=26}getWideString{$ELSE}getString{$IFEND}(Name);
if tmpStr = '' then
begin
tmpIndex := (AChild as TlkJSONobject).IndexOfName(Name);
if tmpIndex <> -1 then
Result := (AChild as TlkJSONobject).getString(tmpIndex);
end
else Result:= tmpStr;
end;
so with your code, you can use it :
var sJSON: String;
js, Items, Item: TlkJSONBase;
I, J: Integer;
begin
sJSON := Memo1.text;
js := TlkJSON.ParseText(sJSON);
for I := 0 to Pred(js.Count) do
begin
Items := js.Child[I].Field['user'];
Memo2.Lines.Add(ChildValueStr(Items, 'hd_profile_pic_url_info'));
end;
end;
I hope this can help u
Another alternative to parse JSON without use external components is the free online service https://jsontodelphi.com/
You paste the JSON text and it generate a unit with delphi classes to parse the text without problems. Better if the JSON text is complicated.
In this case, the code to access to the value is simpliest:
procedure TForm2.Button1Click(Sender: TObject);
var
root:TRootClass;
begin
root := TRootClass.FromJsonString(Memo1.Lines.Text {your JSON text});
// The caption get the URL of the pic
Caption := root.user.hd_profile_pic_url_info.url;
end;

Delphi pointer variable required

I am trying to create a global procedure which can append a JSON field to a main JSON object dynamically.
procedure TJSONAdapter.addField(Key, Field: String);
var
i: Integer;
strArr: TStringList;
j: Integer;
pJSONObj: ^TJSONObject;
begin
strArr:= TStringList.Create;
Split('.', Key, strArr);
pJSONObj:= #STATICJSON;
i:= 0;
repeat
begin
if IsSimpleJsonValue(STATICJSON.GetValue(strArr[i])) then
begin
Exit;
end;
if STATICJSON.GetValue(strArr[i]) is TJSONObject then
begin
pJSONObj:= #(STATICJSON.GetValue(strArr[i]) as TJSONObject); -> error in this line
if i + 1 = strArr.Count then
begin
I store my values in a JSON object named STATICJSON until the program closes, and then I save it to file.
I am trying to add a field somewhere in STATICJSON. For example;
{
"colors" :
{
"id": "F00",
"color": "red",
"details" : [
{
"name_en": "Red",
},
{
"name_de": "Rot"
}
]
},
{
"id": "0F0",
"color": "green",
"details" : [
{
"name_en": "Green",
},
{
"name_de": "Grün"
}
]
}
}
If I want to add a code field in every details of the first object in the colors array:
obj.addField('colors.0.details.X', 'code');
What I expected :
{
"colors" :
{
"id": "F00",
"color": "red",
"details" : [
{
"name_en": "Red",
"code": ""
},
{
"name_de": "Rot",
"code": ""
}
]
},
{
"id": "0F0",
"color": "green",
"details" : [
{
"name_en": "Green",
},
{
"name_de": "Grün"
}
]
}
}
So I am trying to go to the details array of the first color and addField using a pointer.
I was using:
STATICJSON:= STATICJSON.GetValue(strArr[i]) as TJSONObject;
and it works well, but STATICJSON content is changed to this:
"details" : [
{
"name_en": "Red",
"code": ""
},
{
"name_de": "Rot",
"code": ""
}
]
So I lost all other JSON content. This is why I want to use a pointer. But I'm getting an error on this line:
pJSONObj:= #(STATICJSON.GetValue(strArr[i]) as TJSONObject);
Variable required
UPDATE :
procedure TJSONAdapter.addField(Key, Field: String);
var
i: Integer;
strArr: TStringList;
j: Integer;
begin
strArr:= TStringList.Create;
Split('.', Key, strArr);
i:= 0;
repeat
begin
if IsSimpleJsonValue(STATICJSON.GetValue(strArr[i])) then
begin
Exit;
end;
if STATICJSON.GetValue(strArr[i]) is TJSONObject then
begin
STATICJSON:= STATICJSON.GetValue(strArr[i]) as TJSONObject;
if i + 1 = strArr.Count then
begin
STATICJSON.AddPair(TJSONPair.Create(Field, ''));
Exit;
end;
end;
if STATICJSON.GetValue(strArr[i]) is TJSONArray then
begin
if strArr[i + 1] = 'X' then
begin
for j := 0 to (STATICJSON.GetValue(strArr[i]) as TJSONArray).Size -1 do
begin
((STATICJSON.GetValue(strArr[i]) as TJSONArray).Get(j) as TJSONObject).AddPair(TJSONPair.Create(Field, ''));
end;
Exit;
end;
STATICJSON:= (STATICJSON.GetValue(strArr[i]) as TJSONArray).Get(StrToInt(strArr[i+1])) as TJSONObject;
i:= i+1;
end;
Inc(i);
end;
until i = strArr.Count;
strArr.Free;
end;
It works, but because of these lines:
STATICJSON:= STATICJSON.GetValue(strArr[i]) as TJSONObject;
STATICJSON:= (STATICJSON.GetValue(strArr[i]) as TJSONArray).Get(StrToInt(strArr[i+1])) as TJSONObject;
I lost the main JSON content, so I don't want to assign STATICJSON, i just want to assign its address to a pointer to not lose its content.
Delphi objects are reference types. TJSONObject is already a pointer, so there is no need to use ^TJSONObject.
Try something more like this:
var
STATICJSON: TJSONObject = nil;
procedure TJSONAdapter.addField(Key, Field: String);
var
I, J, Index: Integer;
strArr: TStringList;
pJSONVal: TJSONValue;
begin
strArr := TStringList.Create;
try
Split('.', Key, strArr);
if STATICJSON = nil then begin
STATICJSON := TJSONObject.Create;
end;
pJSONVal := STATICJSON;
For I := 0 to strArr.Count-1 then
begin
if TryStrToInt(strArr[I], Index) then
begin
if not (pJSONVal is TJSONArray) then Exit;
pJSONVal := TJSONArray(pJSONVal).Get(Index);
end
else if strArr[I] = '*' then
begin
if I <> (strArr.Count-1) then Exit;
if not (pJSONVal is TJSONArray) then Exit;
with TJSONArray(pJSONVal) do
begin
For J := 0 to Count-1 do
begin
pJSONVal := Get(Index);
if pJSONVal is TJSONObject then
TJSONObject(pJSONVal).AddPair(Field, '');
end;
end;
end
else if pJSONVal is TJSONObject then
begin
pJSONVal := TJSONObject(pJSONVal).Get(strArr[I]);
if pJSONVal = nil then Exit;
end
else Exit;
end;
if pJSONVal is TJSONObject then
TJSONObject(pJSONVal).AddPair(Field, '');
finally
strArr.Free;
end;
end;
obj.addField('colors.0.details.*', 'code');

read inner JSON Object delphi

I have these JSON Object , I read it well , But when i read oauth value i got an empty result ,
How I can read it ?
{
"status": true,
"message": "Success",
"items": {
"id": 6,
"name": "Tesst1",
"email": "Test1#tesst.Test",
"image": "https://www.website.com/images/man.png",
"created_at": "2017-08-24 09:18:15",
"updated_at": "2017-08-24 09:18:15",
"oauth": {
"token_type": "abc",
"expires_in": 1296000,
"access_token": "jI5NiwiZXhGVzIjpbXX0.RaC3ixxUeyYnCB6vNlwKsdjf09UeOwUJlcKmKErmE_LTAeQ-4fm8iBOKqUgpikTkyB3ztDGf4DAsaeEjUMqH76jZdbPHnX0vr676dCXkEunWoDEB8sYiHz7XRVgQ5W0O9yybA93mPO_XyrWPibkGW7GLQOApRD605N0e6vw0v9Kb_WQBim7zjTNqoLM1fSjgKJezFqf9_s3KIqBc4bjsayYLl7duzo2fzRmWtnGFfbsgO6YcaIz8ezNtWbtixLRMKnJEj1-MluqjWubsbq_gTI6yiyyac3_oY22Ge0QDdCtljadgO7wRz5VT5aJkxmJRB90u0ovm0tpGzYOO_4giY-J5egpOptjt2VZbPeM-vWPEo4-c6NYMZx6WqxBHjkZwiKUsM-tufzl5P5lFRJ9V_rBUBHEiSonTAk9FVDAwjqLc6N_IC1lsFDEC_3NBy4",
"refresh_token": "def502003e7826477c1072497ad66d7f11ea29e81a0fafef6223a63b6a0a3d18de71165afb9a340d10facca3ac7ee955aac5786a5c66a39cdf77e3f6449458e07271cbcde699aabf4d7f72dad10d586c37497216552f88460e50e9ea4944214984d5b23bac04b5f8265d132"
}
}
}
If i read the oauth as a JSON Object I got an exception about unsupported conversion,
conversion from TJSONObject to string is not supported
what is the wrong with my code ??
if JsonRespnse <> '' then
begin
jsonObiekt := TJSONObject.ParseJSONValue
(TEncoding.ASCII.GetBytes(JsonRespnse), 0) as TJSONObject;
try
try
LoginValue := jsonObiekt.get('status').JsonValue;
LoginValueIsTrue := StrToBool(LoginValue.value);
if LoginValueIsTrue = True then
begin
ItemsValue := jsonObiekt.get('items').JsonValue;
if ItemsValue is TJSONObject then
begin
strIdValue := ItemsValue.GetValue<string>('id');
// strOuthValue := ItemsValue.GetValue<string>('oauth');
OauthValue := TJSONObject(ItemsValue).get('oauth').JsonValue;
if OauthValue is TJSONObject then
Memo1.Lines.Add('oauth : ' + OauthValue.value);
end;
end;
except
on E: Exception do
ShowMessage('Read JSON : ' + E.Message);
end;
finally
jsonObiekt.Free;
end;
end;
strOuthValue := ItemsValue.GetValue<string>('oauth');
Is not working because it’s not a string in the context of the TJSON* classes. The key oauth is an json object just like 'items'.
You can read the values of the oauth object like you did it with 'items.id'
if OauthValue is TJSONObject then
begin
Memo1.Lines.Add('oauth : ' + TJSONObject(OauthValue).ToString);
Memo1.Lines.Add('oauth.token_type: ' + TJSONObject(OauthValue).Values['token_type'].ToString);
end;
Does this cover your question?

Delphi XE5 JSON nested object

I am trying to generate JSON, data source is a DB FireBird.
I have a schema to generate path like this:
schema:= TDictionary<string, string>.Create;
schema.Add('DBTableName1', 'nest1.valueKeyName1');
schema.Add('DBTableName2', 'nest1.valueKeyName2');
schema.Add('DBTableName3', 'nest2.valueKeyName1');
schema.Add('DBTableName4', 'nest3.valueKeyName1');
schema.Add('DBTableName5', 'nest3.valueKeyName2');
schema.Add('DBTableName6', 'nest4.valueKeyName1');
How to create function for generate path to make nested objects?
{
"nest1": {
valueKeyName1: DBTableValue1,
valueKeyName2: DBTableValue2,
},
"nest2": {
valueKeyName1: DBTableValue3
},
"nest5":{
"nest6": {
"key1": "value1",
"key2": "value2",
},
"nest7": {}
}
In JavaScript I can do something like:
if (object.hasOwnProperty['key'] == false) object['key'] = {};
object = object['key'];
But in Delphi I have problem, and do not know, how to go deeper:
function TKlient.wprowadzWartoscDoJSON(wartosc: string; JSON: TJSONObject; sciezka: TStringList): TJSONObject;
var
i: integer;
obiekt: TJSONObject;
para: TJSONPair;
zagniezdzen: integer;
begin
zagniezdzen := sciezka.Count - 2;
obiekt := JSON;
para:= obiekt.Get(sciezka[i]);
for i := 1 to zagniezdzen do
begin
if obiekt.Get(sciezka[i]) = nil then obiekt.AddPair(sciezka[i], TJSONObject.Create)
else obiekt := obiekt.Get(sciezka[i]);
end;
obiekt.AddPair(sciezka[sciezka.Count - 1], wartosc);
result := obiekt;
end;
Here I've used a TDictionary<string, TJSONObject> to keep track of the object paths.
var
schema: TDictionary<string, string>;
pathSchema: TDictionary<string{path to every object}, TJSONObject>;
pair: TPair<string, string>;
values: TStringDynArray;
jsonObj,
jsonChildObj,
jsonParentObj: TJSONObject;
path: string;
i: Integer;
begin
schema := TDictionary<string, string>.Create;
try
schema.Add('DBTableName1', 'nest1.valueKeyName1');
schema.Add('DBTableName2', 'nest1.valueKeyName2');
schema.Add('DBTableName3', 'nest2.valueKeyName1');
schema.Add('DBTableName4', 'nest3.valueKeyName1');
schema.Add('DBTableName5', 'nest3.valueKeyName2');
schema.Add('DBTableName6', 'nest4.valueKeyName1');
schema.Add('value1', 'nest5.nest6.key1');
schema.Add('value2', 'nest5.nest6.key2');
pathSchema := TDictionary<string, TJSONObject>.Create;
try
jsonObj := TJSONObject.Create;
try
for pair in schema do begin
values := SplitString(pair.Value, '.');
path := '';
jsonParentObj := jsonObj;
for i := Low(values) to High(values)-1 do begin
if i > 0 then
path := path + '.';
path := path + values[i];
if pathSchema.ContainsKey(path) then
jsonChildObj := pathSchema[path]
else begin
jsonChildObj := TJSONObject.Create;
jsonParentObj.AddPair(TJSONPair.Create(values[i], jsonChildObj));
pathSchema.Add(path, jsonChildObj);
end;
jsonParentObj := jsonChildObj;
end;
jsonChildObj.AddPair(TJSONPair.Create(values[High(values)], pair.Key));
end;
WriteLn(jsonObj.ToString);
finally
jsonObj.Free;
end;
finally
pathSchema.Free;
end;
finally
schema.Free;
end;
ReadLn;
end.
The above prints the following:
{
"nest4":{
"valueKeyName1":"DBTableName6"
},
"nest2":{
"valueKeyName1":"DBTableName3"
},
"nest5":{
"nest6":{
"key1":"value1",
"key2":"value2"
}
},
"nest1":{
"valueKeyName1":"DBTableName1",
"valueKeyName2":"DBTableName2"
},
"nest3":{
"valueKeyName1":"DBTableName4",
"valueKeyName2":"DBTableName5"
}
}

Read a specific value from a JSON request using SuperObject

Hello I get the next result in a web API in JSON format:
[
{
"$id":"47",
"CodISO":"BIH",
"ES":"Bosnia y Herzegovina",
"EN":"Bosnia and Herzegovina"
},
{
"$id":"48",
"CodISO":"BLR",
"ES":"Bielorrusia",
"EN":"Belarus"
},
{
"$id":"49",
"CodISO":"BLZ",
"ES":"Belice",
"EN":"Belize"
},
{
"$id":"50",
"CodISO":"BOL",
"ES":"Bolivia",
"EN":"Bolivia"
},
{
"$id":"51",
"CodISO":"BON",
"ES":"Bonaire",
"EN":"Bonaire"
},
{
"$id":"52",
"CodISO":"BOT",
"ES":"Botsuana",
"EN":"Botswana"
},
{
"$id":"53",
"CodISO":"BRA",
"ES":"Brasil",
"EN":"Brazil"
},
{
"$id":"54",
"CodISO":"BRB",
"ES":"Barbados",
"EN":"Barbados"
}
]
Now, I want read the value from item 'ES' where the value of item 'CodISO' = 'BOL' in Delphi SuperObject, I'm not able to find the solution, took all day trying it.
I don't know how iterate with SuperObject elements as I do it with Embarcadero TJSONValue, TJSONObject, TJSONArray. I'm a newbie with SuperObject:
var
json: ISuperObject;
Retriever: TIdHTTP;
Url: string;
AnsiStr: AnsiString;
begin
URL := Form1.RestClient1.BaseURL;
try
Retriever := TIdHTTP.Create(nil);
try
AnsiStr := Retriever.Get(Url);
json := SO(AnsiStr);
{ Here code to iterate with json elements in SuperObject.......
.
.
.
.
}
finally
Retriever.Free;
end;
except
on E: Exception do
ShowMessage(E.ClassName + ': ' + E.Message);
end;
End;
As Sir Rufo said, you need to read the SuperObject documentation.
Try something like this:
var
JsonArr, JsonObj: ISuperObject;
Retriever: TIdHTTP;
Url, JsonStr, ES: string;
I: Integer;
begin
URL := Form1.RestClient1.BaseURL;
try
Retriever := TIdHTTP.Create(nil);
try
JsonStr := Retriever.Get(Url);
finally
Retriever.Free;
end;
JsonArr := SO(JsonStr).AsArray;
for I := 0 to JsonArr.Length-1 do
begin
JsonObj := JsonArr.O[I];
if JsonObj.S['CodISO'] = 'BOL' then
begin
ES := JsonObj.S['ES'];
Break;
end;
end;
except
on E: Exception do
ShowMessage(E.ClassName + ': ' + E.Message);
end;
end;