I am using XE2 and trying to parse a JSON file sent by a robot to a URL. I've looked at several solutions, but most don't apply due to my version of Delphi. I tried to apply the solution I found here: How to parse nested JSON object in Delphi XE2?, but I can't seem to figure out how to get the information I need.
JSON string:
{"ATTITUDE":{"message_information":{"counter":48023,"frequency":10.002707481384277,"time":{"first_message":"2021-06-02T03:17:20.370144292+00:00","last_message":"2021-06-02T04:37:22.120250362+00:00"}},"pitch":0.5178558826446533,"pitchspeed":0.04289548471570015,"roll":-3.072502613067627,"rollspeed":0.08245258033275604,"time_boot_ms":4827404,"type":"ATTITUDE","yaw":1.652945876121521,"yawspeed":0.1658300906419754},"BATTERY_STATUS":{"battery_function":{"type":"MAV_BATTERY_FUNCTION_UNKNOWN"},"battery_remaining":99,"charge_state":{"type":"MAV_BATTERY_CHARGE_STATE_UNDEFINED"},"current_battery":4,"current_consumed":52,"energy_consumed":-1,"id":0,"mavtype":{"type":"MAV_BATTERY_TYPE_UNKNOWN"},"message_information":{"counter":48022,"frequency":10.0024995803833,"time":{"first_message":"2021-06-02T03:17:20.384144633+00:00","last_message":"2021-06-02T04:37:22.032157658+00:00"}},"temperature":32767,"time_remaining":0,"type":"BATTERY_STATUS","voltages":[65535,65535,65535,65535,65535,65535,65535,65535,65535,65535]},"GLOBAL_POSITION_INT":{"alt":0,"hdg":9470,"lat":0,"lon":0,"message_information":{"counter":48023,"frequency":10.002707481384277,"time":{"first_message":"2021-06-02T03:17:20.364293452+00:00","last_message":"2021-06-02T04:37:22.114859879+00:00"}},"relative_alt":0,"time_boot_ms":4827404,"type":"GLOBAL_POSITION_INT","vx":6,"vy":-12,"vz":0},"GPS_RAW_INT":{"alt":0,"alt_ellipsoid":0,"cog":0,"eph":9999,"epv":0,"fix_type":{"type":"GPS_FIX_TYPE_NO_GPS"},"h_acc":0,"hdg_acc":0,"lat":0,"lon":0,"message_information":{"counter":4773,"frequency":0.9943749904632568,"time":{"first_message":"2021-06-02T03:17:20.950291643+00:00","last_message":"2021-06-02T04:37:21.690087398+00:00"}},"satellites_visible":0,"time_usec":0,"type":"GPS_RAW_INT","v_acc":0,"vel":0,"vel_acc":0},"HEARTBEAT":{"autopilot":{"type":"MAV_AUTOPILOT_ARDUPILOTMEGA"},"base_mode":{"bits":81},"custom_mode":19,"mavlink_version":3,"mavtype":{"type":"MAV_TYPE_SUBMARINE"},"message_information":{"counter":4803,"frequency":1.0002082586288452,"time":{"first_message":"2021-06-02T03:17:18.825804090+00:00","last_message":"2021-06-02T04:37:21.134719064+00:00"}},"system_status":{"type":"MAV_STATE_CRITICAL"},"type":"HEARTBEAT"},"MISSION_CURRENT":{"message_information":{"counter":48023,"frequency":10.002707481384277,"time":{"first_message":"2021-06-02T03:17:20.346736191+00:00","last_message":"2021-06-02T04:37:22.092055518+00:00"}},"seq":0,"type":"MISSION_CURRENT"},"NAMED_VALUE_FLOAT":{"message_information":{"counter":422608,"frequency":87.98834228515625,"time":{"first_message":"2021-06-02T03:17:18.835553199+00:00","last_message":"2021-06-02T04:37:22.112692363+00:00"}},"name":["S","t","i","c","k","M","o","d","e","\u0000"],"time_boot_ms":4827404,"type":"NAMED_VALUE_FLOAT","value":0.0},"NAV_CONTROLLER_OUTPUT":{"alt_error":-3.370908737182617,"aspd_error":0.0,"message_information":{"counter":48023,"frequency":10.002707481384277,"time":{"first_message":"2021-06-02T03:17:20.346971656+00:00","last_message":"2021-06-02T04:37:22.097877400+00:00"}},"nav_bearing":94,"nav_pitch":29.67095375061035,"nav_roll":-176.0414276123047,"target_bearing":90,"type":"NAV_CONTROLLER_OUTPUT","wp_dist":0,"xtrack_error":0.0},"PARAM_VALUE":{"message_information":{"counter":690,"frequency":172.5,"time":{"first_message":"2021-06-02T03:17:17.942380315+00:00","last_message":"2021-06-02T03:17:22.780401008+00:00"}},"param_count":689,"param_id":["R","C","1","6","_","D","Z","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000"],"param_index":688,"param_type":{"type":"MAV_PARAM_TYPE_INT16"},"param_value":0.0,"type":"PARAM_VALUE"},"POWER_STATUS":{"Vcc":4796,"Vservo":4817,"flags":{"bits":6},"message_information":{"counter":48023,"frequency":10.002707481384277,"time":{"first_message":"2021-06-02T03:17:20.338866582+00:00","last_message":"2021-06-02T04:37:22.086196344+00:00"}},"type":"POWER_STATUS"},"RAW_IMU":{"id":0,"message_information":{"counter":48022,"frequency":10.0024995803833,"time":{"first_message":"2021-06-02T03:17:20.392561785+00:00","last_message":"2021-06-02T04:37:22.077733412+00:00"}},"temperature":0,"time_usec":532436271,"type":"RAW_IMU","xacc":577,"xgyro":82,"xmag":-221,"yacc":-13,"ygyro":42,"ymag":319,"zacc":836,"zgyro":165,"zmag":-254},"RC_CHANNELS":{"chan10_raw":1100,"chan11_raw":1100,"chan12_raw":0,"chan13_raw":0,"chan14_raw":0,"chan15_raw":0,"chan16_raw":0,"chan17_raw":0,"chan18_raw":0,"chan1_raw":1500,"chan2_raw":1500,"chan3_raw":1500,"chan4_raw":1500,"chan5_raw":1500,"chan6_raw":1500,"chan7_raw":1500,"chan8_raw":1500,"chan9_raw":1100,"chancount":0,"message_information":{"counter":48023,"frequency":10.002707481384277,"time":{"first_message":"2021-06-02T03:17:20.368143023+00:00","last_message":"2021-06-02T04:37:22.118597838+00:00"}},"rssi":0,"time_boot_ms":4827404,"type":"RC_CHANNELS"},"SCALED_IMU2":{"message_information":{"counter":48022,"frequency":10.0024995803833,"time":{"first_message":"2021-06-02T03:17:20.394756436+00:00","last_message":"2021-06-02T04:37:22.079559371+00:00"}},"temperature":0,"time_boot_ms":4827403,"type":"SCALED_IMU2","xacc":607,"xgyro":79,"xmag":0,"yacc":-197,"ygyro":45,"ymag":0,"zacc":850,"zgyro":166,"zmag":0},"SCALED_PRESSURE":{"message_information":{"counter":48022,"frequency":10.0024995803833,"time":{"first_message":"2021-06-02T03:17:20.396526198+00:00","last_message":"2021-06-02T04:37:22.081281790+00:00"}},"press_abs":985.1317138671875,"press_diff":-0.42578125,"temperature":3843,"time_boot_ms":4827403,"type":"SCALED_PRESSURE"},"SERVO_OUTPUT_RAW":{"message_information":{"counter":48023,"frequency":10.002707481384277,"time":{"first_message":"2021-06-02T03:17:20.366297689+00:00","last_message":"2021-06-02T04:37:22.116724015+00:00"}},"port":0,"servo10_raw":0,"servo11_raw":0,"servo12_raw":0,"servo13_raw":0,"servo14_raw":0,"servo15_raw":0,"servo16_raw":0,"servo1_raw":1500,"servo2_raw":1500,"servo3_raw":1500,"servo4_raw":1500,"servo5_raw":1500,"servo6_raw":1500,"servo7_raw":1100,"servo8_raw":1500,"servo9_raw":0,"time_usec":532437021,"type":"SERVO_OUTPUT_RAW"},"STATUSTEXT":{"message_information":{"counter":3,"frequency":null,"time":{"first_message":"2021-06-02T03:17:18.844799660+00:00","last_message":"2021-06-02T03:17:18.847208006+00:00"}},"severity":{"type":"MAV_SEVERITY_INFO"},"text":["P","X","4","v","2"," ","0","0","2","6","0","0","3","8"," ","3","4","4","E","5","0","1","4"," ","2","0","3","9","3","8","4","E","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000","\u0000"],"type":"STATUSTEXT"},"SYSTEM_TIME":{"message_information":{"counter":96045,"frequency":20.005207061767578,"time":{"first_message":"2021-06-02T03:17:20.346859002+00:00","last_message":"2021-06-02T04:37:22.095579470+00:00"}},"time_boot_ms":4827403,"time_unix_usec":1622646643891000,"type":"SYSTEM_TIME"},"SYS_STATUS":{"battery_remaining":-1,"current_battery":3,"drop_rate_comm":0,"errors_comm":0,"errors_count1":0,"errors_count2":0,"errors_count3":0,"errors_count4":0,"load":309,"message_information":{"counter":48022,"frequency":10.0024995803833,"time":{"first_message":"2021-06-02T03:17:20.398575174+00:00","last_message":"2021-06-02T04:37:22.084398874+00:00"}},"onboard_control_sensors_enabled":{"bits":2137095},"onboard_control_sensors_health":{"bits":2161671},"onboard_control_sensors_present":{"bits":2161671},"type":"SYS_STATUS","voltage_battery":28},"VFR_HUD":{"airspeed":0.0,"alt":3.369999885559082,"climb":0.0,"groundspeed":0.0,"heading":94,"message_information":{"counter":48023,"frequency":10.002707481384277,"time":{"first_message":"2021-06-02T03:17:20.376004716+00:00","last_message":"2021-06-02T04:37:22.125711470+00:00"}},"throttle":0,"type":"VFR_HUD"},"VIBRATION":{"clipping_0":0,"clipping_1":0,"clipping_2":0,"message_information":{"counter":48022,"frequency":10.0024995803833,"time":{"first_message":"2021-06-02T03:17:20.390603900+00:00","last_message":"2021-06-02T04:37:22.037444653+00:00"}},"time_usec":4827304899,"type":"VIBRATION","vibration_x":0.772567629814148,"vibration_y":1.1524462699890137,"vibration_z":0.9556428790092468}}
To make it more simple to read, here is just the "ATTITUDE" part of the JSON:
{
"message_information": {
"counter": 49703,
"frequency": 10.002615928649902,
"time": {
"first_message": "2021-06-02T03:17:20.370144292+00:00",
"last_message": "2021-06-02T04:40:10.111812828+00:00"
}
},
"pitch": 0.5262367725372314,
"pitchspeed": -0.0031247171573340893,
"roll": -3.0792529582977295,
"rollspeed": 0.09408686310052872,
"time_boot_ms": 4995408,
"type": "ATTITUDE",
"yaw": 1.6096009016036987,
"yawspeed": 0.0655876100063324
}
I am trying to get the roll
value. Here is my code:
function TForm_OV_REC.ParseJSON(sJSON,sITEM,sVALUE : String) : String;
var
LJsonObj : TJSONObject;
LJPair : TJSONPair;
LItems : TJSONValue;
s :string;
begin
LJsonObj := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(sJSON),0) as TJSONObject;
try
LItems := LJsonObj.Get(sITEM).JsonValue;
LJPair := TJSONPair(LItems);
ParseJSON := TJSONPair(sVALUE).JsonString.Value;
finally
LJsonObj.Free;
end;
end;
procedure TForm_OV_REC.timerRESTAPITimer(Sender: TObject);
var
MyString,sJSON : String;
IdHTTP: TIdHTTP;
begin
IdHTTP := TIdHTTP.Create(nil);
IdHTTP.ConnectTimeout := 100;
try
MyString := ParseJSON(IdHTTP.Get('http://192.168.2.2:4777/mavlink'),'ATTITUDE','roll');
finally
IdHTTP.Free;
end;
end;
I got as far as putting the JSON string into the JSON object, but I get an Access Violation when I get to this line:
ParseJSON := TJSONPair(sVALUE).JsonString.Value;
Well, for starters, you don't need to convert your downloaded string
to an ASCII encoded TBytes
. TJSONObject.ParseJSONValue()
has an overload that takes a string
as input.
Second, LJsonObj.Get('ATTITUDE').JsonValue
will return a TJSONObject
, which you are incorrectly type-casting to a TJSONPair
. But that doesn't matter, since you are then ignoring that TJSONPair
and instead incorrectly type-casting the input parameter sVALUE
from a string
to a TJSONPair
and then trying to access its children. That is why you are getting the Access Violation.
But even if you were able to find the TJSONPair
for the roll
value, you are returning the string value of its JsonString
(name) property, not the string value of its JsonValue
(value) property.
Try this instead:
function TForm_OV_REC.ParseJSON(sJSON, sITEM, sVALUE : String) : String;
var
LJsonVal : TJSONValue;
LJPair : TJSONPair;
begin
Result := '';
LJsonVal := TJSONObject.ParseJSONValue(sJSON);
if LJsonVal = nil then Exit;
try
LJPair := (LJsonVal as TJSONObject).Get(sITEM);
if LJPair = nil then Exit;
LJPair := (LJPair.JsonValue as TJSONObject).Get(sVALUE);
if LJPair = nil then Exit;
Result := LJPair.JsonValue.Value;
finally
LJsonVal.Free;
end;
end;
procedure TForm_OV_REC.timerRESTAPITimer(Sender: TObject);
var
MyString, sJSON : String;
IdHTTP: TIdHTTP;
begin
IdHTTP := TIdHTTP.Create(nil);
try
IdHTTP.ConnectTimeout := 100;
sJSON := IdHTTP.Get('http://192.168.2.2:4777/mavlink');
finally
IdHTTP.Free;
end;
MyString := ParseJSON(sJSON, 'ATTITUDE', 'roll');
...
end;