How to read fairly simple JSON file in Delphi Xe4?
Solution 1
// XE5- version
uses System.SysUtils, Data.DBXJSON, System.IOUtils;
function GetGeneratedNames: TArray<string>;
var
fileName: TFileName;
JSONValue, jv: TJSONValue;
begin
fileName := TPath.Combine(ExePath, 'Names.json');
JSONValue := TJSONObject.ParseJSONValue(TFile.ReadAllText(fileName));
try
if JSONValue is TJSONArray then
begin
for jv in TJSONArray(JSONValue) do
begin
Append(Result, (jv as TJSONObject).Get('FirstName').JSONValue.Value);
Append(Result, (jv as TJSONObject).Get('Surname').JSONValue.Value);
end;
end;
finally
JSONValue.Free;
end;
end { GetGeneratedNames };
// XE6+ version
uses System.SysUtils, System.JSON, System.IOUtils;
function GetGeneratedNames: TArray<string>;
var
fileName: TFileName;
JSONValue, jv: TJSONValue;
begin
fileName := TPath.Combine(ExePath, 'Names.json');
JSONValue := TJSONObject.ParseJSONValue(TFile.ReadAllText(fileName));
try
if JSONValue is TJSONArray then
begin
for jv in TJSONArray(JSONValue) do
begin
Append(Result, jv.GetValue<string>('FirstName'));
Append(Result, jv.GetValue<string>('Surname'));
end;
end;
finally
JSONValue.Free;
end;
end { GetGeneratedNames };
Solution 2
You are not reading the correct value from the array items.
Try something like this:
//...
var
JSONArr: TJSONArray;
Item: TJSONValue;
FirstName, Surname, WholeObject: String;
begin
//...
JSONArr := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(TFile.ReadAllText(filename)), 0);
try
for Item in JSONArr do
begin
// Get the first or last names
FirstName := (Item as TJSONObject).GetValue('FirstName').Value;
Surname := (Item as TJSONObject).GetValue('Surname').Value;
// Get the whole string {"FirstName": "Oleg", "Surname": "Buckley"}
WholeObject := Item.ToString;
end;
finally
JSONArr.Free;
end;
// do something with them ...
end;
The JSON object contains value pairs, but it doesn't have a value itself, so you get empty strings. If you want the whole object text you should use the "ToString" method.
And indeed SuperObject or XSuperObject are easier to use and faster if you happen to work with a large amount of data. The second one seems to also be available for iOS/Android, although I haven't used it.
Mark Patterson
I've been using Delphi since 1995! And it was like coming home. But now I am learning Swift, and it seems even better.
Updated on June 14, 2022Comments
-
Mark Patterson almost 2 years
I've been struggling with this for a while, and doing something simple seems to be taking too long.
I have a file like this:
[ { "FirstName": "Oleg", "Surname": "Buckley" }, { "FirstName": "Amery", "Surname": "Mcmillan" }, { "FirstName": "Denton", "Surname": "Burnett" ....
I want to be able to read them into my program. So far I have worked up this pretty little function:
function GetGeneratedNames: TArray<string>; var fileName: TFileName; JSONValue, jv: TJSONValue; JSONArray: TJSONArray; jo: TJSONObject; pair: TJSONPair; begin result := nil; filename := ExePath + 'Names.json'; JSONValue := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(TFile.ReadAllText(filename)), 0); if JSONValue is TJSONArray then begin for jv in (JSONValue as TJSONArray) do begin if jv is TJSONObject then begin jo := jv as TJSONObject; for pair in jo do begin Append(result, jo.Value); end; end; end; end; end{ GetGeneratedNames};
The trouble is, it returns an array of blank strings. Can anyone point me in the right direction?
TIA Mark
-
Mark Patterson almost 10 yearsThat code looks nice and readable. Where does JSONArr come from though? It doesn't get assigned.
-
Mark Patterson almost 10 yearsAh, the elegance of generics. And the simpler unit name of System.JSON suggests that JSON is seen as more important.
-
Mark Patterson almost 10 yearsFortuately my Xe4 has the same form as the XE5 example. That worked!
-
Jerry Dodge almost 10 years
JSONValue
is actually supposed to beJSONArr