【问题标题】:Deserializing complex nested dictionary type with interface values using Json.net使用 Json.net 反序列化具有接口值的复杂嵌套字典类型
【发布时间】:2016-11-17 19:41:00
【问题描述】:

我在尝试使用 Json.net 反序列化具有接口值的非常复杂的嵌套字典类型时遇到问题。代码在这里“https://dotnetfiddle.net/JSoAug”,有问题的类型有:

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>>
{
}

我有几个嵌套级别的包含接口对象的集合或字典(以BlobItem 作为根),并且在每个级别我使用CustomCreationConverter&lt;T&gt; 的子类将接口反序列化为已知的具体类型。但是,在这种情况下,当我尝试这样做时:

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&lt;T&gt; 不起作用?

【问题讨论】:

    标签: c# dictionary nested json.net deserialization


    【解决方案1】:

    问题在于您的BlobItem 类型:

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

    对于TypeXDataDictionary,您指定ItemConverterType = typeof(TypeConverter&lt;IEnumerable&lt;IDataItem&gt;, List&lt;DataItem&gt;&gt;) 来指示如何反序列化TypeXDataDictionary 的值。然而,这本词典实际上是一个词典的词典

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

    因此,它的值不是IEnumerable&lt;IDataItem&gt; 类型,而是Dictionary&lt;string, IEnumerable&lt;IDataItem&gt;&gt; 类型,转换器将无法工作。你需要的是TypeXDictionary的item的转换器,可以定义如下:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-19
      • 2011-09-18
      • 2014-08-21
      • 1970-01-01
      • 2012-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多