2011-07-27 66 views
14

我有一個JSON:json.net:指定字典鍵轉換

{ 
    "data": { "A": 5, "B": 6 }, 
    "foo": "foo", 
    "bar": "bar" 
} 

我需要將數據反序列化到一個類:

public Dictionary<MyEnum, int> Data { get; set; } 
public string Foo { get; set; } 
public string Bar { get; set; } 

但MyEnum值CodeACodeB代替分別爲AB

我有一個可以處理轉換的自定義轉換器。但是,如何指定JsonConverter與Dictionary鍵配合使用?

回答

13

我相信唯一的辦法是爲整個Dictionary<MyEnum, int>類型或Dictionary<MyEnum, T>製作一個JsonConverter。

字典鍵不被視爲值,不會通過JsonConverters運行。 TypeConverters應該是一個解決方案,但是在查看TypeConverters之前,默認的enum轉換字符串將會進入。

所以......我不認爲這是可以做任何其他方式。

編輯:

完全測試,但我用這樣的事情在我的一個項目:

public class DictionaryWithSpecialEnumKeyConverter : JsonConverter 
{ 
    public override bool CanWrite 
    { 
     get { return false; } 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotSupportedException(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 

     var valueType = objectType.GetGenericArguments()[1]; 
     var intermediateDictionaryType = typeof(Dictionary<,>).MakeGenericType(typeof(string), valueType); 
     var intermediateDictionary = (IDictionary)Activator.CreateInstance(intermediateDictionaryType); 
     serializer.Populate(reader, intermediateDictionary); 

     var finalDictionary = (IDictionary)Activator.CreateInstance(objectType); 
     foreach (DictionaryEntry pair in intermediateDictionary) 
      finalDictionary.Add(Enum.Parse(MyEnum, "Code" + pair.Key, false), pair.Value); 

     return finalDictionary; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType.IsA(typeof(IDictionary<,>)) && 
       objectType.GetGenericArguments()[0].IsA<MyEnum>(); 
    } 
} 

你需要這個小幫手:

public static bool IsA(this Type type, Type typeToBe) 
    { 
     if (!typeToBe.IsGenericTypeDefinition) 
      return typeToBe.IsAssignableFrom(type); 

     var toCheckTypes = new List<Type> { type }; 
     if (typeToBe.IsInterface) 
      toCheckTypes.AddRange(type.GetInterfaces()); 

     var basedOn = type; 
     while (basedOn.BaseType != null) 
     { 
      toCheckTypes.Add(basedOn.BaseType); 
      basedOn = basedOn.BaseType; 
     } 

     return toCheckTypes.Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeToBe); 
    } 

希望工程爲你而出。

+1

在移動平臺上使用Json.Net時,因爲類型轉換器不支持,這是特別有幫助的,而這種做法是例如需要。結構也是關鍵。 –

+0

如何正確使用你的轉換器?我有類似的json。我想把它變成下一個類:'public class InsightsReportDataMetric { [JsonProperty(「programs」)] public InsightsReportDataPrograms [] Programs {get;組; } = new InsightsReportDataPrograms [0]; [JsonProperty(「date」)] public string Date {get;組; } [JsonConverter(typeof(InsightsMetricConverter))] public Dictionary MetricValues {get;組; } }'但在我的例子中轉換器永遠不會到達... – demo

0

下面是使用JSON與字典與任何類型的關鍵問題一個通用的解決方案:

[JsonObject] 
public class MyKeyValuePair<TKey, TValue> 
{ 
    public TKey MyKey; 

    public TValue MyValue; 

    [JsonConstructor] 
    public MyKeyValuePair() 
    { 

    } 

    public MyKeyValuePair(TKey t1, TValue t2) 
    { 
     MyKey = t1; 
     MyValue = t2; 
    } 
} 



[JsonObject] 
public class MyDictionaty<TKey, TValue> 

{ 
    public ICollection<MyKeyValuePair<TKey, TValue>> Collection; 

    [JsonConstructor] 
    public MyDictionaty() 
    { 

    } 
    public MyDictionaty(Dictionary<TKey, TValue> refund) 
    { 
     Collection = BuildMyKeyValuePairCollection(refund); 
    } 
    internal Dictionary<TKey, TValue> ToDictionary() 
    { 
     return Collection.ToDictionary(pair => pair.MyKey, pair => pair.MyValue); 
    } 

    private ICollection<MyKeyValuePair<TKey, TValue>> BuildMyKeyValuePairCollection(Dictionary<TKey, TValue> refund) 
    { 
     return refund.Select(o => new MyKeyValuePair<TKey, TValue>(o.Key, o.Value)).ToList(); 
    } 
} 




[JsonObject] 
public class ClassWithDictionary 
{ 
    [JsonProperty] 
    private readonly MyDictionary<AnyKey, AnyValue> _myDictionary; 

    private Dictionary<AnyKey, AnyValue> _dic; 

    [JsonConstructor] 
    public ClassWithDictionary() 
    { 

    } 
    public ClassWithDictionary(Dictionary<AnyKey, AnyValue> dic) 
    { 
     _dic= dic; 
     _myDictionary = new MyDictionaty<AnyKey, AnyValue>(dic); 
    } 

    public Dictionary<AnyKey, AnyValue> GetTheDictionary() 
    { 
     _dic = _dic??_myDictionary.ToDictionary(); 
     return _dic; 
    } 
} 
+0

如何使用這個通用的解決方案? – sky91