意想不到的Json.使用MemberSerialization时.NET异常.OptIn和required.always

本文关键字:OptIn 异常 required always NET Json 使用 MemberSerialization 意想不到 | 更新日期: 2023-09-27 18:13:23

我已经声明了一个模型类,其中一些属性将由JSON填充,另一些属性将由代码填充,由JsonObject和JsonProperty属性表示。下面是一个简化的版本:

[JsonObject(MemberSerialization.OptIn, ItemRequired = Required.Always)]
public class AppCard
{
    [JsonProperty]
    public string Name { get; set; }
    [JsonProperty]
    public string Author { get; set; }
    public bool IsInstalled { get; set; }
}

这是我的单元测试的JSON:

[
  {
    "name": "App 1",
    "author": "Author 1"
  },
  {
    "name": "App 2",
    "author": "Author 2"
  }
]

这里是我调用DeserializeObject的地方

appCards = JsonConvert.DeserializeObject<IEnumerable<AppCard>>(content);

不幸的是,这会失败,并出现以下错误:

Newtonsoft.Json.JsonSerializationException: Required property 'IsInstalled'
not found in JSON. Path '[0]', line 5, position 3.

由于该属性没有JsonProperty属性并且指定了OptIn,所以我假设DeserializeObject方法会忽略它。我是否误解了这些设置应该如何协同工作?

意想不到的Json.使用MemberSerialization时.NET异常.OptIn和required.always

我觉得这是个bug。在逐步执行代码时,Json。如果将MemberSerialization设置为OptIn, Net将未修饰的属性标记为忽略,但是在检查所需属性时不考虑忽略状态。如果您使用OptOut序列化(默认),则会发生相同的事情,将对象标记为具有所需的属性,然后显式地使用[JsonIgnore]标记属性:

[JsonObject(ItemRequired = Required.Always)]
public class AppCard
{
    public string Name { get; set; }
    public string Author { get; set; }
    [JsonIgnore]
    public bool IsInstalled { get; set; }
}

这可能是有意为之,但它似乎违反了"最小意外原则"。您可能需要报告一个问题。

作为一种解决方法,只需通过[JsonProperty]属性标记所需的单个属性,而不是在类上设置该选项。既然你已经用[JsonProperty]标记了所有的属性(通过使用OptIn),那么用查找和替换添加Required选项应该很容易。

[JsonObject(MemberSerialization.OptIn)]
public class AppCard
{
    [JsonProperty(Required = Required.Always)]
    public string Name { get; set; }
    [JsonProperty(Required = Required.Always)]
    public string Author { get; set; }
    public bool IsInstalled { get; set; }
}

您指定ItemRequired = Required.Always

根据文档:

获取或设置一个值,该值指示是否需要对象的属性。

你的IsInstalled成员实际上是一个属性。

JsonObject中的一些选项是互斥的,尽管没有明确说明。