Parsing a Json array in Delphi - arrays

I have a problem to parse an array in Json. The Json is like this example:
[
[
A1,
A2,
A3,
],
[
B1,
B2,
B3,
],
and so on.
I get always an access violation error if I try to parse it:
procedure tform1.test;
var
i:integer
value,A:string;
jValue:TJSONValue;
JSonValue:TJSonValue;
Jarray:TJSONArray;
begin
jValue:=RESTResponse1.JSONValue;
Jarray := TJSonObject.ParseJSONValue(value) as tjsonarray;
for i := 0 to Jarray.Count - 1 do
A:=Jarray.items[i].value;
end;
What am I doing wrong?

Use JsonValue as TJSONArray twice. A working example:
procedure TForm1.Test1;
var
I: Integer;
Value, A: String;
jValue: TJSONValue;
JSonValue1, JSonValue2: TJSonValue;
JArray, JArr: TJSONArray;
begin
Value := '[["A1","A2","A3"],["B1","B2","B3"]]';
JsonValue1 := TJSonObject.ParseJSONValue(Value);
try
JArray := JsonValue1 as TJSONArray;
for JsonValue2 in JArray do
begin
JArr := JsonValue2 as TJSONArray;
A := JArr.Items[0].Value;
ShowMessage(A);
end;
finally
JsonValue1.Free;
end;
end;

Related

Create an Array from Json Object

I have the following JSON structure, calling it from web:
[
{
"Code":"31212",
"Desc":"JOHN",
"DOYDESC":"MADRID",
"Street":"Str41",
"StreetNo":"86"
},
{
"Code":"30214",
"Desc":"GEORGE",
"DOYDESC":"NEW YORK",
"Street":"Str3",
"StreetNo":null
},
{
"Code":"09215",
"Desc":"MARY",
"DOYDESC":"PARIS",
"Street":"Str3",
"StreetNo":"22"
},
{
"Code":"10217",
"Desc":"MEGAN",
"DOYDESC":"ROME",
"Street":"Str4",
"StreetNo":null
}
]
I want the user to give a number in Edit.Text, and then search the values of Code to find if the given value exists.
Is there a way to create an array named Code with the values from the JSON?
For example, to create something like this:
Code = ["31212","30214","09215","10217"]
and then make the search? Or, is there another way to find a specific value of Code from the JSON? I tried this so far:
procedure Tlog_form.Button2Click(Sender: TObject);
var
jso : TJsonObject;
jsv,jsval : TJsonValue;
jsa,jsarr : TJsonArray;
data,str : string;
i,j,user : integer;
jsp : TJsonPair;
arr : array of string;
begin
try
data := GetURLAsString('http://...');
except
on E: exception do
end;
try
jsv := TJSONObject.ParseJSONValue(data);
try
jsa := jsv as TJSONArray;
try
for I := 0 to jsa.Size - 1 do
begin
jso := jsa.Get(i) as TJsonObject;
if jso.ToString = 'Code' then
begin
str := jso.GetValue('Code').ToString;
if Edit1.Text = str then
begin
ShowMessage('found it');
end;
end;
end;
finally
end;
finally
jsv.Free;
end;
except
on E: exception do
end;
end;
When I debug, it doesn't get any error. but it still doesn't work.
You are converting each TJSONObject in the array to a string, and then comparing that to your TEdit text. Which will obviously not match. You need to compare only the Code field of each TJSONObject, which you would be doing if you remove the if jso.ToString = 'Code' then check completely, eg:
procedure Tlog_form.Button2Click(Sender: TObject);
var
jsv : TJSONValue;
jsa : TJSONArray;
jso : TJSONObject;
data, str, code : string;
I : integer;
begin
str := Edit1.Text;
try
data := GetURLAsString('http://...');
jsv := TJSONObject.ParseJSONValue(data);
if jsv <> nil then
try
jsa := jsv as TJSONArray;
for I := 0 to jsa.Size - 1 do
begin
jso := jsa.Get(I) as TJSONObject;
code := jso.GetValue('Code').ToString;
if str = code then
begin
ShowMessage('found it');
end;
end;
finally
jsv.Free;
end;
except
end;
end;
I'm not sure I understand you very well, but if you try TALJsonDocument (https://github.com/Zeus64/alcinoe), you have this function:
Function ALFindJsonNodeByTextChildNodeValue(const JsonNode:TalJsonNode;
Const ChildNodeName: AnsiString;
Const ChildNodeValue : AnsiString;
Const Recurse: Boolean = False): TALJsonNode;

Extract Values from key and array on JSON begins with '['

Sorry, I searched here for This problem on the site
But the Json I have is unlike any other here on the site Because it begins with '['
and I got tired trying to extract the values
Then how I can Extract Values from key and array on JSON begins with '['
[{"date":"12/11/1990","name":"Delphi7"},{"date":"03/05/2012","name":"Delphi 10.4"}]
Or extract Form This :
[{"User":{"date":"12/11/1990","name":"Delphi7"}},{"User":{"date":"03/05/2012","name":"Delphi 10.4"}}]
In JSON, [] denotes an array. In this case, both examples you have provided represent an array of objects.
If you parse these strings using TJSONObject.ParseJSONValue(), it will return a TJSONValue pointer to a TJSONArray object that is holding TJSONObject elements, eg:
uses
..., System.JSON;
var
JSONStr, DateStr, NameStr: string;
JSONVal: TJSONValue;
JSONArr: TJSONArray;
JSONObj: TJSONObject;
I: Integer;
begin
JSONStr := '[{"date":"12/11/1990","name":"Delphi7"},{"date":"03/05/2012","name":"Delphi 10.4"}]';
JSONVal := TJSONObject.ParseJSONValue(JSONStr);
try
JSONArr := JSONVal as TJSONArray;
for I := 0 to JSONArr.Count-1 do
begin
JSONObj := JSONArr[I] as TJSONObject;
DateStr := JSONObj.GetValue('date').Value;
NameStr := JSONObj.GetValue('name').Value;
...
end;
finally
JSONVal.Free;
end;
end;
uses
..., System.JSON;
var
JSONStr, DateStr, NameStr: string;
JSONVal: TJSONValue;
JSONArr: TJSONArray;
JSONObj, JSONUser: TJSONObject;
I: Integer;
begin
JSONStr := '[{"User":{"date":"12/11/1990","name":"Delphi7"}},{"User":{"date":"03/05/2012","name":"Delphi 10.4"}}]';
JSONVal := TJSONObject.ParseJSONValue(JSONStr);
try
JSONArr := JSONVal as TJSONArray;
for I := 0 to JSONArr.Count-1 do
begin
JSONObj := JSONArr[I] as TJSONObject;
JSONUser := JSONObj.GetValue('User') as TJSONObject;
DateStr := JSONUser.GetValue('date').Value;
NameStr := JSONUser.GetValue('name').Value;
...
end;
finally
JSONVal.Free;
end;
end;

How to count number of elements in a JSON array in Delphi

I am accessing a TJSONValue in Delphi(using REST components and Google Books' API). I want to know how many elements are in the array: 'items'.
This is the format of the JSONValue:
"kind": "books#volumes",
"totalItems": 221,
"items": [
{...},
{...},
{...}]
Note* "totalItems" does not refer to the size of the array.
I've tried somethin along this line, but it raises a conversion error.
var
JSONBook: TJSONValue;
CountItems: integer;
begin
JSONBook := RESTResponse1.JSONValue;
ShowMessage(IntToStr(JSONBook.GetValue<string>('items').Length));
CountItems := JSONBook.GetValue<string>('items').Length;
for i := 0 to CountItems-1 do
begin
...
end;
end;
The items field is an array, so retrieving it as a string is just wrong, so it makes sense that reading the array count via a string length would not work.
Try this instead:
uses
..., System.JSON;
var
JSONBook, JSONItem: TJSONObject;
JSONItems: TJSONArray;
CountItems: integer;
begin
JSONBook := RESTResponse1.JSONValue as TJSONObject;
JSONItems := JSONBook.GetValue('items') as TJSONArray;
CountItems := JSONItems.Count;
ShowMessage(IntToStr(CountItems));
for i := 0 to CountItems-1 do
begin
JSONItem := JSONItems.Items[i] as TJSONObject;
...
end;
end;

How to create a JSONArray without a name in Delphi?

I have been searching the internet for a couple of days and have been trying out lots of things but I did not manage to create a JSONArray without a name yet.
Normally a JSONArray looks like this:
"MyArray" [
//content
]
But I need this:
[
//content
]
My JSON-File needs to look like this in the end:
[
{
"videos":"Hello.MOV",
"render-status":"ready",
"output":"test\\out1.mov"
},
{
"videos":"123.MOV",
"render-status":"ready",
"output":"test\\out1.mov"
},
]
By the way I am using Delphi 10.2.
Can anyone point me in the right direction?
Micha
You can use the Stadard System.JSON objects in Delphi as well.
uses
System.JSON;
function CreateArray: TJSONArray;
var
LTempObject: TJSONOBject;
begin
Result := TJSONArray.Create;
LTempObject := TJSONOBject.Create;
LTempObject.AddPair('videos', 'Hello.MOV');
LTempObject.AddPair('render-status', 'ready');
LTempObject.AddPair('output', 'test\out1.mov');
Result.AddElement(LTempObject);
LTempObject := TJSONOBject.Create;
LTempObject.AddPair('videos', '123.MOV');
LTempObject.AddPair('render-status', 'ready');
LTempObject.AddPair('output', 'test\out1.mov');
Result.AddElement(LTempObject);
end;
Use Like so:
var
LJSON: TJSONArray;
begin
LJSON := CreateArray;
//Will give you exact string as above
//without and formatting
memo.Text := LJSON.ToJSON;
end;
Using JsonDataObjects
uses
JsonDataObjects;
const
JSON_ARRAY =
'[{"videos":"Hello.MOV","render-status":"ready","output":"test\\out1.mov"},{"videos":"123.MOV","render-status":"ready","output":"test\\out1.mov"}]';
procedure TJsonTests.BuildArrayTest;
var
A: TJsonArray;
O: TJsonObject;
V: string;
begin
A := TJsonArray.Create;
try
O := A.AddObject;
O.S['videos'] := 'Hello.MOV';
O.S['render-status'] := 'ready';
O.S['output'] := 'test\out1.mov';
O := A.AddObject;
O.S['videos'] := '123.MOV';
O.S['render-status'] := 'ready';
O.S['output'] := 'test\out1.mov';
CheckEquals(2, A.Count);
V:= A.ToJSON();
CheckEquals(JSON_ARRAY, V);
finally
A.Free;
end;
end;
procedure TJsonTests.ParseArrayTest;
var
A: TJsonArray;
V: string;
begin
A := TJsonArray.Create;
try
A.FromUtf8JSON(JSON_ARRAY);
CheckEquals(2, A.Count);
V:= A.ToJSON();
CheckEquals(JSON_ARRAY, V);
finally
A.Free;
end;
end;

Array Implementation in Delphi xe6

I want to fill the last three Edit's with the elements of r. Somehow the value of i is not changing. Please have a look!
procedure TForm1.Button1Click(Sender: TObject);
var
r: Array of Real;
cod,h,N,code,i: Integer;
value: Real;
begin
Val(Edit1.Text, cod, code);
Val(Edit2.Text, h, code);
Val(Edit3.Text, N, code);
Edit1.Text := Edit1.Text;
Edit2.Text := Edit2.Text;
Edit3.Text := Edit3.Text;
setlength(r, N);
i:= 0;
while i<= N do
begin
r[i] := cod/2 + h*i;
i := i + 1;
end;
Edit4.Text := formatfloat('#.0', r[0]);
Edit5.Text := formatfloat('#.0', r[1]);
Edit6.Text := formatfloat('#.0', r[2]);
end;
end.
Your code contains a lot of useless and buggy code. So I will fix it as far I can do from the given informations. I added a prefix L to all local variables
procedure TForm1.Button1Click(Sender: TObject);
var
Lr : Array[0..2] of Real;
Lcod, Lh : Integer;
LIdx : Integer;
begin
// throws an exception if Edit1.Text cannot converted to an Integer
Lcod := StrToInt( Edit1.Text );
// throws an exception if Edit2.Text cannot converted to an Integer
Lh := StrToInt( Edit2.Text );
for LIdx := 0 to 2 do
Lr[LIdx] := Lcod/2 + Lh*LIdx;
Edit4.Text := FormatFloat( '#.0', Lr[0] );
Edit5.Text := FormatFloat( '#.0', Lr[1] );
Edit6.Text := FormatFloat( '#.0', Lr[2] );
end;

Resources