Home > Software design >  I want to check if there is a specific key in the json object
I want to check if there is a specific key in the json object

Time:01-13

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;

CodePudding user response:

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;

CodePudding user response:

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.
  • Related