Json.net `JsonConstructor` 构造函数参数名称

2024-03-17

当使用特定的 .ctor 时JsonConstructor用于反序列化IList<ISomeInterface>属性,参数名称必须匹配originalJson 名称和JsonProperty不使用这些属性上的映射。

Example:

SpokenLanguages参数始终为空,因为它不匹配spoken_languages,但是有一个JsonProperty映射它:

public partial class AClass : ISomeBase
{
    public AClass() { }

    [JsonConstructor]
    public AClass(IList<SysType> SysTypes, IList<ProductionCountry> production_countries, IList<SpokenLanguage> SpokenLanguages)
    {
        this.Genres = SysTypes?.ToList<IGenre>();
        this.ProductionCountries = production_countries?.ToList<IProductionCountry>();
        this.SpokenLanguages = SpokenLanguages?.ToList<ISpokenLanguage>();
    }

    public int Id { get; set; }
    public IList<IGenre> Genres { get; set; }
    [JsonProperty("production_countries")]
    public IList<IProductionCountry> ProductionCountries { get; set; }
    [JsonProperty("spoken_languages")]
    public IList<ISpokenLanguage> SpokenLanguages { get; set; }
}

这只是一种“限制”吗?Json.Net调用构造函数或者我缺少什么。

仅供参考:我正在通过 Rosyln 生成所有这些代码,并且不考虑生成JsonConverter对于每种类型...


当 Json.NET 调用参数化构造函数时,它会使用忽略序数大小写的匹配,按名称将 JSON 属性与构造函数参数进行匹配。但是,对于也对应于类型成员的 JSON 属性,它使用哪个名称 - 成员名称,或由 指定的覆盖类型成员名称JsonPropertyAttribute.PropertyName http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonPropertyAttribute_PropertyName.htm?

看来您希望它匹配both,因为您的参数命名约定不一致:

  • 构造函数参数production_countries匹配覆盖的属性名称:

     [JsonProperty("production_countries")]
     public IList<IProductionCountry> ProductionCountries { get; set; }
    
  • 构造函数参数IList<SpokenLanguage> SpokenLanguages匹配反射的名称而不是覆盖的属性名称:

     [JsonProperty("spoken_languages")]
     public IList<ISpokenLanguage> SpokenLanguages { get; set; }
    
  • IList<SysType> SysTypes两者都不匹配(这是问题中的拼写错误吗?)

然而,重要的是属性名称在 JSON 文件本身中构造函数参数名称如图所示JsonSerializerInternalReader.ResolvePropertyAndCreatorValues() https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs#L2136。该算法的简化版本如下:

  1. 属性名称是从 JSON 文件中读取的。
  2. 找到最匹配的构造函数参数(如果有)。
  3. 找到最接近的匹配成员名称(如果有)。
  4. 如果 JSON 属性与构造函数参数匹配,则反序列化为该类型并传递到构造函数中,
  5. 但如果不是,则反序列化为适当的成员类型并在构造后设置成员值。

(当 JSON 属性匹配时,实现会变得复杂both开发人员期望,例如,[JsonProperty(Required = Required.Always)] http://www.newtonsoft.com/json/help/html/JsonPropertyRequired.htm在构造函数中设置时,应尊重添加到成员的内容。)

因此构造函数参数production_countries将匹配名为的值"production_countries"在 JSON 中,而构造函数参数SpokenLanguages will not匹配名为的 JSON 值"spoken_languages".

那么,如何成功反序列化你的类型呢?首先,您可以标记构造函数参数[JsonProperty(overrideName)]覆盖反序列化期间使用的构造函数名称:

public partial class AClass : ISomeBase
{
    public AClass() { }

    [JsonConstructor]
    public AClass([JsonProperty("Genres")] IList<SysType> SysTypes, IList<ProductionCountry> production_countries, [JsonProperty("spoken_languages")] IList<SpokenLanguage> SpokenLanguages)
    {
        this.Genres = SysTypes == null ? null : SysTypes.Cast<IGenre>().ToList();
        this.ProductionCountries = production_countries == null ? null : production_countries.Cast<IProductionCountry>().ToList();
        this.SpokenLanguages = SpokenLanguages == null ? null : SpokenLanguages.Cast<ISpokenLanguage>().ToList();
    }

其次,由于您似乎正在使用构造函数来反序列化包含接口作为具体对象的集合中的项目,因此您可以考虑使用基于CustomCreationConverter http://www.newtonsoft.com/json/help/html/DeserializeCustomCreationConverter.htm as an ItemConverter http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonPropertyAttribute_ItemConverterType.htm:

public partial class AClass : ISomeBase
{
    public AClass() { }

    public int Id { get; set; }

    [JsonProperty(ItemConverterType = typeof(CustomCreationConverter<IGenre, SysType>))]
    public IList<IGenre> Genres { get; set; }

    [JsonProperty("production_countries", ItemConverterType = typeof(CustomCreationConverter<IProductionCountry, ProductionCountry>))]
    public IList<IProductionCountry> ProductionCountries { get; set; }

    [JsonProperty("spoken_languages", ItemConverterType = typeof(CustomCreationConverter<ISpokenLanguage, SpokenLanguage>))]
    public IList<ISpokenLanguage> SpokenLanguages { get; set; }
}

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

小提琴示例 https://dotnetfiddle.net/og3nhP显示两个选项。

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

Json.net `JsonConstructor` 构造函数参数名称 的相关文章

  • OpenCv读/写视频色差

    我试图简单地使用 openCV 打开视频 处理帧并将处理后的帧写入新的视频文件 我的问题是 即使我根本不处理帧 只是打开视频 使用 VideoCapture 读取帧并使用 VideoWriter 将它们写入新文件 输出文件看起来比输入更 绿
  • asp.net 文本框文本模式数字,仅允许数字

    我只是想知道 ASP NET 中是否有一种方法只允许文本框中的数字textmode number 当我使用这个时
  • 以编程方式检查页面是否需要基于 web.config 设置进行身份验证

    我想知道是否有一种方法可以检查页面是否需要基于 web config 设置进行身份验证 基本上如果有这样的节点
  • C++:重写已弃用的虚拟方法时出现弃用警告

    我有一个纯虚拟类 它有一个纯虚拟方法 应该是const 但不幸的是不是 该接口位于库中 并且该类由单独项目中的其他几个类继承 我正在尝试使用这个方法const不会破坏兼容性 至少在一段时间内 但我找不到在非常量方法重载时产生警告的方法 以下
  • Clang 编译器 (x86):80 位长双精度

    我正在尝试在 x86 Windows 平台上使用本机 80 位长双精度 海湾合作委员会选项 mlong double 80 https gcc gnu org onlinedocs gcc x86 Options html似乎不适用于 cl
  • POCO HTTPSClientSession 发送请求时遇到问题 - 证书验证失败

    我正在尝试使用 POCO 库编写一个向服务器发出 HTTPS 请求的程序 出于测试目的 我正在连接到具有自签名证书的服务器 并且我希望允许客户端进行连接 为了允许这种情况发生 我尝试安装InvalidCertificateHandler这是
  • 从多个类访问串行端口

    我正在尝试使用串行端口在 arduino 和 C 程序之间进行通信 我对 C 编程有点陌生 该程序有多种用户控制形式 每一个都需要访问串口来发送数据 我需要做的就是从每个类的主窗体中写入串行端口 我了解如何设置和写入串行端口 这是我的 Fo
  • C 语言中 =+(等于加)是什么意思?

    我碰到 与标准相反 今天在一些 C 代码中 我不太确定这里发生了什么 我在文档中也找不到它 In ancientC 版本 相当于 它的残余物与最早的恐龙骨头一起被发现 例如 B 引入了广义赋值运算符 使用x y to add y to x
  • Azure 事件中心 - 按顺序接收事件

    我使用下面的代码从 Azure Event Hub 接收事件 https learn microsoft com en us azure event hubs event hubs dotnet framework getstarted s
  • 为什么我不应该对不是由 malloc() 分配的变量调用 free() ?

    我在某处读到 使用它是灾难性的free删除不是通过调用创建的对象malloc 这是真的 为什么 这是未定义的行为 永远不要尝试它 让我们看看当您尝试时会发生什么free 自动变量 堆管理器必须推断出如何获取内存块的所有权 为此 它要么必须使
  • 将构建日期放入“关于”框中

    我有一个带有 关于 框的 C WinForms 应用程序 我使用以下方法将版本号放入 关于 框中 FileVersionInfo GetVersionInfo Assembly GetExecutingAssembly Location F
  • 当“int”处于最大值并使用 postfix ++ 进行测试时,代码定义良好吗?

    示例 未定义行为的一个示例是整数溢出的行为 C11dr 3 4 3 3 int溢出是未定义的行为 但这是否适用于存在循环的以下内容 并且不使用现在超出范围的副作用i 特别是 这是否后缀增量规格帮助 结果的值计算在副作用之前排序 更新操作数的
  • 如何挤出平面 2D 网格并赋予其深度

    我有一组共面 连接的三角形 即二维网格 现在我需要将其在 z 轴上挤出几个单位 网格由一组顶点定义 渲染器通过与三角形数组匹配来理解这些顶点 网格示例 顶点 0 0 0 10 0 0 10 10 0 0 10 0 所以这里我们有一个二维正方
  • g++ 对于看似不相关的变量“警告:迭代...调用未定义的行为”

    考虑以下代码strange cpp include
  • 结构体指针的动态数组

    我必须使用以下代码块来完成学校作业 严格不进行任何修改 typedef struct char firstName char lastName int id float mark pStudentRecord pStudentRecord
  • 剪贴板在 .NET 3.5 和 4 中的行为有所不同,但为什么呢?

    我们最近将一个非常大的项目从 NET Framework 3 5 升级到 4 最初一切似乎都工作正常 但现在复制粘贴操作开始出现错误 我已经成功制作了一个小型的可复制应用程序 它显示了 NET 3 5 和 4 中的不同行为 我还找到了一种解
  • 使用 C# 从 DateTime 获取日期

    愚蠢的问题 给定日期时间中的日期 我知道它是星期二 例如我如何知道它的 tue 2 和 mon 1 等 Thanks 您正在寻找星期几 http msdn microsoft com en us library system datetim
  • 使用 CSharpCodeProvider 类编译 C# 7.3 的 C# 编译器版本是什么?

    我想使用 Microsoft CSharp CSharpCodeProvider 类来编译 C 7 3 代码 编译器版本在 IDictionary 中指定 在创建新的 CSharpCodeProvider 时将其作为输入 例如 Compil
  • Googletest:如何异步运行测试?

    考虑到一个包含数千个测试的大型项目 其中一些测试需要几分钟才能完成 如果按顺序执行 整套测试需要一个多小时才能完成 通过并行执行测试可以减少测试时间 据我所知 没有办法直接从 googletest mock 做到这一点 就像 async选项
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检

随机推荐