如何使用 XE2 dbxJSON 解析 JSON

How to parse JSON with XE2 dbxJSON

我正在使用 XE2 并尝试解析机器人发送给 URL 的 JSON 文件。我查看了几种解决方案,但由于我的 Delphi 版本,大多数都不适用。我尝试应用我在此处找到的解决方案:How to parse nested JSON object in Delphi XE2?,但我似乎无法弄清楚如何获取我需要的信息。

JSON 字符串:

{"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}}

为了阅读起来更简单,这里只是 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
}

我正在尝试获取 roll 值。这是我的代码:

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;

我已经将 JSON 字符串放入 JSON 对象,但是当我到达这一行时,我遇到了访问冲突:

ParseJSON := TJSONPair(sVALUE).JsonString.Value;

首先,您不需要将下载的 string 转换为 ASCII 编码 TBytesTJSONObject.ParseJSONValue() 有一个以 string 作为输入的重载。

其次,LJsonObj.Get('ATTITUDE').JsonValue会return一个TJSONObject,你是错误的type-casting一个TJSONPair。但这没关系,因为您随后忽略了 TJSONPair 而是错误地 type-casting 输入参数 sVALUEstringTJSONPair 然后试图访问其 children。这就是您遇到访问冲突的原因。

但即使您能够找到 roll 值的 TJSONPair,您也在 return 其 JsonString(名称)属性,不是其JsonValue(值)属性.

的字符串值

试试这个:

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;