.net 序列化字典<;TKey,TValue>;使用DataContractJsonSerializer创建JSON
我有一个对象树,我正在使用.net 序列化字典<;TKey,TValue>;使用DataContractJsonSerializer创建JSON,.net,oop,serialization,datacontractjsonserializer,multiple-interface-implem,.net,Oop,Serialization,Datacontractjsonserializer,Multiple Interface Implem,我有一个对象树,我正在使用DataContractJsonSerializer将其序列化为JSON字典被序列化,但我不喜欢标记-项目不是这样呈现的: {key1:value, key2:value2} public class MyClass : Dictionary<string, object>, ISerializable { public override void GetObjectData(SerializationInfo info, Str
DataContractJsonSerializer
将其序列化为JSON<代码>字典被序列化,但我不喜欢标记-项目不是这样呈现的:
{key1:value, key2:value2}
public class MyClass : Dictionary<string, object>, ISerializable
{
public override void GetObjectData(SerializationInfo info,
StreamingContext context)
}
但与序列化的KeyValuePair
对象数组类似:
[{
"__type":"KeyValuePairOfstringanyType:#System.Collections.Generic",
"key":"key1",
"value":"value1"
},
{
"__type":"KeyValuePairOfstringanyType:#System.Collections.Generic",
"key":"key2",
"value":"value2"
}]
难看,不是吗
因此,我通过将泛型词典包装在实现iseerializable
的自定义对象中来避免这种情况,并在GetObjectData
方法中实现自定义序列化(只需要3行代码)
现在的问题是,我无法使我的类派生自字典
,因此我在自定义类中实现了所有逻辑(添加
,清除
,等等),应用于私有的字典
字段。继承更可取,因为在使用自定义对象时,我将拥有所有通用字典功能
继承的问题是,Dictionary
单独实现了ISerializable
,而且DataContractJsonSerializer
似乎更喜欢这种实现,即使我从自定义类显式实现了ISerializable
,如下所示:
{key1:value, key2:value2}
public class MyClass : Dictionary<string, object>, ISerializable
{
public override void GetObjectData(SerializationInfo info,
StreamingContext context)
}
但显然,我在生成的JSON中看到,KeyValuePair
序列化程序仍然被调用,这并没有发生。我错过了什么
更新:
到目前为止,我得到的答案和评论几乎只是建议解决办法。然而,我注意到,我有一个变通方法,效果非常好,因此问这个问题我有两个目标:
DataContractJsonSerializer
没有使用我的序列化代码的谜团,正如我在博客中提到的那样,我对接口实现和继承做了各种各样的实验,我确信我掌握了这个过程的所有细节,所以我很不明白这件事到底发生了什么此外,字典序列化的默认实现完全符合您的需要。正如@Pashec所提到的,如果您使用Json.NET,您可以尝试以下操作:
public Message <methodname> {
...
string jsonMessage = JsonConvert.SerializeObject(myObjectTree);
return WebOperationContext.Current.CreateTextResponse(jsonMessage, "application/javascript; charset=utf-8", Encoding.UTF8);
}
公共消息{
...
字符串jsonMessage=JsonConvert.SerializeObject(myObjectTree);
返回WebOperationContext.Current.CreateTextResponse(jsonMessage,“application/javascript;charset=utf-8”,Encoding.UTF8);
}
一个选项是使用代理属性,并将字典置于自定义ISerializable类型中,这样您就不必担心继承问题:
public Dictionary<string, string> NodeData { get; set; }
[DataMember(Name="NodeData")]
private CustomDictionarySerializer NodeDataSurrogate
{
get
{
return new CustomDictionarySerializer(NodeData);
}
set
{
NodeData = value._data;
}
}
[Serializable]
private class CustomDictionarySerializer : ISerializable
{
public Dictionary<string, string> _data;
public CustomDictionarySerializer(Dictionary<string, string> dict)
{
_data = dict;
}
public CustomDictionarySerializer(SerializationInfo info, StreamingContext context)
{
_data = new Dictionary<string, string>();
var valueEnum = info.GetEnumerator();
while(valueEnum.MoveNext())
{
_data[valueEnum.Current.Name] = valueEnum.Current.Value.ToString();
}
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
foreach (var pair in _data)
{
info.AddValue(pair.Key, pair.Value);
}
}
}
公共字典节点数据{get;set;}
[数据成员(Name=“NodeData”)]
私有自定义词典序列化器NodeDataSurrogate
{
得到
{
返回新的CustomDictionarySerializer(NodeData);
}
设置
{
NodeData=值。\u数据;
}
}
[可序列化]
私有类CustomDictionarySerializer:ISerializable
{
公共词典数据;
公共自定义词典序列化程序(词典dict)
{
_数据=dict;
}
public CustomDictionarySerializer(序列化信息、StreamingContext上下文)
{
_数据=新字典();
var valueEnum=info.GetEnumerator();
while(valueEnum.MoveNext())
{
_数据[valueEnum.Current.Name]=valueEnum.Current.Value.ToString();
}
}
public void GetObjectData(SerializationInfo信息、StreamingContext上下文)
{
foreach(数据中的var对)
{
info.AddValue(pair.Key,pair.Value);
}
}
}
似乎可以用IEnumerable类和ISerializable实现来包装字典。比从字典继承要省力得多。您也可以使用JavaScriptSerializer
,因为它可以按您喜欢的方式序列化字典。@RitchMelton-从字典继承不需要很多工作,但我必须承认,实现IEnumerable并返回成员字典的getEnumarator乍一看似乎比我的解决方法要好——只有一种方法可以解决这个问题implement@PaulTyng-正如更新中提到的,更改序列化程序将产生更广泛的影响,仅仅为了这个小小的设计改进是不值得的。在这里,我更感好奇的是,为什么DataCoContractJSonSerializer的诀窍无法找到答案。Dan Rigsby的链接文章只提到DataContractSerializer是不可配置的,但与我在探讨为何不调用显式GetObjectData实现时所用的篇幅相比,它的篇幅更大。除此之外,我对json.net非常了解,我知道这很好——仅仅在项目中更改序列化引擎就会产生太大的影响——不仅仅是我的自定义词典正在被序列化——Drigsby link现在已经死了(DNS失败)。所有标准序列化定制机制都可用,因为它们都基于XmlObjectSerializer
。不幸的是,这并不是一个“简单”的问题(请参见“代理属性”答案),而是一个“不可能”的问题。如果您控制了类,那么这项工作会很好,您可以将CustomDictionarySerializer
值类型设置为通用参数,以便可以序列化(和反序列化)任何类型的字典。请注意,引用类型的任何值也会添加一个“\uuuu type”属性(用于反序列化目的)。您还必须对类使用DataContract
属性