2016-03-25 93 views
3

序列化字典来JSON通过Newtonsoft.json和娄代码:Newtonsoft.Json,填充字典失败

var serializeSettings = new JsonSerializerSettings 
     { 
      TypeNameHandling = TypeNameHandling.All, 
      TypeNameAssemblyFormat = FormatterAssemblyStyle.Full, 
      Formatting = Formatting.Indented 
     }; 
     var serializedObject = JsonConvert.SerializeObject(dic, serializeSettings); 

该代码生成这样的JSON:

{ 
    "$type": "System.Collections.Generic.Dictionary`2[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 
    "9648af76-7986-4b34-8b2c-97b2345769ef": "Test" 
} 

我尝试反序列化json以此代码字典:

var newDic = new Dictionay<Guid,string>(); 
var deserializeSettings = new JsonSerializerSettings 
{ 
    TypeNameHandling = TypeNameHandling.All, 
    TypeNameAssemblyFormat = FormatterAssemblyStyle.Full, 
    Formatting = Formatting.Indented 
} 
JsonConvert.PopulateObject(serializedObject, newDic, deserializeSettings); 

但是会发生此异常:

无法将字符串'$ type'转换为字典密钥类型'System.Guid'。创建一个TypeConverter将字符串转换为键类型对象。路径 '$类型',第2行,位置10

在Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateDictionary(IDictionary的字典,JsonReader读卡器,JsonDictionaryContract合同,JsonProperty containerProperty,字符串ID)

在Newtonsoft.Json .Serialization.JsonSerializerInternalReader.Populate(JsonReader阅读器,对象目标)

在Newtonsoft.Json.JsonSerializer.PopulateInternal(JsonReader阅读器,对象目标)

在Newtonsoft.Json.JsonSerializer.Populate(JsonReader阅读器,对象目标)

在Newtonsoft.Json.JsonConvert.PopulateObject(字符串值,对象目标,JsonSerializerSettings设置)

我写GuidConverter这样并使用它。但不行

public class GuidConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType.IsAssignableFrom(typeof(Guid)); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     try 
     { 
      return serializer.Deserialize<Guid>(reader); 
     } 
     catch 
     { 
      return Guid.Empty; 
     } 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     serializer.Serialize(writer, value); 
    } 
} 

编辑:

,我发现我的问题。更改代码反序列化JSON来解释<字符串,字符串>并产生字典现在第一项是:

Kay: "$type" 
Value : "System.Collections.Generic.Dictionary`2[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 

为什么?

+1

您是否需要dspecial设置和Guid?也许尝试像JsonConvert.SerializeObject(dic);这样更简单,看看是否给你你需要的东西。 – senschen

+0

@senschen我使用泛型类来序列化和反序列化我的项目中的多个类型。我的项目中的其他类型需要此设置。 请阅读我的问题的最后编辑 – Fred

+0

使用字符串,而不是Guid @Fred –

回答

4

问题是您在序列化字典时指定TypeNameHandling = TypeNameHandling.All。这使得元数据"$type"属性被发射以在字典中的第一个对象:

{ 
    "$type": "System.Collections.Generic.Dictionary`2[[System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 
    "9648af76-7986-4b34-8b2c-97b2345769ef": "Test" 
} 

当使用DeserializeObject反序列化,该标记通常是通过Json.NET相应的C#对象被构造时所消耗。但是,您在预先分配的字典上使用了PopulateObject。因此,元数据属性在构造期间不被消耗,而是Json.NET尝试将其添加到字典中,并且失败。

解决方案的设置MetadataPropertyHandling = MetadataPropertyHandling.ReadAheaddeserializeSettings。这样做将导致"$type"属性被消耗或忽略(如适用)无条件地:

var deserializeSettings = new JsonSerializerSettings 
{ 
    TypeNameHandling = TypeNameHandling.All, 
    TypeNameAssemblyFormat = FormatterAssemblyStyle.Full, 
    Formatting = Formatting.Indented, 
    MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead 
}; 
JsonConvert.PopulateObject(serializedObject, newDic, deserializeSettings); 

请注意,从release notes有使用此设置在内存使用和速度了一定的代价。

或者,如果你不无条件地需要在你的JSON元数据类型的信息,您可以用TypeNameHandling = TypeNameHandling.Auto序列化和只能发出类型信息为多态类型,你Dictionary<Guid, string>不是。

+1

非常感谢。你的解决方案很好。 – Fred