使用MemberSerialization.OptIn和Required.Always时出现意外的Json.NET异常

时间:2016-10-17 23:39:29

标签: c# json.net

我已经声明了一个模型类,其中有一些属性需要由JSON填充,一些属性将由代码填充,由JsonObjectJsonProperty属性指示。这是一个简化版本:

[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方法会忽略它。我是否误解了这些设置应该如何协同工作?

2 个答案:

答案 0 :(得分:2)

这对我来说感觉像个错误。在单步执行代码时,如果MemberSerialization设置为OptIn,Json.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; }
}

这可能是设计上的,但它似乎违反了最少惊喜的原则&#34;。您可能想要report an issue

作为一种解决方法,只需根据需要通过[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; }
}

答案 1 :(得分:0)

您指定的是ItemRequired = Required.Always

根据文件:

Gets or sets a value that indicates whether the object's properties are required.

您的IsInstalled成员实际上是一个财产。

JsonObject中的某些选项虽然not explicitly stated是互斥的。