2016-03-25 91 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