TJSONUnMarshal如何为JSONObject子项注册Reverter?
解决TJSONUnMarshal嵌套对象Reverter不触发的问题
核心结论:完全可以给JSONObject子项设置Reverter,你的问题是Reverter的注册方式不对,没关联到嵌套对象的反序列化流程里。
问题原因
单独反序列化TCustomerHeader时,TJSONUnMarshal直接识别到目标类型是TCustomerHeader,会触发你注册的对应Reverter;但反序列化顶层的TCustomer时,默认只会扫描针对TCustomer类型注册的Reverter,不会自动关联子类型的Reverter——除非你明确给子类型或者子字段路径注册。
两种可行的解决方法
1. 全局注册子类型TCustomerHeader的Reverter
这种方式不管是嵌套还是单独反序列化TCustomerHeader,都会触发Reverter,通用性强:
// 注册TCustomerHeader类型的changeDate字段Reverter JSONUnMarshal.RegisterReverter(TypeInfo(TCustomerHeader), 'changeDate', procedure(Obj: TObject; const Value: TJSONValue) var Header: TCustomerHeader; DateStr: string; begin Header := TCustomerHeader(Obj); if Value is TJSONString then begin DateStr := TJSONString(Value).Value; // 替换成你的实际日期解析逻辑,比如处理自定义格式 Header.changeDate := StrToDate(DateStr); end; end);
注意:注册时要指定子类型
TCustomerHeader的TypeInfo,而不是顶层的TCustomer。
2. 针对顶层对象的子字段路径注册Reverter
如果只需要处理TCustomer里的header子对象的changeDate,可以直接指定字段路径,精准控制:
// 针对TCustomer的header.changeDate字段注册Reverter JSONUnMarshal.RegisterReverter(TypeInfo(TCustomer), 'header.changeDate', procedure(Obj: TObject; const Value: TJSONValue) var Customer: TCustomer; DateStr: string; begin Customer := TCustomer(Obj); if Value is TJSONString then begin DateStr := TJSONString(Value).Value; Customer.header.changeDate := StrToDate(DateStr); end; end);
额外注意事项
- 确认JSON字段名和Delphi类属性名完全匹配(如果JSON里是
changedate而类里是changeDate,需要用[JSONName('changedate')]标注属性) - Reverter必须在反序列化操作之前注册,否则不会生效
- 如果日期格式是非标准格式,要在Reverter里用自定义解析逻辑(比如
TryStrToDate加格式参数,或者用TDateTimeHelper的Parse方法)
内容的提问来源于stack exchange,提问作者MonkeySleeve
相关产品推荐
相关产品推荐

