delphi 如何避免解析ISperObject类型字段中的json对象

du7egjpx  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(128)

很久以前,我们决定使用XSuperObject库将对象编组到json中,以便在系统的两个部分之间进行转换。其中一个字段在服务器端表示为ISuperObject,在客户端表示为各种对象。
这个想法是,我发送对象到服务器,然后它返回一个没有任何变化的。例如,我发送这个:

[
  {
    "NAME": "Today",
    "VALUE": {"loginIndex": 0,"shipmentDate": "2023-09-08","shipmentAddressId": "","paymentMethodId": "","shipmentMethodId": "","shipmentOfficeId": ""},
    "IS_DEFAULT": false,
    "ID": 0,
    "WH_ID": 0
  },
  {
    "NAME": "Monday",
    "VALUE": {"loginIndex": 0,"shipmentDate": "2023-09-11","shipmentAddressId": "","paymentMethodId": "","shipmentMethodId": "","shipmentOfficeId": ""},
    "IS_DEFAULT": false,
    "ID": 0,
    "WH_ID": 0
  },
  {
    "NAME": "Tuesday",
    "VALUE": {"loginIndex": 0,"shipmentDate": "2023-09-12","shipmentAddressId": "","paymentMethodId": "","shipmentMethodId": "","shipmentOfficeId": ""},
    "IS_DEFAULT": false,
    "ID": 0,
    "WH_ID": 0
  }
]

并将其转换为具有以下结构的对象:

TMySelectedItem = record
  NAME:String;
  VALUE:ISuperObject;
  IS_DEFAULT:Boolean;
  ID:Integer;
  WH_ID:Integer;
end

当我使用TSuperRecord<TMySelectedItem>.FromJSON(Resp.Data[i])将JSON转换为对象,提取VALUE字段并使用VALUE.AsJSON将其转换为字符串时,我期望这样:

{"loginIndex": 0,"shipmentDate": "2023-09-08","shipmentAddressId": "","paymentMethodId": "","shipmentMethodId": "","shipmentOfficeId": ""}

但服务器返回给我的是

{"loginIndex": 0,"shipmentDate": "2023-09-07Z","shipmentAddressId": "","paymentMethodId": "","shipmentMethodId": "","shipmentOfficeId": ""}

正如你所看到的,它不仅将字段shipmentDate识别为日期,正如我所想的那样,它还改变了时区,尽管这个字符串中缺少时间值,特别是我没有告诉它,这个字段是一个日期。我可以标记字段,输入ISuperObject转换为输出JSON,而不做任何更改吗?

aiazj4mn

aiazj4mn1#

您使用的库(XSuperObject)在阅读JSON时具有从JSON字符串值中识别日期、时间和日期-时间值的内置功能。默认情况下启用此选项。
库中的一些API允许您控制此行为-TSuperObject.Create(JSON: String = '{}'; const CheckDate: Boolean = True),但TSuperRecord<T>.FromJson(const JSON: String)并非如此。
在这种情况下,您可以使用FromJson方法的版本,该方法将ISuperObject作为显式禁用日期识别的参数:

var LSuperObject: ISuperObject := TSuperObject.Create(Resp.Data[i], {CheckDate}False);
var Item := TSuperRecord<TMySelectedItem>.FromJSON(LSuperObject);

但由于库中的bug,这也不起作用:

  1. CheckDate参数的值不会传播到嵌套对象。方法TBaseJSON<T, Typ>.GetObject(V: Typ): ISuperObject返回TSuperObject的新示例,默认情况下启用CheckDate
    1.在TSuperRecord<T>.FromJSON()中解组ISuperObject类型的值也会忽略用于创建TSuperObject示例的CheckDate参数的值。见方法TSuperObject.Clone: ISuperObject
    这只是适用于您的场景的两个bug,但我猜还有更多,因为库缺少测试套件。从理论上讲,你可以要求作者修复这些bug,或者贡献bug修复,但是基于issuescommits,这个项目对我来说似乎已经死了。
    该库包含负责识别日期的静态类TJSONDateManager。它包含以ISO-8601格式初始化的Formats类属性。清除这些格式将禁用任何日期识别,并且特定问题的解决方案将变为一行程序:
TJSONDateManager.Formats.Clear;

在这一点上,您依赖的库是错误的,您可能不会得到任何支持。我强烈建议你换到其他的图书馆。
FWIW,建议修复上述错误是:

function TBaseJSON<T, Typ>.GetObject(V: Typ): ISuperObject;
begin
  Result := Nil;
  if not Member(V) then
    Member<TJSONObject, Pointer>(V, Nil);

  //Original: Result := TSuperObject.Create(GetValue<TJSONObject>(V));
  Result := TSuperObject.Create(GetValue<TJSONObject>(V), FCheckDate);
end;

function TSuperObject.Clone: ISuperObject;
begin
  //Original: Result := SO(AsJSON);
  Result := TSuperObject.Create(AsJSON, FCheckDate);
end;

相关问题