使用Json.net使用接口值反序列化复杂的嵌套字典类型 [英] Deserializing complex nested dictionary type with interface values using Json.net

查看:58
本文介绍了使用Json.net使用接口值反序列化复杂的嵌套字典类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试使用Json.net使用接口值反序列化一个非常复杂的嵌套字典类型时遇到问题.代码位于此处" https://dotnetfiddle.net/JSoAug ",所涉及的类型为:

I am having a problem trying to deserialize a pretty complex nested dictionary type with interface values using Json.net. The code is located here "https://dotnetfiddle.net/JSoAug", and the types in question are:

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为根)的集合或字典级别,在每个级别上,我都使用

I have several nested levels of collections or dictionaries containing interface objects (with BlobItem as the root), and at each level I use a subclass of CustomCreationConverter<T> to deserialize the interfaces as known concrete types. However, in this case, when I attempt to do so as follows:

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>不起作用?

推荐答案

问题出在您的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<IEnumerable<IDataItem>, List<DataItem>>)来指示如何反序列化TypeXDataDictionary的值.但是,这本词典实际上是词典的字典:

For TypeXDataDictionary you specify an ItemConverterType = typeof(TypeConverter<IEnumerable<IDataItem>, List<DataItem>>) to indicate how to deserialize the values of the TypeXDataDictionary. However, this dictionary is actually a dictionary of dictionaries:

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

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

因此它的值不是IEnumerable<IDataItem>类型,它们的值是Dictionary<string, IEnumerable<IDataItem>>类型,并且转换器将无法工作.您需要的是TypeXDictionary项的项的转换器,可以将其定义如下:

Thus its values are not of type IEnumerable<IDataItem>, they are of type Dictionary<string, IEnumerable<IDataItem>> and the converter will not work. What you need is a converter for the items of the items of the TypeXDictionary, which can be defined as follows:

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,如下所示:

Then applied to BlobItem as follows:

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

}

样本小提琴.

这篇关于使用Json.net使用接口值反序列化复杂的嵌套字典类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆