3

I have a similar problem to Delphi parse JSON array or array, but the answers do not fit my need.

I have this JSON:

[
  {
    "total": "9",
    "page": "9",
    "records": "99",
    "rows": [
      {
        "id": "62316",
        "titleId": "47243",
        "subject": [
          "000607",
          "000607_",
          "001727"
        ],
        "keyFeatures": [
          "AI",
          "URL"
        ]
      },
      {
        "id": "66",
        "titleId": "47243",
        "subject": [
          "000607",
          "000607_",
          "001727"
        ],
        "keyFeatures": [
          "KK"
        ]
      }
    ],
    "suggestion": "90"
  }
]

I would like to write all f.e. "keyFeatures" of every "id" in a memo, like this:

1: 62316   KeyFeatures: AI,URL
2: 66      KeyFeatures: KK   
procedure TIFForm1.ParseJson(StrJson: string);
var
  LJsonArr: TJSONArray;
  LJsonArrRow: TJSONArray;
  vJSONObject: TJSONObject;
  vJSONPair: TJSONPair;
  vJSONObjectKF: TJSONObject;
  vJSONPairKF: TJSONPair;
  vJasonArrRows: TJSONArray;
  vJSONValue: TJSONValue;
  LJSONAttribute: String;
  LJSONKF_key: String;
  LJSONValue: String;
  i: integer;
begin
  LJsonArr := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(StrJson), 0) as TJSONArray;
  if LJsonArr <> nil then
  try
    // rows
    vJasonArrRows := LJsonArr as TJSONArray;
    for vJSONValue in vJasonArrRows do
    begin
      i := i + 1;
      vJSONObject := vJSONValue as TJSONObject;
      vJSONPair := vJSONObject.get('id');
      LJSONAttribute := vJSONPair.JsonString.Value;
      vJSONValue := vJSONPair.JsonValue.Value;
      vJSONObjectKF := vJSONValue as TJSONObject;
      vJSONPairKF := vJSONObject.Get('keyFeatures');
      LJSONKF_key := vJSONPairKF.JsonString.Value;
      // How can I here merge all keyFeatures together with , separated?
      //Edit: My Serializer
      rowresult.KeyFeatures := serialize(vJSONObject, 'keyFeatures');
      Memo5.Lines.Add(Format('%d: %s KeyFeatures: %s', [i, rowresult.id, rowresult.keyFeatures]));
    end;
  finally
    LJsonArr.Free;
  end;
end;

Moreover, it would be handy if I could ask for the type of the JSON elements. Here is an example with keyFeatures which is again an JSON Array. But there could be more unknown named JSON keys which are also array, and these ones should also be written in the Memo. Is there a solution?

EDIT: I have solved it this way with the help from the DP Answer, look below.

function TIFForm1.serialize(MyJSONObject: TJSONObject; keystring: string): string;
var
  KeyFeatures: TJSONValue;
  FeatureList: TStringList;
  FeatureItem: TJSONValue;
begin
  KeyFeatures := (MyJSONObject as TJSONObject).GetValue(keystring);
  if KeyFeatures is TJSONArray then
  begin
    FeatureList := TStringList.Create;
    try
      for FeatureItem in TJSONArray(KeyFeatures) do
        FeatureList.Add(FeatureItem.Value);
      Result := FeatureList.CommaText;
    finally
      FeatureList.Free;
    end;
  end
  else
  begin
    Result := KeyFeatures.Value;
  end;
end;
4
  • 2
    Start by writing code to read a simple JSON array of scalars. Once you have mastered that, learn to read a JSON object. Then put the two together. Don't attempt to run before you can walk. Commented Aug 17, 2019 at 13:44
  • I would prefer learning by examples and if you know the change of my program why do you not provide tve fee code lines, best Commented Aug 17, 2019 at 14:17
  • 2
    So learn by examples. Find examples that do what I outlined in my comment above. Commented Aug 17, 2019 at 16:25
  • @Remy Lebeau Thanks for editing my post. Commented Aug 18, 2019 at 18:52

1 Answer 1

6

A nice guy from Delphipraxis DP has provided a very sophisticated solution:

     procedure TForm1.Button1Click(Sender: TObject);
     var
       DataBase: String;
       JsonArray: TJSONArray;
       ArrayElement: TJSonValue;
       RowValue: TJSonValue;
       RowItem: TJSonValue;
       keyFeatures: TJSonValue;
       FeatureItem: TJSonValue;
       FeatureList: TStringlist;
       Id: Integer;
       Index: Integer;
     begin
       Memo1.Clear;
       DataBase :=
         '[{"total":"9","page":"9","records":"99","rows":[{"id":"62316","titleId":"47243","subject":'
         + '["000607","000607_","001727"],"keyFeatures":["AI","URL"]},{"id":"66","titleId":"47243","subject":'
         + '["000607","000607_","001727"],"keyFeatures":["KK"]}],"suggestion":"90"}]';

       JsonArray := TJSonObject.ParseJSONValue(DataBase) as TJSONArray;
       try
         Index := 1;
         for ArrayElement in JsonArray do
         begin
           RowValue := (ArrayElement as TJSonObject).GetValue('rows');
           if RowValue is TJSONArray
           then
           begin
             for RowItem in TJSONArray(RowValue) do
             begin
               RowItem.TryGetValue('id', Id);
               keyFeatures := (RowItem as TJSonObject).GetValue('keyFeatures');
               if keyFeatures is TJSONArray
               then
               begin
                 FeatureList := TStringlist.Create;
                 try
                   for FeatureItem in TJSONArray(keyFeatures) do
                     FeatureList.Add(FeatureItem.Value);
                   Memo1.Lines.Add(Format('%d: %d KeyFeatures: %s', [Index, Id, FeatureList.CommaText]));
                 finally
                   FeatureList.Free;
                 end;
               end;
             end;
           end;
           inc(Index);
         end;
       finally
         JsonArray.Free;
       end;
     end;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.