JSON object- how to iterate through all properties without knowing their names?

5.4k views Asked by At

I have a fairly simple JSON:

[
    {
      "hero-img": "girl-ipad.png",
      "main-story-headline": "How to Stay Mentally Healthy During a Pandemic",
      "main-story-paragraph": "lorem ipsum",
      "main-story-button-text": "Read More"
    },
    {
      "hero-img": "painter-woman.png",
      "main-story-headline": "How to Stay Mentally Healthy During a Pandemic",
      "main-story-paragraph": "lorem ipsum",
      "main-story-button-text": "Explore More"
    },
    {
      "hero-img": "old-man.png",
      "main-story-headline": "How to Stay Mentally Healthy During a Pandemic",
      "main-story-paragraph": "lorem ipsum",
      "main-story-button-text": "Get Yours Now"
    } ]

By using Delphi 10.3 Rio, I want to iterate through all properties no matter how they are named. I've started this way:

program JuTemplates;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.JSON, System.IOUtils, System.Types;

var
  root, OutputDir, TemplatesDir, JsonDir, jsonText: string;
  JsonFiles: TStringDynArray;
  i, j: Integer;
  JSONValue: TJSONObject;
  JSONValues: TJSONArray;
begin
  try

    try
      root := ExtractFilePath(ParamStr(0));
      OutputDir := root + 'OutputDir\';
      TemplatesDir := root + 'TemplatesDir\';
      JsonDir := root + 'JsonDir\';
      writeln('Processing: ' + JsonDir);
      JsonFiles := TDirectory.GetFiles(JsonDir);
      for i := 0  to High(JsonFiles) do
      begin
        jsonText := TFILE.ReadAllText(JsonFiles[i]);
        JSONValues := TJSONObject.ParseJSONValue(jsonText) as TJSONArray;

        for j := 0 to JSONValues.Count - 1 do
        begin
          JSONValue := JSONValues.Items[i] as TJSONObject;
          // here I should iterate through that JSONValue object
        end;
      end;
    except
      on E: Exception do
        Writeln(E.ClassName, ': ', E.Message);
    end;
  finally
    writeln ('Press any key to continue');
    readln;
  end;
end.
1

There are 1 answers

0
fpiette On BEST ANSWER

To enumerate a JSONObject, you can use an enumerator like below.

Use for..in loop (implicit enumerator)

procedure TForm1.Button1Click(Sender: TObject);
var
   JSONData       : String;
   JSONObject     : TJSONObject;
   JSONPair       : TJSONPair;
begin
   JSONData   := '... some JSON data ...';   // Place you data here
   JSONObject := TJSonObject.ParseJSONValue(JSONData) as TJSONObject;
   try
     for JSONPair in JSONObject do
         ShowMessage(Format('1) Key=%s Value=%s',
                     [JSONPair.JsonString.ToString,
                      JSONPair.JsonValue.ToString]));
   finally
     JSONObject.Free;
   end;
end;

Use a classic for loop:

procedure TForm1.Button1Click(Sender: TObject);
var
   JSONData       : String;
   JSONObject     : TJSONObject;
   JSONPair       : TJSONPair;
   I              : Integer;
begin
   JSONData   := '... some JSON data ...';   // Place you data here
   JSONObject := TJSonObject.ParseJSONValue(JSONData) as TJSONObject;
   try
     for I := 0 to JSONObject.Count - 1 do begin
       ShowMessage(Format('Key=%s Value=%s',
                   [JSONObject.Pairs[I].JsonString.ToString,
                    JSONObject.Pairs[I].JsonValue.ToString]));
     end;
   finally
     JSONObject.Free;
   end;
end;

Use an explicit enumerator and a while loop:

procedure TForm1.Button1Click(Sender: TObject);
var
   JSONData       : String;
   JSONObject     : TJSONObject;
   JSONEnumerator : TJSONObject.TEnumerator;
   JSONPair       : TJSONPair;
begin
   JSONData   := '... some JSON data ...';   // Place you data here
   JSONObject := TJSonObject.ParseJSONValue(JSONData) as TJSONObject;
   try
     JSONEnumerator := JSONObject.GetEnumerator;
     try
       while JSONEnumerator.MoveNext do begin
         JSONPair := JSONEnumerator.Current;
         ShowMessage(Format('Key=%s Value=%s',
                     [JSONPair.JsonString.ToString,
                      JSONPair.JsonValue.ToString]));
       end;
     finally
       JSONEnumerator.Free;
     end;
   finally
     JSONObject.Free;
   end;
end;

Note that you may need to check if JSONPair.JsonValue has childs and enumerate those childs with another enumerator, recursively.