当 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。该算法的简化版本如下:
- 属性名称是从 JSON 文件中读取的。
- 找到最匹配的构造函数参数(如果有)。
- 找到最接近的匹配成员名称(如果有)。
- 如果 JSON 属性与构造函数参数匹配,则反序列化为该类型并传递到构造函数中,
- 但如果不是,则反序列化为适当的成员类型并在构造后设置成员值。
(当 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显示两个选项。