coming from .NET, I've been unable to do what I consider a simple task.
I want to use TJSONObject, TJSONArray, TJSONPair etc to construct a simple JSON like the following:
{
"APIKEY": "sadfsafsafdsa",
"UserID": "123123123",
"Transactions:"
[{
"TransactionID": 1,
"Amount": 23
},
{
"TransactionID": 2,
"Amount": 53
}]
}
Logically what I would do is create a TJSONObject and then add 3 TJSONPair, the third pair being TJSONPair of Transactions and a TJSONArrary
However, I am not getting what I wanted. For the Transactions pair, if I convert my transactions TJSONArrary to string, then it comes out as a long string which is invalid.
Any help would be appreciated.
Try this
{$APPTYPE CONSOLE}
{$R *.res}
uses
Data.DBXJSON,
System.SysUtils;
var
LJson, LJsonObject: TJSONObject;
LArr: TJSONArray;
begin
try
ReportMemoryLeaksOnShutdown:=True;
LJsonObject := TJSONObject.Create;
try
LJsonObject.AddPair(TJSONPair.Create('APIKEY', 'sadfsafsafdsa'));
LJsonObject.AddPair(TJSONPair.Create('UserID', '123123123'));
LArr := TJSONArray.Create;
LJson := TJSONObject.Create;
LJson.AddPair(TJSONPair.Create('TransactionID', '1'));
LJson.AddPair(TJSONPair.Create('Amount', '23'));
LArr.Add(LJson);
LJson := TJSONObject.Create;
LJson.AddPair(TJSONPair.Create('TransactionID', '2'));
LJson.AddPair(TJSONPair.Create('Amount', '53'));
LArr.Add(LJson);
LJsonObject.AddPair(TJSONPair.Create('Transactions', LArr));
Write(LJsonObject.ToString);
finally
LJsonObject.Free; //free all the child objects.
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
This will create a JSON like so
{ "APIKEY": "sadfsafsafdsa",
"UserID": "123123123",
"Transactions":
[{
"TransactionID": "1",
"Amount": "23"
},
{
"TransactionID": "2",
"Amount": "53"
}]
}
Related
I want to parse the JSON and extract all ID values and assign, show them in a combo box.
I am using ULKJson library and Delphi 7. Here is my JSON
{
"ID": null,
"ResCode": 100,
"ResMessage": "هیچ آیتم جدیدی در پایگاه داده ذخیره نشد",
"ResPos": null,
"ResData": {
"data": [
{
"data": {
"id": "2994LUZUWL",
"type": "SHEBAD_ID"
},
"sendDate": "2021-11-02T20:00:16.827"
},
{
"data": {
"id": "2992CQVAE1",
"type": "SHEBAD_ID"
},
"sendDate": "2021-11-02T18:43:12.857"
},
{
"data": {
"id": "Z2005KUU6ZB",
"type": "SHEBAD_ID"
},
"sendDate": "2021-11-02T18:51:36.107"
},
{
"data": {
"id": "Z29914MM2WL",
"type": "SHEBAD_ID"
},
"sendDate": "2021-11-02T19:21:08.607"
}
],
"message": "",
"succeeded": true
}
}
How can I access to ID values inside this JSON?
Delphi 6 user here, but same thing really..
You need to have uLKJson installed, which I assume you have.
You need to parse each element as one of the uLKJSON types:
jsBase, jsNumber, jsString, jsBoolean, jsNull, jsList, jsObject
You have
{ <<< root = object
"ResData": { <<< ResData = object
"data": [ <<< data = list
{ <<< element[0] = object
"data": { <<< data = object
"id": "2994LUZUWL", <<< id = string. This is what you want.
...
In jq, this would be selection string: ".ResData.data[].data.id".
The program to parse the data could look something like this:
program testparse;
{$APPTYPE CONSOLE}
uses
SysUtils, // for writing on console
ulkjson; // to parse JSON
var
vJsonObj: TlkJsonObject;
jo : TlkJSONstreamed;
listofelements: TlkJSONlist;
i : integer;
// {
// "data": {
// "id": "2994LUZUWL",
// "type": "SHEBAD_ID"
// },
// "sendDate": "2021-11-02T20:00:16.827"
// },
// function for simplicity
//
function get_key( j : TlkJSONobject) : string;
begin
try
result := j.Field['data'].Field['id'].Value;
except
result := 'N/A'; // if the id key is not there..
end;
end;
begin
jo := TlkJSONstreamed.Create;
try
vJsonObj := jo.LoadFromFile('jsontext.txt') as TlkJsonObject;
listofelements := vJsonObj.Field['ResData'].Field['data'] as TlkJSONlist;
for i := 0 to listofelements.Count-1 do
begin
writeln('Key no ' + inttostr(i) + '=' +
get_key(listofelements.Child[i] as TlkJSONobject)
);
end;
finally
jo.free;
end;
end.
Result:
Key no 0=2994LUZUWL
Key no 1=2992CQVAE1
Key no 2=Z2005KUU6ZB
Key no 3=Z29914MM2WL
Alternative library
Alternatively JSONTools, originally from Lazarus can be used. I have modified and uploaded a version for Delphi 6/7.
Using this unit:
writeln('-- doing it with JSONTools');
N := TJsonNode.Create;
n.LoadFromFile('jsontext.txt'); // will automatically do a parse
n:= n.Find('/ResData/data'); // get the array
for i := 0 to n.Count-1 do
begin
writeln(
'Key no ' + inttostr(i) + '=' +
n.Child(i).Find('data/id').AsString);
end;
n.Free;
Adding to a combobox
As the question was for how to add to a combobox: this is simple. First clear the combobox, then for each item do an "additem".
How do I parse the following Json in Delphi?
This is my first post, and I've taken care to search as much as I can before asking this question,
so please kindly let me know if I posted wrongly in any way.
I would like to get the value of "name_of_centre" in the "records" array
Thank you for any kind assistance.
procedure TForm1.Button1Click(Sender: TObject);
var
i : integer;
jsonRoot: TJSONValue;
jsonObj: TJSONObject;
jsonArr: TJSONArray;
begin
jsonRoot := TJSONObject.ParseJSONValue(memo2.Lines.text);
try
jsonObj := jsonRoot as TJSONObject;
jsonObj := jsonObj.GetValue('result') as TJSONObject;
jsonArr := jsonObj.GetValue('records') as TJSONArray;
showmessage( jsonArr.Count.ToString ); // works ok
for i := 0 to jsonArr.Count - 1 do
begin
jsonObj := jsonArr.Items[i] as TJSONObject;
showmessage( jsonObj.GetValue('name_of_centre').Value ); // error here
end;
finally
jsonRoot.Free;
end;
end;
I've checked out
Delphi parsing a Json with multiple array types?
How to parse this json data in Delphi 10 Seattle?
(especially this one)
and a few other links... but the JSON format seems different.
Any advice?
{
"help": "testing",
"success": true,
"result": {
"resource_id": "data_resource",
"fields": [
{
"type": "int4",
"id": "_id"
},
{
"type": "text",
"id": "name_of_centre"
},
{
"type": "text",
"id": "location_of_centre"
},
{
"type": "text",
"id": "type_of_centre"
},
{
"type": "text",
"id": "owner"
},
{
"type": "numeric",
"id": "no_of_outlets"
},
{
"type": "numeric",
"id": "no_of_branches"
}
],
"records": [
{
"location_of_centre": "Kings Road",
"no_of_outlets": "12",
"no_of_branches": "0",
"name_of_centre": "Kings Road Centre",
"type_of_centre": "HC",
"owner": "Private",
"_id": 1
},
{
"location_of_centre": "Queens",
"no_of_outlets": "14",
"no_of_branches": "1",
"name_of_centre": "Queens Centre",
"type_of_centre": "HC",
"owner": "Public",
"_id": 2
}
],
"_links": {
"start": "ignore",
"next": "ignore2"
},
"limit": 2,
"total": 10
}
}
Thanks for the many replies.
Olivier : I've included the error in this amended code.
Peter : I tried using
jsonRoot.GetValue('result.records[0].name_of_centre')
and it does give me the value of name_of_centre. Good start.
But I'm hoping to get this code to give me the number of items in Array and I iterate the array, instead of hard-code. Thanks.
Remy : strangely though, it works today. It doesn't get Invalid Typecast
at showmessage( jsonObj.GetValue('name_of_centre').Value );
fpiette : I use Delphi 10.3 RIO.
Thanks to everyone for replying.
Is there a need to use jsonRoot.Free; -- i saw this in a posting on stackoverflow.com... How about jsonObj.Free?
jsonRoot := TJSONObject.ParseJSONValue(memo2.Lines.text);
try
jsonObj := jsonRoot as TJSONObject;
jsonObj := jsonObj.GetValue('result') as TJSONObject;
showmessage( jsonObj.ToString );
jsonArr := jsonObj.GetValue('records') as TJSONArray;
showmessage( jsonArr.Count.ToString );
for i := 0 to jsonArr.Count - 1 do
begin
jsonObj := jsonArr.Items[i] as TJSONObject;
if jsonObj .GetValue('name_of_centre').Value = null then
showmessage('null');
// previously had an Invalid Typecast
showmessage( jsonObj.GetValue('name_of_centre').Value );
end;
finally
jsonRoot.Free;
end;
I have a JSON file that looks like this and I'm trying to decode it, but with no luck:
[
{
"FirstName": "Kim",
"Surname": "Jensen"
},
{
"FirstName": "Amery",
"Surname": "Mcmillan"
},
{
"FirstName": "Denton",
"Surname": "Burnett"
}
...
]
Using uJson with Delphi 2007, I know how to extract the data when the array has a name like this:
{
"Names": [
{
"FirstName": "Kim",
"Surname": "Jensen"
},
{
"FirstName": "Amery",
"Surname": "Mcmillan"
},
{
"FirstName": "Denton",
"Surname": "Burnett"
}
...
]
}
var
json: TJSONObject;
Text: String;
i: Integer;
begin
json := TJSONObject.create(jsontext);
for i:=0 to json.getJSONArray('Names').Length -1 do
begin
Text := json.getJSONArray('Names').getJSONObject(i).optString('FirstName');
...
end;
end;
But, this array has no name, and I have tried almost everything I can think of and still this simple thing has taking me hours to figure out.
In the JSON you are having trouble with, the top-level data is the array, so you need to parse it using TJSONArray instead of TJSONObject.
var
json: TJSONArray;
Text: String;
i: Integer;
begin
json := TJSONArray.create(jsontext);
try
for i := 0 to json.Length-1 do
begin
Text := json.getJSONObject(i).optString('FirstName');
...
end;
finally
json.Free;
end;
end;
Since I am writing, there is something that I am not able to understand. I have the following JSON object data that is indented. I would like to retrieve the values that are associated with “industry” and “exchange” for each “response” in PL/SQL in Oracle 12. I have installed the JSON package found in the forum https://github.com/pljson/pljson. All solution that I have found were not indented, so I am not sure if this is the reason, for not being able to access the information. Any suggestion or article that could help me would be greatly appreciated.
Thanks in advance.
This is my JSON string
{
"response":{
"MSFT":{
"meta":{
"status":"ok"
},
"results":{
"industry":{
"data":"Software - Infrastructure",
"meta":{
"status":"ok"
}
},
"exchange":{
"data":"NASDAQ",
"meta":{
"status":"ok"
}
}
}
},
"AAPL":{
"meta":{
"status":"ok"
},
"results":{
"industry":{
"data":"Consumer Electronics",
"meta":{
"status":"ok"
}
},
"exchange":{
"data":"NASDAQ",
"meta":{
"status":"ok"
}
}
}
}
},
"meta":{
"status":"ok",
"url":"http://testdata.com/api/v3/companies/AAPL,MSFT/info/exchange,industry"
}
}
This is a modified sample code that I have found on the forum base on this link
Parse JSON into Oracle table using PL/SQL
create or replace procedure json4(w_periode in varchar2) is
begin
DECLARE
l_param_list VARCHAR2(512);
l_http_request UTL_HTTP.req;
l_http_response UTL_HTTP.resp;
l_response_text VARCHAR2(32767);
l_list json_list;
obj json := json();
arr json_list := json_list();
BEGIN
-- service's input parameters
-- ...set input parameters
-- UTL_HTTP.write_text(l_http_request, l_param_list);
l_response_text := '{"response": {"MSFT": {"meta": {"status": "ok"}, "results": {"industry": {"data": "Software - Infrastructure", "meta": {"status": "ok"}}, "exchange": {"data": "NASDAQ", "meta": {"status": "ok"}}}}, "AAPL": {"meta": {"status": "ok"}, "results": {"industry": {"data": "Consumer Electronics", "meta": {"status": "ok"}}, "exchange": {"data": "NASDAQ", "meta": {"status": "ok"}}}}}, "meta": {"status": "ok", "url": "http://testurl.com"}}';
/* -- get Response and obtain received value
l_http_response := UTL_HTTP.get_response(l_http_request);*/
/* UTL_HTTP.read_text(l_http_response, l_response_text);
*/
obj := json(l_response_text);
DBMS_OUTPUT.put_line(l_response_text);
/* l_list := json_list(l_response_text);*/
/*arr := json_list(obj.get('industry'));*/
end;
end json4;
I found a solution. The link in the post need's to be bracket as an array. In my varchar2 I had to insert the "[" symbol at beginning and at the end. The problem is that it will only parse the JSON if it is not indented, from my understanding.
I then install the APEX5 package, it was able to handle indented code. I follow the installation procedure https://www.youtube.com/watch?v=JGnkPVq7V98 and on the first try it work perfectly.
Hope this help
I have this Json
{
"Sucess": true,
"Msg": "OK",
"Ret": {
"First": 0,
"Next": true,
"Total": 60,
"Itens": [
{
"ID": 212121,
"Name": "uuuuuuuuuuuuuuuuuuuuuuuu",
"LcID": 9898,
"Oclao": false,
"Lal": {
"ID": 12202,
"Name": "pppppppppppppppppp",
"Pais": "Brasil",
"Dtc": 0.0
},
"Subtipo": {
"ID": 7458,
"Desc": "mnmnmnmnn"
},
"Tipo": {
"Sit": "cor1",
"Sitrm": 0,
"Name": "Shsdfow"
},
"Qtde": 0,
"Qntcoes": 0,
"Pubum": "adfsdfsdfs",
"Evias": {
"arq": {
"Mo": [
"site.com"
],
"Moir": [
"site.com"
]
}
}
},
{
"ID": 9797878,
"Name": "uuuuuuuuuuuuuuuuuuuuuuuu",
"LcID": 9898,
"Oclao": false,
"Lal": {
"ID": 12332,
"Name": "pppppppppppppppppp",
"Pais": "Brasil",
"Dtc": 0.0
},
"Subtipo": {
"ID": 7458,
"Desc": "mnmnmnmnn"
},
"Tipo": {
"Sit": "cor1",
"Sitrm": 0,
"Name": "Shsdfow"
},
"Qtde": 0,
"Qntcoes": 0,
"Pubum": "adfsdfsdfs",
"Evias": {
"arq": {
"Mo": [
"site.com"
],
"Moir": [
"site.com"
]
}
}
}
]
}
}
however, I can only take the values of the first items "Sucess, Msg and Ret"
I'm doing as follows
var
JSONValue, jv: TJSONValue;
joName: TJSONObject;
data: TBytes;
sHtmlResp, sTemp : String;
begin
sHtmlResp := '[' + sHtmlResp + ']';
data := TEncoding.ASCII.GetBytes(sHtmlResp);
JSONValue := TJSONObject.ParseJSONValue(data, 0);
for jv in JSONValue as TJSONArray do
begin
joName := jv as TJSONObject;
sTemp:= joName.Get('Msg').JSONValue.Value;
end;
end;
sHtmlResp contains the string json.
I've tried some other ways to get the most unsuccessful field, how do I get the sub-items as "Ret", "Items" and so on.
A detail, had to add '[' ']' in the JSON string I get, otherwise I can not get even the first fields.
Thank!
Ret is a subobject so you need to access it as such. It has its own values and an array of subobjects, and so on.
Try this:
var
joName, joRet, joItem: TJSONObject;
joItems: TJSONArray;
sHtmlResp, sMsg: String;
bSuccess: Boolean;
begin
sHtmlResp := ...; // original JSON without added braces around it
joName := TJSONObject.ParseJSONValue(sHtmlResp) as TJSONObject;
bSuccess := joName.GetValue('Success') is TJSONTrue;
// if you are using Delphi 10 Seattle or later, you can use this instead:
// bSuccess := (joName.GetValue('Success') as TJSONBool).AsBoolean;
sMsg := joName.GetValue('Msg').Value;
joRet := joName.GetValue('Ret') as TJSONObject;
// use joRet.GetValue() as needed ...
joItems := joRet.GetValue('Itens') as TJSONArray;
for i := 0 to joItems.Count-1 do
begin
joItem := joItems.Items[i] as TJSONObject;
// use joItem.GetValue() as needed ...
end;
end;
If each object/sub-object have unique ObjectID (name).
The simple way is using this function
function ExtractJsonParm(parm:string;h:string):string;
var r:integer;
begin
r:=pos('"'+Parm+'":',h);
if r<>0 then
result := copy(h,r+length(Parm)+4,pos(',',copy(h,r+length(Parm)+4,length(h)))-1)
else
result:='';
end;
Usage:
begin
Writeln(ExtractJsonParm('First',Value));
Writeln(ExtractJsonParm('Next',Value));
Writeln(ExtractJsonParm('Total',Value));
end;
Outputs:
0
true
60
Using jsonDoc it would be
JSON(sHtmlResp)['Msg']
optionally enclosed in VarToStr to enforce type (and also silently convert Null to empty string value).
As noted in the comments by Remy: no need to enclose in [] as this enforces the outer array.