2011-07-27 12 views
14

json.net: sözlük tuşları için dönüştürücü belirtin

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

bir sınıfa veri serisini gerekir:

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

Ama MyEnum değerleri CodeA vardır ve CodeB yerine sırasıyla basitçe A ve B

bir JSON var.

Ben dönüşüm işleyebilir özel dönüştürücüsü. Ancak Sözlük anahtarlarıyla kullanılacak bir JsonConverter değerini nasıl belirtebilirim?

cevap

13

Tek yolun, Dictionary<MyEnum, int> türünde veya Dictionary<MyEnum, T> türünde bir JsonConverter oluşturması gerektiğine inanıyorum.

Sözlük tuşları, değerler olarak kabul edilmez ve JsonConverters üzerinden çalıştırılmaz. TypeConverters bir çözüm olurdu, ancak enum dönüşüm için varsayılan dize, TypeConverters'a bakmadan önce girecektir.

Bu yüzden başka bir şekilde yapılabileceğini sanmıyorum.

DÜZENLEME:

tam olarak test değil, ama ben benim bir projede böyle bir şey kullanın:

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); 
    } 

çalışır Umut:

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>(); 
    } 
} 

Bu küçük yardımcıya ihtiyacınız olacak Senin için dışarı.

[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; 
    } 
} 
+1

TypeConverters desteklenmez yana mobil platformlarda Json.NET kullanılırken bu özellikle yararlıdır ve bu yaklaşım: Burada –

+0

Dönüştürücünüzü ne kadar doğru kullanıyorsunuz? Bende benzer bir json var. Ve bunu bir sonraki sınıfa dönüştürmek istiyorum: "public class InsightsReportDataMetric { [JsonProperty (" programlar ")] public InsightsReportDataPrograms [] Programs {get; set; } = new InsightsReportDataPrograms [0]; [JsonProperty ("tarih")] public string Date {get; set; } [JsonConverter (typeof (InsightsMetricConverter))] herkese açık sözlük MetricValues ​​{get; set; } } 'ancak benim örnek dönüştürücüsüne asla ulaşılamıyor ... – demo

0

anahtar herhangi bir tür Sözlük ile json kullanarak problemi için genel bir çözümdür örneğin için gereklidir. anahtarları da yapıları.
+0

Bu genel çözüm nasıl kullanılır? – sky91