使用 Json.net 反序列化具有接口值的复杂嵌套字典类型

2024-01-12

我在尝试使用 Json.net 反序列化具有接口值的相当复杂的嵌套字典类型时遇到问题。代码位于此处“https://dotnetfiddle.net/JSoAug 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<T> http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Converters_CustomCreationConverter_1.htm将接口反序列化为已知的具体类型。但是,在这种情况下,当我尝试执行以下操作时:

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 type:

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

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

}

Sample fiddle https://dotnetfiddle.net/dxybGa.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Json.net 反序列化具有接口值的复杂嵌套字典类型 的相关文章

随机推荐

  • 更改 SwiftUI 中的 DisclosureGroup 指示符图像

    我正在尝试更改 SwiftUI 中 DisclosureGroup 的指示符图像 理想情况下 我想要一个自定义图像 我尝试用自己的方法来实现这一点ButtonStyle struct TestButtonStyle ButtonStyle
  • 在docker容器中安装Postgis

    我像往常一样使用 postgres 图像通过 docker 创建了一个数据库 docker run d name some postgres e POSTGRES PASSWORD mypassword v HOME postgres da
  • 错误“安全警告:没有向 Rack::Session::Cookie 提供秘密选项”[重复]

    这个问题在这里已经有答案了 可能的重复 没有为 Rack Session Cookie 警告提供秘密选项 https stackoverflow com questions 10374871 no secret option provide
  • HTML5 表单验证真的可以访问吗?

    所以我读了很多文章说 HTML 5 表单验证是可以访问的 东西required属性将阻止表单被提交 字段留空 但是当我在 Chrome 上的 NVDA 和 Android 上的 BackTalk 上测试我的表单时 如果我没有填写输入 它会重
  • Uiautomatorviewer SWT 异常

    由于 StackExchange 建议我不要寻求帮助或澄清以前存在的帖子 https stackoverflow com questions 48128648 uiautomatorviewer is not working throwin
  • 多线程问题

    我正在使用计时器来重置用作警告框的标签 基本上 如果用户做了某件事 更具体地说 出了问题 例如 他使用了程序无法识别的单词 这会尽早捕获出现的问题并将发生的情况返回给他 以便他可以更改输入 重置会在 5 秒后清空标签 以防止他看到类似 请不
  • 使用 mget() 将 data.table 与 rbindlist() 连接时出现意外错误消息

    准备的同时这个答案 https stackoverflow com a 47670107 3817004 我收到错误消息 错误 找不到 spine hlfs 的值 从跑步 setDT giraffe rbindlist mget df na
  • Android 标记自定义信息窗口

    我正在使用谷歌地图V2 我需要展示ListView 风俗ListView带图像 自定义InfoWindow 我尝试过并且只在以下方面取得了成功View 问题是我无法得到listItemClick event googleMap setInf
  • 当函数属于必须解析的类时,如何向 IServiceCollection 注册委托或函数?

    我正在使用 Microsoft Extensions DependencyInjection 中的 IServiceCollection IServiceProvider 我想将委托注入到一个类中 public delegate Valid
  • Java 将表面分割成小方块

    我想知道是否有任何算法可以执行以下操作 给定一个特定的表面 它将其分成相同大小的更小的矩形 像这个示例图一样 灰色区域是表面 红色方块是分区本身 我在想是否有一种优化的方法来做到这一点 一个非常糟糕的方法是在所有像素中进行 for 循环 并
  • 将日期格式更改为 ddth mmm,yyyy

    我正在网络表单上打印一些日期 目前我的日期格式是dd mmm yyyy hh mm 如何将日期格式更改为ddth mmm yyyy for例子2016年5月17日 hh mm 这是我的代码 lastlogin DateTime Parse
  • /usr/bin/ld: 找不到 -lpthreads

    我正在 Fedora 22 上编译 NVIDIA Caffe 工具 但遇到问题需要查找lpthread图书馆 Determining if the pthread create exist failed with the following
  • 如何更改R图表中的默认字体大小

    我正在使用 R 包 cooccurr 无法弄清楚如何更改关联图形中的字体大小 par 方法似乎不起作用 这是包中给出的示例 data finches cooccur finches lt cooccur mat finches type s
  • 模块模式与匿名构造函数的实例

    于是就有了这个所谓的模块模式用于创建具有私有成员的单例 var foo function var foo private return foo function console log foo bar public 还有这个方法是我自己找到
  • 如何使用 click 来解析字符串中的参数?

    假设我有一个包含参数和选项的字符串列表 其中argparse 我可以使用以下方法解析这个列表parse args将函数转化为对象 如下 import argparse extra params sum 7 1 42 parser argpa
  • 如果中断 Git 推送会发生什么?

    我运行了以下命令 git push u origin master 推送 非常大 文件很多 所以上传需要时间 中途我发现我忘记添加几个文件 所以我做了 Ctrl C 在终端 中断 Git 然后做完之后git add 我又承诺了 然后又推了
  • DDD - 如何设计不同限界上下文之间的关联

    我已经设置了一个正在使用 ORM 填充的域项目 该域包含不同的聚合 每个聚合都有自己的根对象 我的问题是应该如何处理跨越聚合边界的属性 这些属性是否应该简单地忽略边界 以便有界上下文 A 中的域对象可以引用上下文 B 中的对象 或者 是否应
  • 如何检查一次 UserDefaults 是否为空

    我的应用程序计算日期和 NSDate 之间的天数 当我发布它时 用户只能保存一个日期 一个标题和一张背景图像 现在我有一个 UICollectionView 可以选择保存多个日期 并且它将通过将日期 标题和图像字符串附加到各自的数组来创建一
  • 分叉进程的执行顺序

    我知道还有另一个同名的线程 但这实际上是一个不同的问题 当一个进程多次分叉时 父进程是否先于子进程完成执行 反之亦然 同时 这是一个例子 假设我有一个 for 循环 将 1 个父进程分叉为 4 个子进程 在 for 循环结束时 我希望父进程
  • 使用 Json.net 反序列化具有接口值的复杂嵌套字典类型

    我在尝试使用 Json net 反序列化具有接口值的相当复杂的嵌套字典类型时遇到问题 代码位于此处 https dotnetfiddle net JSoAug https dotnetfiddle net JSoAug 有问题的类型是 pu