如何使用 XE2 dbxJSON 解析数组 JSON

问题描述

继我之前的问题:How to parse JSON with XE2 dbxJSON

关于如何从 JSON 字符串中获取值,我有明确的答案。我现在需要从数组中获取值。

完整的 JSON 字符串:

{"ATTITUDE":{"message_information":{"counter":45942,"frequency":10.07058334350586,"time":{"first_message":"2021-06-02T04:17:19.713053488+00:00","last_message":"2021-06-02T05:33:21.925390505+00:00"}},"pitch":0.39779675006866455,"pitchspeed":0.04370392858982086,"roll":-3.1154606342315674,"rollspeed":0.29034918546676636,"time_boot_ms":4587189,"type":"ATTITUDE","yaw":2.762258768081665,"yawspeed":0.39911729097366333},"AutopILOT_VERSION":{"board_version":0,"capabilities":{"bits":10695},"flight_custom_version":[48,53,102,101,100,52,57,98],"flight_sw_version":50660607,"message_information":{"counter":1,"frequency":null,"time":{"first_message":"2021-06-02T05:03:34.953044355+00:00","last_message":"2021-06-02T05:03:34.953068261+00:00"}},"middleware_custom_version":[56,48,97,50],"middleware_sw_version":0,"os_custom_version":[49,98,56],"os_sw_version":0,"product_id":0,"type":"AutopILOT_VERSION","uid":0,"uid2":[0,0],"vendor_id":0},"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":51,"energy_consumed":-1,"id":0,"mavtype":{"type":"MAV_BATTERY_TYPE_UNKNowN"},"message_information":{"counter":45443,"frequency":9.961201667785645,"time":{"first_message":"2021-06-02T04:17:19.729121346+00:00","last_message":"2021-06-02T05:33:21.936851877+00:00"}},"temperature":32767,"time_remaining":0,"type":"BATTERY_STATUS","voltages":[65535,65535,65535]},"COMMAND_ACK":{"command":{"type":"MAV_CMD_REQUEST_PROTOCOL_VERSION"},"message_information":{"counter":2,"time":{"first_message":"2021-06-02T05:03:34.954980156+00:00","last_message":"2021-06-02T05:03:35.688089082+00:00"}},"progress":0,"result":{"type":"MAV_RESULT_UNSUPPORTED"},"result_param2":0,"target_component":0,"target_system":0,"type":"COMMAND_ACK"},"GLOBAL_POSITION_INT":{"alt":0,"hdg":15816,"lat":0,"lon":0,"message_information":{"counter":45452,"frequency":9.963173866271973,"time":{"first_message":"2021-06-02T04:17:19.707524674+00:00","last_message":"2021-06-02T05:33:21.943859157+00:00"}},"relative_alt":0,"time_boot_ms":4587209,"type":"GLOBAL_POSITION_INT","vx":-10,"vy":11,"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,"message_information":{"counter":4532,"frequency":0.99364173412323,"time":{"first_message":"2021-06-02T04:17:20.312445519+00:00","last_message":"2021-06-02T05:33:21.692667024+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":4563,"frequency":1.0,"time":{"first_message":"2021-06-02T04:17:17.848160794+00:00","last_message":"2021-06-02T05:33:21.539669615+00:00"}},"system_status":{"type":"MAV_STATE_ACTIVE"},"type":"HEARTBEAT"},"MISSION_COUNT":{"count":0,"time":{"first_message":"2021-06-02T05:03:37.486328037+00:00","last_message":"2021-06-02T05:03:37.486349756+00:00"}},"mission_type":{"type":"MAV_MISSION_TYPE_MISSION"},"target_component":190,"target_system":255,"type":"MISSION_COUNT"},"MISSION_CURRENT":{"message_information":{"counter":45414,"frequency":9.95484447479248,"time":{"first_message":"2021-06-02T04:17:19.702201949+00:00","last_message":"2021-06-02T05:33:21.889268605+00:00"}},"seq":0,"type":"MISSION_CURRENT"},"NAMED_VALUE_FLOAT":{"message_information":{"counter":399816,"frequency":87.60210418701172,"time":{"first_message":"2021-06-02T04:17:17.857721885+00:00","last_message":"2021-06-02T05:33:21.912362180+00:00"}},"name":["S","t","i","c","k","M","o","d","e","\u0000"],"time_boot_ms":4587170,"type":"NAMED_VALUE_FLOAT","value":0.0},"NAV_CONTROLLER_OUTPUT":{"alt_error":8.696813583374023,"aspd_error":0.0,"message_information":{"counter":45414,"time":{"first_message":"2021-06-02T04:17:19.702460695+00:00","last_message":"2021-06-02T05:33:21.892910002+00:00"}},"nav_bearing":158,"nav_pitch":22.816354751586914,"nav_roll":-178.67893981933594,"target_bearing":90,"type":"NAV_CONTROLLER_OUTPUT","wp_dist":0,"xtrack_error":0.0},"ParaM_VALUE":{"message_information":{"counter":1379,"frequency":0.496221661567688,"time":{"first_message":"2021-06-02T04:17:17.382040509+00:00","last_message":"2021-06-02T05:03:36.411921703+00:00"}},"param_count":689,"param_id":["R","C","1","6","_","D","Z","\u0000","param_index":688,"param_type":{"type":"MAV_ParaM_TYPE_INT16"},"param_value":0.0,"type":"ParaM_VALUE"},"POWER_STATUS":{"Vcc":4798,"Vservo":4826,"flags":{"bits":6},"time":{"first_message":"2021-06-02T04:17:19.682529932+00:00","last_message":"2021-06-02T05:33:21.886051991+00:00"}},"type":"POWER_STATUS"},"RAW_IMU":{"id":0,"message_information":{"counter":45397,"frequency":9.951117515563965,"time":{"first_message":"2021-06-02T04:17:19.734752711+00:00","last_message":"2021-06-02T05:33:21.877993635+00:00"}},"temperature":0,"time_usec":292202468,"type":"RAW_IMU","xacc":317,"xgyro":175,"xmag":-491,"yacc":167,"ygyro":-9,"ymag":266,"zacc":957,"zgyro":456,"zmag":-115},"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":1300,"chan6_raw":1500,"chan7_raw":1500,"chan8_raw":1500,"chan9_raw":1100,"chancount":0,"message_information":{"counter":45418,"frequency":9.955720901489258,"time":{"first_message":"2021-06-02T04:17:19.711293621+00:00","last_message":"2021-06-02T05:33:21.917371628+00:00"}},"RSSi":0,"type":"RC_CHANNELS"},"SCALED_IMU2":{"message_information":{"counter":45397,"time":{"first_message":"2021-06-02T04:17:19.736843145+00:00","last_message":"2021-06-02T05:33:21.879795741+00:00"}},"time_boot_ms":4587169,"type":"SCALED_IMU2","xacc":350,"xgyro":168,"xmag":0,"yacc":23,"ygyro":-16,"ymag":0,"zacc":947,"zgyro":417,"zmag":0},"SCALED_PRESSURE":{"message_information":{"counter":45397,"time":{"first_message":"2021-06-02T04:17:19.738746395+00:00","last_message":"2021-06-02T05:33:21.881683105+00:00"}},"press_abs":985.9927978515625,"press_diff":0.9619531035423279,"temperature":3839,"type":"SCALED_PRESSURE"},"SERVO_OUTPUT_RAW":{"message_information":{"counter":45418,"time":{"first_message":"2021-06-02T04:17:19.709378809+00:00","last_message":"2021-06-02T05:33:21.914680318+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":292203152,"type":"SERVO_OUTPUT_RAW"},"STATUSTEXT":{"message_information":{"counter":6,"frequency":0.0021606050431728363,"time":{"first_message":"2021-06-02T04:17:17.906866746+00:00","last_message":"2021-06-02T05:03:34.950209089+00:00"}},"severity":{"type":"MAV_SEVERITY_INFO"},"text":["P","X","4","v","2"," ","0","3","8","E","5","9","type":"STATUSTEXT"},"SYstem_TIME":{"message_information":{"counter":90857,"frequency":19.916046142578125,"time":{"first_message":"2021-06-02T04:17:19.702351114+00:00","last_message":"2021-06-02T05:33:21.934951232+00:00"}},"time_unix_usec":1622669680316000,"type":"SYstem_TIME"},"SYS_STATUS":{"battery_remaining":-1,"drop_rate_comm":0,"errors_comm":0,"errors_count1":0,"errors_count2":0,"errors_count3":0,"errors_count4":0,"load":320,"message_information":{"counter":45413,"frequency":9.954625129699707,"time":{"first_message":"2021-06-02T04:17:19.740726362+00:00","last_message":"2021-06-02T05:33:21.884494257+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":-8.6899995803833,"climb":0.0,"groundspeed":0.0,"heading":158,"message_information":{"counter":45610,"frequency":9.997807502746582,"time":{"first_message":"2021-06-02T04:17:19.718803757+00:00","last_message":"2021-06-02T05:33:21.919499092+00:00"}},"throttle":0,"type":"VFR_HUD"},"VIBRATION":{"clipping_0":0,"clipping_1":1,"clipping_2":0,"time":{"first_message":"2021-06-02T04:17:19.732746078+00:00","last_message":"2021-06-02T05:33:21.941986844+00:00"}},"time_usec":4587189930,"type":"VIBRATION","vibration_x":0.743248462677002,"vibration_y":1.1571483612060547,"vibration_z":1.0443675518035889}}

这是从 JSON 字符串的 NAMED_VALUE_FLOAT 部分提取的。

  "message_information": {
    "counter": 302846,"frequency": 87.47718048095703,"time": {
      "first_message": "2021-06-02T04:17:17.857721885+00:00","last_message": "2021-06-02T05:15:00.035238554+00:00"
    }
  },"name": [
    "P","l","G","a","n","\u0000"
  ],"time_boot_ms": 3485250,"type": "NAMED_VALUE_FLOAT","value": 0.5
}

这是 Remi Lebeau 提供的用于获取值的工作代码

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,'NAMED_VALUE_FLOAT','value');
  ...
end;

名称”数组从 PilotGain 更改为 Tethertrn 等,我需要检索它以关联正确的值。我对 JSON 的了解非常有限。老实说,我不知道如何继续。

干杯, E.

================================================ == 说明:

机器人每秒大约 20 次向 URL http://192.168.2.2:4777/mavlink 发送 JSON。出于某种原因,我不明白他们使用项目 NAMED_VALUE_FLOAT 来传递 PilotGain、Stickmode、TetherTrn 等的值 出于进一步的原因我不明白,而不是只使用字符串作为“名称”,他们使用数组...

NAMED_VALUE_FLOAT 与上一个问题中的 ATTITUDE 类似。

我可以从 NAMED_VALUE_FLOAT 获取“值”,但除非我可以将其与其标识符联系起来,否则该值没有任何意义。 PilotGain 的价值是什么?对于 TetherTrn?等

我试图检索的部分是:

"name": [
    "P",

其中“name”数组包含“P”、“i”、“l”、“o”、“t”、“G”、“a”、“i”、“n”、“\u0000”

所以我需要检索:PilotGain

名称数组更改为其他字符,例如:

"S","\u0000"

所以我需要检索:StickMode

"T","h","r","T","\u0000"

所以我需要检索:TetherTrn

等等...

如果我尝试检索“name”的值,我会得到一个空字符串。所以我猜我必须检索 Name 中的数组,然后将其放入一个字符串中。

抱歉,我无法更改机器人输出的 JSON 格式。

我希望这更清楚。

谢谢。

解决方法

按照 Remy Lebeau 的指示,我想出了这个代码,它输出我试图检索的字符串。

所有功劳都归功于他。

我希望这对仍在使用 Delphi XE2 的其他人有所帮助。

function TForm_OV_REC.ParseJSONArray(sJSON,sITEM,sArray : String) : String;
var
  LJsonVal : TJSONValue;
  LJPair : TJSONPair;
  LJsonArray : TJSONArray;
  LIndex    : Integer;
  LSize     : Integer;
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(sArray);
    if LJPair = nil then Exit;

    LJsonArray := TJSONArray(LJPair.JsonValue); 
    LSize := LJsonArray.Size;
    if LSize < 1 then Exit;

    for LIndex := 0 to LSize-1 do
      begin
        Result := Result +  LJsonArray.Get(LIndex).Value;
      end;
  finally
    LJsonVal.Free;
  end;
end;