Stack Overflow Asked by Stanley Mladenek on February 17, 2021
I need to read the fuelTanks
value. Everything before that goes to me / in fact there are more items /, but I don’t know how to read the fuelTanks
field.
My current code:
procedure TMain.JsonAktStav;
var
JSonObject: TJSonObject;
data: TJSONArray;
JSonValue: TJSonValue;
//*** bJSon is the TByteStream from the previous procedure ***
idx: integer;
begin
JSonObject := TJSonObject.Create;
JSonValue := JSonObject.ParseJSONValue(bJSON.Bytes, 0, bJSON.Size) as TJSONObject;
JSonValue := (JSonValue as TJSONObject).Get('response').JSonValue;
JSonValue := (JSonValue as TJSONObject).Get('data').JSonValue;
data := JSonValue as TJSONArray;
for idx := 0 to data.Size - 1 do
begin
if (JSonValue is TJSONArray) then
vehicleid := ((JSonValue as TJSONArray).Items[idx] as TJSonObject).Get('vehicleid').JSonValue.Value;
end;
JSonObject.Free;
bJSON.Free;
end;
TIdHTTP
will return the JSON response, which is listed below:
{
"response": {
"actionName": "getActualStates",
"code": 200,
"data": [
{
"vehicleid": 4500,
"temperatures": [],
"fuelTanks": [
{
"fuelTankNumber": 1,
"status": 247
},
{
"fuelTankNumber": 2,
"status": 65
}
]
},
{
"vehicleid": 4751,
"temperatures": [],
"fuelTanks": [
{
"fuelTankNumber": 1,
"status": 462
},
{
"fuelTankNumber": 2,
"status": 380
}
]
}
]
}
}
I can’t read "fuelTankNumber"
and "status"
.
fuelTanks
is an array of objects, and you already know how to access child fields that are arrays and objects, so you just need to expand your code further to iterate deeper into the JSON structure, eg:
procedure TMain.JsonAktStav;
var
JSonValue: TJSonValue;
data, fuelTanks: TJSONArray;
vehicle, fuelTank: TJSonObject;
idx, idx2: integer;
vehicleid, fuelTankNumber, status: integer;
begin
try
//*** bJSon is the TByteStream from the previous procedure ***
JSonValue := JSonObject.ParseJSONValue(bJSON.Bytes, 0, bJSON.Size);
if JSonValue <> nil then
try
JSonObject := JSonValue as TJSONObject;
JSonObject := JSonObject.GetValue<TJSONObject>('response');
data := JSonObject.GetValue<TJSONArray>('data');
for idx := 0 to data.Size - 1 do
begin
vehicle := data.Items[idx] as TJSONObject;
vehicleid := vehicle.GetValue<Integer>('vehicleid');
// use vehicleid as needed...
fuelTanks := vehicle.GetValue<TJSONArray>('fuelTanks');
for idx2 := 0 to fuelTanks.Size - 1 do
begin
fuelTank := fuelTanks.Items[idx2] as TJSONObject;
fuelTankNumber := fuelTank.GetValue<Integer>('fuelTankNumber');
status := fuelTank.GetValue<Integer>('status');
// use fuelTankNumber and status as needed...
end;
end;
finally
JSonValue.Free;
end;
finally
bJSON.Free;
end;
end;
Answered by Remy Lebeau on February 17, 2021
As I told before, I think the best way to work with JSON is serialization and deserialization.
So, first of all you have to describe objects that represents your json (I've made it in unit):
unit Unit3;
interface
TYPE
TMyDoubleArray = Array OF double;
TMyFuelObject = CLASS(TObject)
PRIVATE
FFuelTankNumber:integer;
FStatus:integer;
procedure SetFuelTankNumber(const Value: integer);
procedure SetStatus(const Value: Integer);
PUBLIC
property fuelTankNumber:integer read FFuelTankNumber write SetFuelTankNumber;
property status:Integer read FStatus WRITE SetStatus;
END;
TMyFuelArray = ARRAY OF TMyFuelObject;
TMyAnotherOneInnerObject = CLASS(TObject)
private
FVehicleId:Integer;
FTemperatures:TMyDoubleArray;
FFuelTanks:TMyFuelArray;
procedure SetFuelTanks(const Value: TMyFuelArray);
procedure SetTemperatures(const Value: TMyDoubleArray);
procedure SetVehicleId(const Value: integer);
PUBLIC
property vehicleid:integer read FVehicleId WRITE SetVehicleId;
property temperatures:TMyDoubleArray read FTemperatures write SetTemperatures; //Is it double?
property fuelTanks:TMyFuelArray read FFuelTanks write SetFuelTanks;
END;
TMyInnerArray = ARRAY of TMyAnotherOneInnerObject;
TMyInnerObject = CLASS(TObject)
PRIVATE
FActionName:String;
FCode:SmallInt;
FData:TMyInnerArray;
procedure SetActionName(const Value: String);
procedure SetCode(const Value: SmallInt);
procedure SetData(const Value: TMyInnerArray);
PUBLIC
property actionName:String read FActionName write SetActionName;
PROPERTY code:SmallInt read FCode write SetCode;
PROPERTY data:TMyInnerArray read FData write SetData;
END;
TMyObject = CLASS(TObject)
PRIVATE
FResponse:TMyInnerObject;
procedure SetResponse(const Value: TMyInnerObject);
PUBLIC
PROPERTY response:TMyInnerObject READ FResponse WRITE SetResponse;
END;
implementation
{ TMyObject }
procedure TMyObject.SetResponse(const Value: TMyInnerObject);
begin
FResponse := Value;
end;
{ TMyInnerObject }
procedure TMyInnerObject.SetActionName(const Value: String);
begin
FActionName := Value;
end;
procedure TMyInnerObject.SetCode(const Value: SmallInt);
begin
FCode := Value;
end;
procedure TMyInnerObject.SetData(const Value: TMyInnerArray);
begin
FData := Value;
end;
{ TMyAnotherOneInnerObject }
procedure TMyAnotherOneInnerObject.SetFuelTanks(const Value: TMyFuelArray);
begin
FFuelTanks := Value;
end;
procedure TMyAnotherOneInnerObject.SetTemperatures(const Value: TMyDoubleArray);
begin
FTemperatures := Value;
end;
procedure TMyAnotherOneInnerObject.SetVehicleId(const Value: integer);
begin
FVehicleId := Value;
end;
{ TMyFuelObject }
procedure TMyFuelObject.SetFuelTankNumber(const Value: integer);
begin
FFuelTankNumber := Value;
end;
procedure TMyFuelObject.SetStatus(const Value: Integer);
begin
FStatus := Value;
end;
end.
Yes, there is a plenty of code. But if trying to work with this information in future it can be easier than parse every field in json.
Then you have to parse it. I've put your JSON into Memo on the form and implemented this OnButtonClick event:
uses ... REST.Json, Unit3;
...
procedure TForm2.Button1Click(Sender: TObject);
var json:string;
myObject:TMyObject;
begin
json := Memo1.Text;
try
myObject := TJson.JsonToObject<TMyObject>(json);
//do with myObject everything you want
finally
FreeAndNil(myObject);
end;
end;
Then I got this:
To get values try this code:
if length(myObject.response.data) > 0 then
for i := 0 to length(myObject.response.data) - 1 do
with myObject.response.data[i] do
if length(FuelTanks) > 0 then
for j := 0 to length(FuelTanks) - 1 do
ShowMessage(FuelTanks[j].FuelTankNumber.ToString); // or inttostr(FuelTanks[j].FuelTankNumber)
Answered by mrNone on February 17, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP