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.