本文介绍了序列化字典< TKEY的,TValue>以JSON与DataContractJsonSerializer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我序列化到JSON与 DataContractJsonSerializer 对象树。 词典< TKEY的,TValue> 被序列化,但我不喜欢的标记 - 该项目没有像这样渲染:

  {键:值,键2:值2}
 

而是像序列化数组 KeyValuePair< TKEY的,TValue> 目标:

  [{
    __type:KeyValuePairOfstringanyType:#System.Collections.Generic,
    钥匙:KEY1
    值:值1
 },
 {
    __type:KeyValuePairOfstringanyType:#System.Collections.Generic,
    钥匙:KEY2
    值:值2
 }]
 

丑,是不是?

所以,我避免这种通过包装通用字典中的自定义对象实现 ISerializable的,我实现了 GetObjectData使用方法(和它只需3行)。

现在的问题 - 我不能让我的类从词典&LT获得; TKEY的,TValue> ,让我实现所有的逻辑(添加清除等)在我的自定义类,被应用到私人词典< TKEY的,TValue> 字段。继承将是preferable,我会用我的自定义对象时,必须在我手上所有的通用字典的功能。

与继承的问题是,词典< TKEY的,TValue> 工具 ISerializable的自己,而 DataContractJsonSerializer 似乎preFER此实现,即使我实施 ISerializable的明确地从我的自定义类,像这样的:

 公共类MyClass的:字典<字符串,对象&gt ;,了ISerializable
{
    公众覆盖无效GetObjectData使用(SerializationInfo中的信息,
        的StreamingContext上下文)
}
 

实际上,我是惊讶,这是可能的,因为它可以让我实现相同的接口两次没有被明显地能够使用显式接口实现 - 所以我分析了形势更详细地在博客中的

因此​​,根据我做那里的实验中,序列化应该是叫我实现了ISerializable的,不管是什么类型的铸件内部使用 -

 ((ISerializable的)((词典<,>)OBJ))。GetObjectData使用(...)
 

 ((ISerializable的)目标文件).GetObjectData(...)
 

但它显然是不发生,因为我在生成的JSON看到 KeyValuePair< TKEY的,TValue> 串行器仍然被调用。可能发生的事,我很想念?

更新:这些问题的答案和意见,我越来越至今都pretty的多少只是建议的解决方法。我注意到,不过,我有工作的很好所以用问这个问题,一种解决方法我有2个目标:

  1. 最后,使其与原来的设计工作 - 我不会改变只是该序列的逻辑,有很多的code和逻辑依赖于它

  2. 要unserstand为什么不是 DataContractJsonSerializer 用我的序列化code中的奥秘 ​​- 这可以在博客文章中,我提到可以看出,我取得了各种实验,接口实现和继承,我相信我抓住所有的插件和过程的出局,让我困扰未能了解发生了什么hapenning在这种情况下

解决方案

一种选择是使用替代性和有字典是定制ISerializable的类型里面,这样你就不需要担心继承:

 公共字典<字符串,字符串> NODEDATA {获得;组; }

[数据成员(NAME =NODEDATA)
私人CustomDictionarySerializer NodeDataSurrogate
{
    得到
    {
        返回新CustomDictionarySerializer(NODEDATA);
    }
    组
    {
        NODEDATA = value._data;
    }
}

[可序列化]
私有类CustomDictionarySerializer:ISerializable的
{
    公共字典<字符串,字符串> _数据;

    公共CustomDictionarySerializer(词典<字符串,字符串>字典)
    {
        _data =字典;
    }

    公共CustomDictionarySerializer(SerializationInfo中的信息,的StreamingContext上下文)
    {
        _data =新字典<字符串,字符串>();
        变种valueEnum = info.GetEnumerator();
        而(valueEnum.MoveNext())
        {
            _data [valueEnum.Current.Name] = valueEnum.Current.Value.ToString();
        }
    }

    公共无效GetObjectData使用(SerializationInfo中的信息,的StreamingContext上下文)
    {
        的foreach(VAR对的_data)
        {
            info.AddValue(pair.Key,pair.Value);
        }
    }
}
 

I have an object tree that I'm serializing to JSON with DataContractJsonSerializer. Dictionary<TKey, TValue> gets serialized but I don't like the markup - the items are not rendered like this:

{key1:value, key2:value2}

but rather like an array of serialized KeyValuePair<TKey, TValue> objects:

[{
    "__type":"KeyValuePairOfstringanyType:#System.Collections.Generic",
    "key":"key1",
    "value":"value1"
 },
 {
    "__type":"KeyValuePairOfstringanyType:#System.Collections.Generic",
    "key":"key2",
    "value":"value2"
 }]

Ugly, isn't it?

So, I avoid this by wrapping the generic Dictionary in a custom object that implements ISerializable, and I implement my custom serialization in the GetObjectData method (and it takes just 3 lines).

Now the problem - I can't make my class derive from Dictionary<TKey, TValue>, so I implement all logic (Add, Clear, etc.) in my custom class, being applied to a private Dictionary<TKey, TValue> field. Inheritance would be preferable as I'll have all generic Dictionary functionality at my disposal when using my custom object.

The problem with inheritance is that Dictionary<TKey, TValue> implements ISerializable on its own, and DataContractJsonSerializer seems to prefer this implementation even if I implement ISerializable explicitly from my custom class, like this:

public class MyClass : Dictionary<string, object>, ISerializable
{
    public override void GetObjectData(SerializationInfo info,
        StreamingContext context)
}

I was actually surprised that this is possible as it allows me to implement the same interface twice without being obviously able to use explicit interface implementation - so I analyzed the situation in more detail in a blog post about multiple interface implementation

So, according to the experiments I did there, the serializer should be calling my implementation of ISerializable, no matter what type of casting is used internally -

((ISerializable)((Dictionary<,>)obj)).GetObjectData(...)

or:

((ISerializable)obj).GetObjectData(...)

but it apparently isn't happening as I see in the resulting JSON that the KeyValuePair<TKey, TValue> serializer still being called. What might be happening that I'm missing?

Update:The answers and comments I'm getting so far are pretty much only suggesting workarounds. I noted, however, that I have a workaround that works quite well so with asking this question I have 2 objectives:

  1. Eventually make it work with the original design - and I'm not going to change serialization logic just for that, there is a lot of code and logic dependent on it

  2. To unserstand the mystery of why isn't the DataContractJsonSerializer using my serialization code - as can be seen in the blog post I referred, I have made all kinds of experiments with interface implementation and inheritance and I was confident that I'm grasping all the ins and outs of the process, so I'm troubled by failing to understand what's hapenning in this case

解决方案

One option is using a surrogate property and have the dictionary be inside the custom ISerializable type, that way you don't need to worry about inheritance:

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);
        }
    }
}

这篇关于序列化字典&LT; TKEY的,TValue&GT;以JSON与DataContractJsonSerializer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-29 03:19