2017-09-25 196 views
0

我想序列化/反序列化字典,問題是我用StringComparer.OrdinalIgnoreCase比較器創建字典。用StringComparer反序列化JSON字典

這是我遇到的問題的代碼片段:

var dict = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); 

dict["x"] = new Dictionary<string, string>(); 
dict["x"]["y"] = "something"; 

var serialized = JsonConvert.SerializeObject(dict); 

var unSerialized = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(serialized); 

Console.WriteLine((dict.Comparer == unSerialized.Comparer ? "Same" : "Different")); 

.NET Fiddle - Try It

打印出控制檯上執行以下操作:

Different

顯然, JSON序列化程序不會序列化我在創建字典時設置的比較器,但問題是我無法設置自Dictionary<TKey, TValue>.Comparer以來事件後的比較器是隻讀的。

我確定它與一些自定義JsonSerializerSetting有關,但我似乎無法弄清楚如何攔截集合創建並返回一個帶有不同比較器的字典。

+0

OK ,羅恩,假設你把這個json發送到另一個站點。它如何知道你是如何構建這個詞典的(你甚至可以使用其他方法而不需要任何字典來創建相同的json) –

+0

@ L.B這個應用程序不是基於web的,我使用JSON進行序列化,以實現其他商業原因。數據不會被外部系統處理。 –

+0

這只是一個例子來解釋邏輯。 json的接收者不知道你是如何創建它的。它甚至不知道你用來創建它的語言。所以你做出錯誤的假設 –

回答

2

你可以還填充現有對象與PopulateObject

var dict = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); 

dict["x"] = new Dictionary<string, string>(); 
dict["x"]["y"] = "something"; 

var json = JsonConvert.SerializeObject(dict); 


var result = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); 
JsonConvert.PopulateObject(json, result); 

Console.WriteLine(result["x"]["y"]); 
Console.WriteLine(result.Comparer == dict.Comparer ? "Same" : "Diff"); 

輸出:

something 
Same 
+0

謝謝,這正是我需要的。 –

1

如果傳遞兩個要使用到新字典的構造函數的反序列化的結果和比較器可以指定在你的字典的構造函數使用比較器:

var unSerialized = 
    new Dictionary<string, Dictionary<string, string>> 
     (JsonConvert 
      .DeserializeObject<Dictionary<string, Dictionary<string, string>>>(serialized), 
      dict.Comparer); 
+0

謝謝,我沒有想到將它作爲字典的構造函數中的集合返回。 –

2

這可能有點遲,但可以使用JsonConverter來擴展生成的JSON會稍微複雜一些,但是更加靈活。我創建了所描述的情形下的樣品,它不是完全
.NET Fiddle - Try It
(隨意擴展,如果你決定使用它):

public class DictConverter<TValue> : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return true; 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var obj = JToken.ReadFrom(reader);     
     if (objectType == typeof(Dictionary<string, TValue>)) 
     { 
      var comparer = obj.Value<string>("Comparer"); 
      Dictionary<string, TValue> result; 
      if (comparer == "OrdinalIgnoreCase") 
      { 
       result = new Dictionary<string, TValue>(StringComparer.OrdinalIgnoreCase); 
      } 
      else 
      { 
       result = new Dictionary<string, TValue>(); 
      } 
      obj["Comparer"].Parent.Remove(); 
      serializer.Populate(obj.CreateReader(), result); 
      return result; 
     } 
     return obj.ToObject(objectType); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var obj = JObject.FromObject(value); 
     if (value is Dictionary<string, TValue>) 
     { 
      if((value as Dictionary<string, TValue>).Comparer == StringComparer.OrdinalIgnoreCase) 
       obj.Add("Comparer", JToken.FromObject("OrdinalIgnoreCase")); 
     } 
     obj.WriteTo(writer); 

    } 
} 

和使用

var dict = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); 

dict["x"] = new Dictionary<string, string>(); 
dict["x"]["y"] = "something"; 

var serialized = JsonConvert.SerializeObject(dict, 
    new DictConverter<Dictionary<string,string>>()); 
var unSerialized = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>> 
    (serialized, new DictConverter<Dictionary<string, string>>());