How to read fairly simple JSON file in Delphi Xe4?

16,868

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.

Share:
16,868
Mark Patterson
Author by

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, 2022

Comments

  • Mark Patterson
    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
    Mark Patterson almost 10 years
    That code looks nice and readable. Where does JSONArr come from though? It doesn't get assigned.
  • Mark Patterson
    Mark Patterson almost 10 years
    Ah, the elegance of generics. And the simpler unit name of System.JSON suggests that JSON is seen as more important.
  • Mark Patterson
    Mark Patterson almost 10 years
    Fortuately my Xe4 has the same form as the XE5 example. That worked!
  • Jerry Dodge
    Jerry Dodge almost 10 years
    JSONValue is actually supposed to be JSONArr