XSuperObject解析JSON日期字段异常:字符串日期转数值问题求助
Delphi结合XSuperObject解析JSON日期返回数值而非字符串的解决办法
用Delphi结合XSuperObject组件解析JSON数据时,大部分字段都能正常解析,比如job['Id'].AsString可以正确拿到'POS-1'。但StartDate.Date和EndDate.Date对应的字符串日期(比如'2020-03-01'),用job['StartDate.Date'].AsString获取时,返回的却是43891、44355这类数值,不是原始的字符串日期。
相关代码
unit fmainForm; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses XSuperObject; procedure TForm1.FormCreate(Sender: TObject); var fileContents : string; job: ISuperObject; LDate: TDate; LValue: string; LFormat: TFormatSettings; LDouble: Double; begin fileContents := '{' + ' "Id": "POS-1",' + ' "Employer": {' + ' "Name": {' + ' "Normalized": "Acme"' + ' }' + ' },' + ' "IsSelfEmployed": false,' + ' "IsCurrent": true,' + ' "StartDate": {' + ' "Date": "2020-03-01",' + ' },' + ' "EndDate": {' + ' "Date": "2021-06-08",' + ' },' + '}'; job := SO(fileContents); if Assigned(job['Id']) then Memo1.Lines.Add('Job Id = ' + job['Id'].AsString); if Assigned(job['Employer.Name.Normalized']) then Memo1.Lines.Add('Employer name = ' + job['Employer.Name.Normalized'].AsString); if Assigned(job['StartDate.Date']) then Memo1.Lines.Add('Start date = ' + job['StartDate.Date'].AsString); if Assigned(job['EndDate.Date']) then Memo1.Lines.Add('End date = ' + job['EndDate.Date'].AsString); end; end.
程序输出结果
Job Id = POS-1
Employer name = Acme
Start date = 43891
End date = 44355
问题原因
XSuperObject会自动识别JSON中的日期格式字符串(比如yyyy-mm-dd),并将其转换为Delphi的TDate类型存储——而TDate本质是Double类型,代表从1899年12月30日开始计算的天数。所以调用.AsString时,实际上是把这个浮点数转换成了字符串,而非返回JSON里的原始字符串值。
解决办法
方法1:直接获取原始JSON字符串值
使用.AsJSON属性拿到带引号的原始值,再去掉引号即可:
if Assigned(job['StartDate.Date']) then Memo1.Lines.Add('Start date = ' + Trim(job['StartDate.Date'].AsJSON, ['"'])); if Assigned(job['EndDate.Date']) then Memo1.Lines.Add('End date = ' + Trim(job['EndDate.Date'].AsJSON, ['"']));
方法2:关闭XSuperObject的自动日期解析
创建ISuperObject时,添加soNoDateParse参数,禁止组件自动识别日期字符串:
job := SO(fileContents, [soNoDateParse]);
之后再调用.AsString就能直接拿到原始的日期字符串了。
方法3:将数值转回日期字符串
如果需要保留日期类型的解析,只是要显示成字符串格式,可以用FormatDateTime把TDate转成指定格式的字符串:
if Assigned(job['StartDate.Date']) then Memo1.Lines.Add('Start date = ' + FormatDateTime('yyyy-mm-dd', job['StartDate.Date'].AsTDate)); if Assigned(job['EndDate.Date']) then Memo1.Lines.Add('End date = ' + FormatDateTime('yyyy-mm-dd', job['EndDate.Date'].AsTDate));
内容的提问来源于stack exchange,提问作者Mawg
相关产品推荐
相关产品推荐

