把别人发来的 JSON 解析为 Delphi 的对象

需求

这个 JSON 是其它语言生成的,在 Delphi 程序里面,如果能把它变成对象,后继的代码就会更简单。

数据

{"pkt_type":"scan_report","gw_addr":"c7ef72a011b6","time":"2024-07-20 18:49:33","data":{"flags":5,"pkt_sn":2299,"report_type":"le5_raw","pkt_total":1,"pkt_index":0,"dev_total":1,"dev_num":1,"dev_infos":[{"addr":"e91440214207","rssi":-59,"time":"2024-07-20 18:49:33","name":"C2","adv_raw":"02010617FF000100251505AA00A26C0400410A4101EA0D9400640003094332"}]}}

解决方法

如何根据这个 JSON 字符串,构造 Delphi 的类?靠人眼去读 JSON 然后手写代码,比较累。尤其是里面有很多嵌套。

把这段 JSON 代码丢给 ChatGPT,让它写出对应的 Delphi 类。确实写出来了,但运行结果有问题。

反复和 ChatGPT 拉扯几次后,虽然它每次的回答都不全对,但是,在它东拉西扯的回答里面,逐步发现一些东西,反复做实验,由此增加了对 Delphi 处理 JSON 的了解。

先给出可以运行的代码:

interface

uses
  System.SysUtils,
  System.Classes,
  System.JSON,
  System.Generics.Collections,
  REST.Json.Types,
  REST.Json;



type
  TDevInfo = class
  private
    FAddr: string;
    FRssi: Integer;
    FTime: string;
    FName: string;

    [JSONName('adv_raw')]
    FAdvRaw: string;
  public
    property Addr: string read FAddr write FAddr;
    property Rssi: Integer read FRssi write FRssi;
    property Time: string read FTime write FTime;
    property Name: string read FName write FName;
    property adv_raw: string read FAdvRaw write FAdvRaw;
  end;

  TDevInfos = TArray<TDevInfo>; // array of TDevInfo;

  TData = class
  private
    FFlags: Integer;
    FPktSn: Integer;
    FReportType: string;
    FPktTotal: Integer;
    FPktIndex: Integer;
    FDevTotal: Integer;
    FDevNum: Integer;

    [JSONName('dev_infos')]
    FDevInfos: TDevInfos; //TObjectList<TDevInfo>;
  public
    constructor Create;
    destructor Destroy; override;
    property Flags: Integer read FFlags write FFlags;
    property pkt_sn: Integer read FPktSn write FPktSn;
    property report_type: string read FReportType write FReportType;
    property pkt_total: Integer read FPktTotal write FPktTotal;
    property pkt_index: Integer read FPktIndex write FPktIndex;
    property dev_total: Integer read FDevTotal write FDevTotal;
    property dev_num: Integer read FDevNum write FDevNum;
    property dev_infos: TDevInfos read FDevInfos write FDevInfos;
  end;

  TScanReport = class
  private
    [JSONName('pkt_type')]
    FPktType: string;
    FGwAddr: string;
    FTime: string;
    FData: TData;
  public
    constructor Create;
    destructor Destroy; override;

    class function ParseJSON(const JSONStr: string): TScanReport;

    property PktType: string read FPktType write FPktType;
    property gw_addr: string read FGwAddr write FGwAddr;
    property Time: string read FTime write FTime;
    property Data: TData read FData write FData;
  end;

implementation

{ TScanReport }

constructor TScanReport.Create;
begin
  FData := TData.Create;
end;

destructor TScanReport.Destroy;
begin
  FData.Free;
  inherited;
end;

class function TScanReport.ParseJSON(const JSONStr: string): TScanReport;
begin
  Result := TJson.JsonToObject<TScanReport>(JSONStr);
end;

{ TData }

constructor TData.Create;
begin
  //FDevInfos := TObjectList<TDevInfo>.Create;
end;

destructor TData.Destroy;
begin
  //FDevInfos.Free;
  inherited;
end;

end.

代码的解释和注意事项

1. 一开始 ChatGPT 把 JSON 里面的数组,定义为 TObjectList<T>。但这样做是错误的。错误现象是从 JSON 获得对象没问题,但对象里面的 ObjectList 里面没有内容,其 Count 为 0;这里,必须使用 TArray<> 数组类型,而不能使用 TObjectList<> 来对应 JSON 里面的数组;

2. 解析出来的对象,发现某些字段有值,某些字段没有值。因为 ChatGPT 给出来的代码,属性的名称并没有和 JSON 字符串里面的名称完全一致,所以把字段的属性名称改为和 JSON 字符串里面的名称完全一致(大小写都一样),也不行。最终发现,给每个字段加上类似:[JSONName('dev_infos')] 这样的属性定义,该字段对应的值就有了。

[JSONName('dev_infos')] 这样的属性定义放在类的私有字段定义里面,这个是我这个老程序员不知道的新语法。通过 ChatGPT 学到的。

到此,问题解决。

结论

目前的 ChatGPT 可以帮我们生成 Delphi 代码,节约了手写代码的繁琐。但是,它给出来的代码还是有问题的。之前测试过让它写 Python 代码,写出来的代码运行完全正确。看起来还是 Delphi 不如 Python 热度高,训练永的代码数据比 Python 开源代码少导致。

无论如何,虽然 ChatGPT 写的代码有问题,但仍然提供了思路,在它的代码基础上做一些修改,仍然可以获得能用的代码。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中获取请求体的JSON解析JSON对象时出现了参数含有空格和乱码的问题。出现这个问题可能是由于请求体JSON中的参数值中含有空格或者非UTF-8编码导致的。 要解决这个问题,首先需要检查并确认请求体JSON中的参数值是否正确且符合JSON格式的规范。如果参数值含有空格或其他特殊字符,建议在发送请求时对参数值进行URL编码,确保其在传输过程中不会出现乱码。 在Java代码中,可以使用URLDecoder对请求体JSON进行解码。例如,可以使用如下代码获取请求体中的JSON字符串,并进行解码: String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); String decodedBody = URLDecoder.decode(body, "UTF-8"); 接下来,可以使用JSON库(如Jackson、Gson等)将解码后的JSON字符串解析JSON对象。例如,对于使用Jackson库的情况,可以使用如下代码将解码后的JSON字符串解析JSON对象: ObjectMapper mapper = new ObjectMapper(); JsonNode jsonNode = mapper.readTree(decodedBody); 在解析JSON对象之后,可以通过遍历JSON对象的属性、调用对应的getter方法等获取具体的参数值,进行后续的业务逻辑处理。 综上所述,要解决Java获取请求体JSON解析JSON对象参数含有空格乱码的问题,需要注意参数值的格式以及编码方式,并在Java代码中正确解码和解析JSON对象。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值