delphi parse jsonarray with System.JSON

10,486

Solution 1

arrayjson:=JSONObject2.ParseJSONValue('current_condition')  as TJSONArray;

This attempts to parse the text

current_condition

as though it were JSON. It is not. Hence arrayjson is nil, and hence the resulting runtime error. Replace that line of code with:

arrayjson := JSONObject2.GetValue('current_condition') as TJSONArray;

For example, this program:

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.JSON;

const
  Text =
    '{ "data":{ "current_condition":[ { "cloudcover":"0", "FeelsLikeC":"-9", "FeelsLikeF":"15", "humidity":"93", ' +
    '"observation_time":"04:10 AM", "precipMM":"0.0", "pressure":"1007", "temp_C":"-6", "temp_F":"21", "visibility":"10", ' +
    '"weatherCode":"113", "weatherDesc":[], "weatherIconUrl":[], "winddir16Point":"SE", "winddirDegree":"130", "windspeedKmph":"7", "windspeedMiles":"4" } ] } }';

procedure Main;
var
  JSONObject, JSONObject2, currcond: TJSONObject;
  arrayjson: TJSONArray;
begin
  JSONObject := TJSONObject.ParseJSONValue(Text) as TJSONObject;
  JSONObject2 := JSONObject.GetValue('data') as TJSONObject;
  arrayjson := JSONObject2.GetValue('current_condition') as TJSONArray;
  currcond := arrayjson.Items[0] as TJSONObject;
  Writeln(currcond.GetValue('observation_time').Value);
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

outputs

04:10 AM

In the simple code above, I've not made any attempt to add error checking. You should do so.

Solution 2

Just as an alternative to the solution provided but using mORMot:

{$APPTYPE CONSOLE}

uses
  SynCommons;

const
    Text =  '{ "data":{ "current_condition":[ { "cloudcover":"0", "FeelsLikeC":"-9", "FeelsLikeF":"15", "humidity":"93", ' +
            '"observation_time":"04:10 AM", "precipMM":"0.0", "pressure":"1007", "temp_C":"-6", "temp_F":"21", "visibility":"10", ' +
            '"weatherCode":"113", "weatherDesc":[], "weatherIconUrl":[], "winddir16Point":"SE", "winddirDegree":"130", "windspeedKmph":"7", "windspeedMiles":"4" } ] } }';

var Data , CurrentConditionArray : TDocVariantData;
    Current_Condition , Json : Variant;
begin
  Json := _Json(Text);
  // Alternative 1
  Current_Condition := Json.data.current_condition._(0);
  Assert( Current_Condition.observation_time = '04:10 AM' );

  // Alternative 2 slightly faster
  Data := TDocVariantData(Json).O['data']^;
  CurrentConditionArray := Data.A['current_condition']^;
  Current_Condition := CurrentConditionArray.Values[0];
  Assert( TDocVariantData(Current_Condition).Value['precipMM'] = '0.0' );
end.

This should work from Delphi 7 to 10.4. Please, find further details and alternatives in the amazing documentation

Share:
10,486
Drdead
Author by

Drdead

Updated on June 05, 2022

Comments

  • Drdead
    Drdead almost 2 years

    Using Delphi XE8's System.JSON, I cannot parse a jsonarray

    Sample Json:

    {
        "data":{
            "current_condition":[
                {
                    "cloudcover":"0",
                    "FeelsLikeC":"-9",
                    "FeelsLikeF":"15",
                    "humidity":"93",
                    "observation_time":"04:10 AM",
                    "precipMM":"0.0",
                    "pressure":"1007",
                    "temp_C":"-6",
                    "temp_F":"21",
                    "visibility":"10",
                    "weatherCode":"113",
                    "weatherDesc":[
                        
                    ],
                    "weatherIconUrl":[
                        
                    ],
                    "winddir16Point":"SE",
                    "winddirDegree":"130",
                    "windspeedKmph":"7",
                    "windspeedMiles":"4"
                }
            ]
        }
    }
    

    using the code:

    memores: TStringList;
    currcond: TJSONObject;
    
    memores2.Text := http.Get ('url');
    JSONObject := TJSONObject.ParseJSONValue(memores2.Text) as TJSONObject;
    Memores1.add('current_condition');
    JSONObject2 := JSONObject.GetValue('data')   as TJSONObject;
    arrayjson := JSONObject2.ParseJSONValue('current_condition')  as TJSONArray;
    currcond := arrayjson.Items[0] as TJSONObject;
    memores1.Add((currcond.GetValue('cloudcover').Value));
    
    • Drdead
      Drdead over 8 years
      error in function TJSONArray.GetCount: Integer; begin if (FElements = nil) or (FElements.Count = 0) then Exit(0); Result := FElements.Count; end; (FElements = nil)
    • Drdead
      Drdead over 8 years
      Done JSONObject2:=JSONObject.GetValue('data') as TJSONObject; arrayjson:=JSONObject2.GetValue('current_condition') as TJSONArray; currcond := arrayjson.Items[0] as TJSONObject; // parse currcond/// memores1.Add((currcond.GetValue('cloudcover').Value));