2016-11-17 15 views
2

Json.netを使用してインターフェイス値を持つかなり複雑なネストされた辞書型を逆シリアル化しようとすると問題が発生します。コードは「https://dotnetfiddle.net/JSoAug」ここに配置され、そして問題のタイプがある:Json.netを使用してインターフェイス値を持つ複雑なネストされた辞書型を逆シリアル化する

public class TypeConverter<T, TSerialized> : CustomCreationConverter<T> 
    where TSerialized : T, new() 
{ 
    public override T Create(Type objectType) 
    { 
     return new TSerialized(); 
    } 
} 

public interface IValue 
{ 
    Dictionary<string, IValue> SomeValues { get; set; } 
} 

public class Value : IValue 
{ 
    [JsonProperty(ItemConverterType = typeof(TypeConverter<IValue, Value>))] 
    public Dictionary<string, IValue> SomeValues { get; set; } 
} 

public interface ISomeAtrributes 
{ 
    Dictionary<string, object> Attributes { get; set; } 
} 

public interface IDataItem : ISomeAtrributes 
{ 
    IValue Value { get; set; } 
} 

public class DataItem : IDataItem 
{ 
    [JsonProperty(ItemConverterType = typeof(TypeConverter<IValue, Value>))] 
    public IValue Value { get; set; } 

    public Dictionary<string, object> Attributes { get; set; } 
} 

public interface IBlobItem 
{ 
    TypeXDictionary<IEnumerable<IDataItem>> TypeXDataDictionary { get; set; } 
} 

public class BlobItem : IBlobItem 
{ 
    public BlobItem() 
    { 
     TypeXDataDictionary = new TypeXDictionary<IEnumerable<IDataItem>>(); 
    } 

    [JsonProperty(ItemConverterType = typeof(TypeConverter<IEnumerable<IDataItem>, List<DataItem>>))] 
    public TypeXDictionary<IEnumerable<IDataItem>> TypeXDataDictionary { get; set; } 

} 

public class TypeYDictionary<T> : Dictionary<string, T> 
{ 
} 

public class TypeXDictionary<T> : Dictionary<string, TypeYDictionary<T>> 
{ 
} 

Iは、コレクション又は(ルートとしてBlobItemで)インターフェイスオブジェクトを含む辞書のいくつかのネストされたレベルを有し、各レベルで私が使用しますCustomCreationConverter<T>のサブクラスを使用して、既知の具象型としてインタフェースを逆シリアル化します。しかし、この場合には、私は次のようにそうしようとしたとき:

var blobItem = new BlobItem(); 
var dataItemDic = new TypeYDictionary<IEnumerable<IDataItem>>(); 
var objDic = new Dictionary<string, object> {{"key", "object"}}; 
dataItemDic.Add("dataItemKey", new List<DataItem>() { new DataItem() { Attributes = objDic } }); 
blobItem.TypeXDataDictionary.Add("typeXKey", dataItemDic); 
var ser = JsonConvert.SerializeObject(blobItem); 

var deSerialized = JsonConvert.DeserializeObject<BlobItem>(ser); 

私は例外を受け取る:

Run-time exception (line 19): Cannot populate JSON object onto type 'System.Collections.Generic.List`1[JsonSerialization.DataItem]'. Path 'TypeXDataDictionary.typeXKey.dataItemKey', line 1, position 50. 

Stack Trace: 

[Newtonsoft.Json.JsonSerializationException: Cannot populate JSON object onto type 'System.Collections.Generic.List`1[JsonSerialization.DataItem]'. Path 'TypeXDataDictionary.typeXKey.dataItemKey', line 1, position 50.] 
    at JsonSerialization.Program.Main(String[] args): line 19 

はなぜCustomCreationConverter<T>が動作していませんか?

答えて

0

問題は、あなたのBlobItemタイプである:あなたがTypeXDataDictionaryの値をデシリアライズする方法を示すためにItemConverterType = typeof(TypeConverter<IEnumerable<IDataItem>, List<DataItem>>)を指定TypeXDataDictionaryするため

public class BlobItem : IBlobItem 
{ 
    public BlobItem() 
    { 
     TypeXDataDictionary = new TypeXDictionary<IEnumerable<IDataItem>>(); 
    } 

    [JsonProperty(ItemConverterType = typeof(TypeConverter<IEnumerable<IDataItem>, List<DataItem>>))] 
    public TypeXDictionary<IEnumerable<IDataItem>> TypeXDataDictionary { get; set; } 
} 

。しかし、この辞書は、実際の辞書の辞書です:

public class TypeXDictionary<T> : Dictionary<string, TypeYDictionary<T>> 
{ 
} 

public class TypeYDictionary<T> : Dictionary<string, T> 
{ 
} 

したがってその値は、彼らがタイプDictionary<string, IEnumerable<IDataItem>>のものであり、コンバータが動作しません、タイプIEnumerable<IDataItem>ではありません。何が必要、次のように定義することができTypeXDictionary、の項目の項目のためのコンバータです:

public class DictionaryValueTypeConverter<TDictionary, TKey, TValue, TValueSerialized> : JsonConverter 
    where TDictionary : class, IDictionary<TKey, TValue>, new() 
    where TValueSerialized : TValue 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     throw new NotImplementedException(); 
    } 

    public override bool CanWrite { get { return false; } } 

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     var surrogate = serializer.Deserialize<Dictionary<TKey, TValueSerialized>>(reader); 
     if (surrogate == null) 
      return null; 
     var dictionary = existingValue as TDictionary ?? new TDictionary(); 
     foreach (var pair in surrogate) 
      dictionary[pair.Key] = pair.Value; 
     return dictionary; 
    } 
} 

そして、次のようにBlobItemに適用:

public class BlobItem : IBlobItem 
{ 
    public BlobItem() 
    { 
     TypeXDataDictionary = new TypeXDictionary<IEnumerable<IDataItem>>(); 
    } 

    [JsonProperty(ItemConverterType = typeof(DictionaryValueTypeConverter<TypeYDictionary<IEnumerable<IDataItem>>, string, IEnumerable<IDataItem>, List<DataItem>>))] 
    public TypeXDictionary<IEnumerable<IDataItem>> TypeXDataDictionary { get; set; } 

} 

サンプルfiddleを。

関連する問題