把别人发来的 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 写的代码有问题,但仍然提供了思路,在它的代码基础上做一些修改,仍然可以获得能用的代码。
原文地址:https://blog.csdn.net/pcplayer/article/details/140581350
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!