1

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));
2
  • error in function TJSONArray.GetCount: Integer; begin if (FElements = nil) or (FElements.Count = 0) then Exit(0); Result := FElements.Count; end; (FElements = nil) Commented Jan 9, 2016 at 5:50
  • 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)); Commented Jan 9, 2016 at 6:07

2 Answers 2

4
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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

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.