Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 序列化字典<;TKey,TValue>;使用DataContractJsonSerializer创建JSON_.net_Oop_Serialization_Datacontractjsonserializer_Multiple Interface Implem - Fatal编程技术网

.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
    没有使用我的序列化代码的谜团,正如我在博客中提到的那样,我对接口实现和继承做了各种各样的实验,我确信我掌握了这个过程的所有细节,所以我很不明白这件事到底发生了什么

  • 似乎,要定制DataContractJsonSerializer

    <>如果你仍然想要达到你想要的,考虑使用。它比DataContractJsonSerializer更快、更灵活。看看Json.Net的JsonConverter概念。它使您可以自定义序列化/反序列化过程


    此外,字典序列化的默认实现完全符合您的需要。

    正如@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
    属性