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

通过JsonConstructor使用特定的.ctor反序列化IList属性时,参数名称必须与原始 Json名称匹配,并且不使用这些属性上的JsonProperty映射。

例:

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

 public partial class AClass : ISomeBase { public AClass() { } [JsonConstructor] public AClass(IList SysTypes, IList production_countries, IList SpokenLanguages) { this.Genres = SysTypes?.ToList(); this.ProductionCountries = production_countries?.ToList(); this.SpokenLanguages = SpokenLanguages?.ToList(); } public int Id { get; set; } public IList Genres { get; set; } [JsonProperty("production_countries")] public IList ProductionCountries { get; set; } [JsonProperty("spoken_languages")] public IList SpokenLanguages { get; set; } } 

这只是Json.Net如何调用构造函数的“限制”,还是我缺少的东西。

仅供参考:我是通过Rosyln生成所有这些的代码,我不打算JsonConverter生成每种类型的JsonConverter

当Json.NET调用参数化构造函数时,它会按名称将JSON属性与构造函数参数匹配。 但是,对于也与类型成员对应的JSON属性,它使用哪个名称 – 成员名称,或者由JsonPropertyAttribute.PropertyName指定的覆盖类型成员名称?

看来你希望它们都匹配,因为你的参数命名约定是不一致的:

  • 构造函数参数production_countries匹配重写的属性名称:

     [JsonProperty("production_countries")] public IList ProductionCountries { get; set; } 
  • 构造函数参数IList SpokenLanguages匹配reflection的名称而不是重写的属性名称:

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

但是,重要的是JSON文件本身中的属性名称和JsonSerializerInternalReader.ResolvePropertyAndCreatorValues()显示的构造函数参数名称 。 该算法的简化版本如下:

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

(当JSON属性与两者兼容时,实现变得复杂,并且开发人员期望在构造函数中设置时,应该尊重添加到成员的[JsonProperty(Required = Required.Always)] 。)

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

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

 public partial class AClass : ISomeBase { public AClass() { } [JsonConstructor] public AClass([JsonProperty("Genres")] IList SysTypes, IList production_countries, [JsonProperty("spoken_languages")] IList SpokenLanguages) { this.Genres = SysTypes == null ? null : SysTypes.Cast().ToList(); this.ProductionCountries = production_countries == null ? null : production_countries.Cast().ToList(); this.SpokenLanguages = SpokenLanguages == null ? null : SpokenLanguages.Cast().ToList(); } 

其次,由于您似乎使用构造函数将包含接口的集合中的项目反序列化为具体对象,因此您可以考虑使用基于CustomCreationConverter的单个通用转换器作为ItemConverter

 public partial class AClass : ISomeBase { public AClass() { } public int Id { get; set; } [JsonProperty(ItemConverterType = typeof(CustomCreationConverter))] public IList Genres { get; set; } [JsonProperty("production_countries", ItemConverterType = typeof(CustomCreationConverter))] public IList ProductionCountries { get; set; } [JsonProperty("spoken_languages", ItemConverterType = typeof(CustomCreationConverter))] public IList SpokenLanguages { get; set; } } public class CustomCreationConverter : CustomCreationConverter where TSerialized : T, new() { public override T Create(Type objectType) { return new TSerialized(); } } 

显示两个选项的示例小提琴 。