Search code examples
jsondelphidelphi-xe7

Json Array into ListBox/Memo in Delphi xe7


I'm trying to catch the following JSON array :

[{"name":"Bryan","email":"Bryan@hotmail.com"},
 {"name":"Louis","email":"Louis@hotmail.com"},
 {"name":"Maria","email":"Maria@hotmail.com"},
 {"name":"Test","email":"test@hotmail.com"},
 {"name":"Anthony","email":"anthony@hotmail.com"}]

and put it in Memo or ListBox in Delphi : the code is the following :

procedure TForm1.Button1Click(Sender: TObject);
var jv: TJSONValue;
    jo: TJSONObject;
    jp: TJSONPair;
    ja: TJSONArray;
    i: integer;
    j: integer;
begin
    RESTRequest1.Execute;

    jv:=RESTResponse1.JSONValue;


    jo:= TJSONObject.ParseJSONValue(jv.ToString) as TJSONObject;

    try
      for i := 0 to jo.Size - 1 do
      begin
        jp := jo.Get(i);
        if jp.JsonValue is TJSONArray then
        begin
            ja := jp.JsonValue as TJSONArray;
            for j := 0 to ja.Size -1 do
              Memo1.Lines.Add(ja.Get(i).ClassName + ': ' + ja.Get(j).ToString);
        end
        else
          Memo1.Lines.Add(jp.ClassName + ': '+ jp.ToString);

      end;
    finally
      jo.Free;
    end;
end;

When I click in Button I got the following error message :

Invalid class typecast

during debugging the following line has a problem : jo:= TJSONObject.ParseJSONValue(jv.ToString) as TJSONObject;

I don't know how to resolve this problem or this mistake , Could you please help me ?

Thanks.


Solution

  • I'm not sure what the problem of TJSONObject is with the string you posted.
    For some reason it will parse it if you changed it.

    {"Persons":[{"name":"Bryan","email":"Bryan@hotmail.com"},{"name":"Louis","email":"Louis@hotmail.com"},{"name":"Maria","email":"Maria@hotmail.com"},{"name":"Test","email":"test@hotmail.com"},{"name":"Anthony","email":"anthony@hotmail.com"}]}
    

    If I run the code as it is I get the following result enter image description here

    If you don't mind using something different than default Delphi units I would suggest superobject (Link here)
    superobject will parse your JSON edited and as posted.

    Your code would look like this:

    Const
      MyJSON = '[{"name":"Bryan","email":"Bryan@hotmail.com"},{"name":"Louis","email":"Louis@hotmail.com"},{"name":"Maria","email":"Maria@hotmail.com"},{"name":"Test","email":"test@hotmail.com"},{"name":"Anthony","email":"anthony@hotmail.com"}]';    
    procedure ParseJSON;
      var
        obj: ISuperObject;
        Ar: TSuperArray;
        I: integer;
      begin
        obj := SO(MyJSON);
        if obj.IsType(stArray) then
        begin
          Ar := obj.AsArray;
          try
            for I := 0 to Ar.Length-1 do
              L.Add(Ar.O[I].AsString);
          finally
            Ar.Free;
          end;
        end
        else
          L.Add(Obj.AsString);
      end;
    

    Result:
    enter image description here

    For Koul, to get the element names and values.
    Like I said not very pretty code but ok.

    Ar.O[0].AsObject.GetNames.AsArray.S[0]
    

    To cut it up in pieces a bit.

    Ar.O[0] //Get the first element in the array as ISuperObject  
    .AsObject //Get it as TSuperTableString
    .GetNames //Gets all names in the array, in this case "name" and "email"
    .AsArray[0]//Get the first name in the names array.
    

    It will result in email (Names are sorted A-Z)

    You can do the same for the values by calling GetValues instead of GetNames.
    I think the prettiest way to get it will be defining 2x more TSuperArray

    procedure PrintNamesAndValues;
    Var
      Ar, ArNames, ArValues:TSuperArray;
      I: Integer;
    begin
      Ar := SO(<JSON string>).asArray;  
      ArNames := Ar.O[0].AsObject.GetNames.AsArray;
      ArValues := Ar.O[0].AsObject.GetValues.AsArray;
      For I := 0 to ArNames.Length-1 do
        WriteLn(Format('%s: %s',[ArNames.S[I], ArValues.S[I]]));  
    end;
    

    Hope it's all clear enough :)