Json.net`JsonConstructor`构造函数参数名称 [英] Json.net `JsonConstructor` constructor parameter names
问题描述
当通过JsonConstructor
使用特定的.ctor来反序列化IList<ISomeInterface>
属性时,参数名称必须与原始 Json名称匹配,并且不使用这些属性上的JsonProperty
映射. /p>
示例:
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属性,它使用的名称是-成员名称,还是
构造函数参数 但是,重要的是JSON文件本身中的属性名称 和构造函数参数名称,如 因此,构造函数自变量 那么,如何成功反序列化您的类型?首先,您可以用 第二,由于您似乎正在使用构造函数反序列化包含作为具体对象的接口的集合中的项目,因此您可以考虑使用基于 示例小提琴显示了这两个选项. When using a specific .ctor via Is this just a "limitation" of how FYI: I am code generating all this via Rosyln and am not looking at generating a When Json.NET invokes a parameterized constructor, it matches JSON properties to constructor arguments by name. However, for JSON properties that also correspond to type members, which name does it use - the member name, or the override type member name specified by It appears you are hoping it matches on both, since your argument naming conventions are inconsistent: The constructor argument The constructor argument However, what matters is the property name in the JSON file itself and the constructor argument name as shown in (The implementation becomes complex when a JSON property matches both and developers expect that, for instance, Thus the constructor argument So, how to deserialize your type successfully? Firstly, you could mark the constructor parameters with Secondly, since you seem to be using the constructor to deserialize items in collections containing interfaces as concrete objects, you could consider using a single generic converter based on Example fiddle showing both options. 这篇关于Json.net`JsonConstructor`构造函数参数名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!IList<SpokenLanguage> SpokenLanguages
与反映的名称匹配,而不是覆盖的属性名称:[JsonProperty("spoken_languages")]
public IList<ISpokenLanguage> SpokenLanguages { get; set; }
IList<SysType> SysTypes
都不匹配(这是问题中的错字吗?)[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<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();
}
ItemConverter
: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();
}
}
JsonConstructor
for deserializing IList<ISomeInterface>
properties, the parameter names must match the original Json names and the JsonProperty
mapping on those properties are not used.Example:
SpokenLanguages
parameter is always null since it does not match spoken_languages
, but there is a JsonProperty
mapping it: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
calls the constructor or is there something I am missing.JsonConverter
for each type for this...JsonPropertyAttribute.PropertyName
?
production_countries
matches the overridden property name:[JsonProperty("production_countries")]
public IList<IProductionCountry> ProductionCountries { get; set; }
IList<SpokenLanguage> SpokenLanguages
matches the reflected name rather than the overridden property name:[JsonProperty("spoken_languages")]
public IList<ISpokenLanguage> SpokenLanguages { get; set; }
IList<SysType> SysTypes
matches neither (is this a typo in the question?)JsonSerializerInternalReader.ResolvePropertyAndCreatorValues()
. A simplified version of the algorithm is as follows:
[JsonProperty(Required = Required.Always)]
added to the member should be respected when set in the constructor.)production_countries
will match a value named "production_countries"
in the JSON, while the constructor argument SpokenLanguages
will not match a JSON value named "spoken_languages"
.[JsonProperty(overrideName)]
to override the constructor name used during deserialization: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
as an ItemConverter
: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();
}
}