如何将Delphi TDictionary序列化为符合C#要求的JSON字符串?
Delphi中序列化TDictionary为指定JSON格式的解决方案
你通过REST.JsonReflect自定义拦截器的方向是正确的,但现有代码存在细节问题,导致序列化结构不符合预期。以下是修正后的实现方案,同时提供其他替代方法:
方法一:修正自定义JSON拦截器
原代码的核心问题是没有正确告诉序列化器直接输出转换后的JSON值,而是将其当作普通对象处理。调整拦截器实现和属性参数即可解决:
uses System.Rtti, Rest.Json, System.Generics.Collections, Rest.JsonReflect, System.JSON; type TDictionaryInterceptor = class(TJSONInterceptor) public function ObjectConverter(Data: TObject; Field: string): TObject; override; procedure ObjectsConverter(Data: TObject; Field: string; out AObjects: TArray<TObject>); override; end; function TDictionaryInterceptor.ObjectConverter(Data: TObject; Field: string): TObject; var Dict: TDictionary<string, string>; JsonObj: TJSONObject; KVPair: TPair<string, string>; begin // 直接将目标对象转为TDictionary类型 Dict := TDictionary<string, string>(Data); JsonObj := TJSONObject.Create; try for KVPair in Dict do JsonObj.AddPair(KVPair.Key, KVPair.Value); Result := JsonObj; except JsonObj.Free; raise; end; end; procedure TDictionaryInterceptor.ObjectsConverter(Data: TObject; Field: string; out AObjects: TArray<TObject>); begin // 空实现,阻止序列化器遍历字典内部成员 AObjects := []; end; DictionaryReflectAttribute = class(JsonReflectAttribute) public constructor Create; end; constructor DictionaryReflectAttribute.Create; begin // 关键参数:指定处理JSON值而非普通对象 inherited Create(ctJSONValue, rtJSONValue, TDictionaryInterceptor); end; TExample = class public [DictionaryReflectAttribute] dictionary: TDictionary<string, string>; end;
测试代码
var Example: TExample; JsonStr: string; begin Example := TExample.Create; try Example.dictionary := TDictionary<string, string>.Create; Example.dictionary.Add('key1', 'KeyValue1'); Example.dictionary.Add('key2', 'KeyValue2'); JsonStr := TJson.ObjectToJsonString(Example); // 输出结果:{"dictionary":{"key1":"KeyValue1","key2":"KeyValue2"}} finally Example.dictionary.Free; Example.Free; end; end;
方法二:手动构建TJSONObject(无需模型类)
如果场景简单,可跳过模型类直接构建JSON结构,避免拦截器的复杂度:
var RootObj: TJSONObject; DictObj: TJSONObject; Dict: TDictionary<string, string>; KVPair: TPair<string, string>; JsonStr: string; begin Dict := TDictionary<string, string>.Create; try Dict.Add('key1', 'KeyValue1'); Dict.Add('key2', 'KeyValue2'); DictObj := TJSONObject.Create; try for KVPair in Dict do DictObj.AddPair(KVPair.Key, KVPair.Value); RootObj := TJSONObject.Create; try RootObj.AddPair('dictionary', DictObj); JsonStr := RootObj.ToString; finally RootObj.Free; end; finally Dict.Free; end; end;
方法三:使用第三方JSON库
原生REST.Json对复杂集合的支持有限,可选择第三方库简化开发,比如SuperObject或mORMot的JSON模块:
以SuperObject为例:
uses SuperObject; var Dict: TDictionary<string, string>; JsonObj: ISuperObject; KVPair: TPair<string, string>; JsonStr: string; begin Dict := TDictionary<string, string>.Create; try Dict.Add('key1', 'KeyValue1'); Dict.Add('key2', 'KeyValue2'); JsonObj := SO; JsonObj.S['dictionary'] := SO; for KVPair in Dict do JsonObj.O['dictionary'].S[KVPair.Key] := KVPair.Value; JsonStr := JsonObj.AsString; finally Dict.Free; end; end;
内容的提问来源于stack exchange,提问作者stmpakir
相关产品推荐
相关产品推荐

