skip to Main Content

I want to check if the JSON object has the key "error". If it has, I want to "continue" the loop, otherwise the program can go to all the loop.

This is the JSON:

[
    {
        "cenario": {
            "origem": "",
            "out": "SNC",
            "country": "",
        },
        "item": "0015963",
        "cod": "17894904009319",
        "nat_rec": null
    },
    {
        "item": "0012868",
        "error": "product unavailable",
        "status": "unavailable",
    }
]

How can I check if the object that I’m reading has the key "error" or not?

I tried:

jValue.FindValue('error') // The problem it's going to search for all objects.
jValue.TryGetValue('error', jArray) // if it doesn't find the key in the index that it's searching at the moment, it breaks the application.

I’m doing:

response:= IdHTTP.Get(url);

jValue:= TJsonObject.ParseJSONValue(response);

for x := 0 to 2 do
begin
    
  if jValue.TryGetValue('error', jvalue) then
  begin
    continue;
  end;

  memo.Lines.Add('cod_item :' + jValue.GetValue<string>('['+intToStr(x)+'].item'));
  memo.Lines.Add('cod: ' + jValue.GetValue<string>('['+intToStr(x)+'].cod'));
end;

2

Answers


  1. You can parse it to an array and iterate the array. The two functions HasValueAtObjectKey & GetValueAtObjectKey demonstrate two different ways of checking the object for the key.

    program JsonTest;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      System.SysUtils,
      System.JSON;
    
    const TEST_JSON = '[' +
                      '   {' +
                      '       "cenario": {' +
                      '           "origem": "",' +
                      '           "out": "SNC",' +
                      '           "country": ""' +
                      '       },' +
                      '       "item": "0015963",' +
                      '       "cod": "17894904009319",' +
                      '       "nat_rec": null' +
                      '   },' +
                      '   {' +
                      '       "item": "0012868",' +
                      '       "error": "product unavailable",' +
                      '       "status": "unavailable"' +
                      '   }' +
                      ']';
    
    function HasValueAtObjectKey(AKeyName: String; AJsonObject: TJsonObject): Boolean;
    var
      LValue: TJsonValue;
    begin
      Result := AJsonObject.TryGetValue(AKeyName, LValue);
    end;
    
    function GetValueAtObjectKey(AKeyName: String; AJsonObject: TJsonObject; var AHasValue: Boolean): String;
    begin
      try
        Result := AJsonObject.GetValue(AKeyName).Value;
        AHasValue := TRUE;
      except
        AHasValue := FALSE;
      end;
    end;
    
    begin
      try
        var LArray := TJSONObject.ParseJSONValue(TEST_JSON) as TJSONArray;
        try
          var i:=1;
          for var LArrayValue in  LArray do
          begin
            var LHasValue: Boolean;
            var LErroVal := ValueAtObjectKey('error', (LArrayValue As TJSONObject), LHasValue);
            if LHasValue then
              Writeln('Object ', i, ' Has error: ', LErroVal)
            else
              Writeln('Object ', i, ' Has no error: ');
              Writeln('Object ', i, ' HasValueAtObjectKey: ', HasValueAtObjectKey('error', (LArrayValue As TJSONObject)));
            Inc(i);
          end;
        finally
          LArray.Free;
        end;
        ReadLn;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end.
    
    Login or Signup to reply.
  2. In your code, jValue is pointing at a TJSONArray, so when you call TryGetValue('error') on it, you are looking for a field named 'error' on the array itself, which obviously is not going to work. That would only work when called on a TJONObject instead.

    You would need to include each object’s index when querying for the 'error' field on the array itself, eg:

    response := IdHTTP.Get(url);
    
    jValue := TJsonObject.ParseJSONValue(response);
    try
      jArray := jValue as TJSONArray;
      for x := 0 to jArray.Count-1 do
      begin
        if jArray.FindValue('['+IntToStr(x)+'].error') = nil then
          continue;
        Memo.Lines.Add('cod_item :' + jArray.GetValue<string>('['+IntToStr(x)+'].item'));
        Memo.Lines.Add('cod: ' + jArray.GetValue<string>('['+IntToStr(x)+'].cod'));
      end;
    finally
      jValue.Free;
    end;
    

    Alternatively, you can iterate the actual objects in memory instead of searching via paths, eg:

    response := IdHTTP.Get(url);
    
    jValue := TJsonObject.ParseJSONValue(response);
    try
      jArray := jValue as TJSONArray;
      for x := 0 to jArray.Count-1 do
      begin
        jObj := jArray[x] as TJSONObject;
        if jObj.GetValue('error') = nil then
        begin
          Memo.Lines.Add('cod_item :' + jObj.GetValue('item').Value);
          Memo.Lines.Add('cod: ' + jObj.GetValue('cod').Value);
        end;
      end;
    finally
      jValue.Free;
    end;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search