gpt4 book ai didi

c# - 使用 Json.net 反序列化具有接口(interface)值的复杂嵌套字典类型

转载 作者:太空宇宙 更新时间:2023-11-03 15:12:15 25 4
gpt4 key购买 nike

我在尝试使用 Json.net 反序列化具有接口(interface)值的相当复杂的嵌套字典类型时遇到问题。代码位于此处“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>>
{
}

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

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 的值.然而,这本词典实际上是一个词典的词典:

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

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

因此它的值不是 IEnumerable<IDataItem> 类型的, 它们的类型是 Dictionary<string, 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 .

关于c# - 使用 Json.net 反序列化具有接口(interface)值的复杂嵌套字典类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40663658/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com