【问题标题】:How can I populate an optional collection property with a default value?如何使用默认值填充可选集合属性?
【发布时间】:2018-05-08 19:43:59
【问题描述】:

我正在尝试反序列化代表此类的 json 文件的一部分。

public class Command
{
    [JsonRequired]
    public string Name { get; set; }

    [DefaultValue("Json!")]
    public string Text { get; set; }

    //[DefaultValue(typeof(Dictionary<string, string>))]
    public Dictionary<string, string> Parameters { get; set; } = new Dictionary<string, string>();
}

其中两个属性是可选的:TextParameters。我希望它们填充默认值。

问题是我无法弄清楚如何让它对他们俩都有效。

  • 如果我使用DefaultValueHandling.Populate 选项,则Text 将被填充,但Parameters 仍然是null
  • 如果我使用DefaultValueHandling.Ignore,那么情况会相反。
  • 如果我在 Parameters 属性上设置 [DefaultValue(typeof(Dictionary&lt;string, string&gt;))],它会崩溃。

问题:有没有办法让它适用于所有属性?

我想让它不为空,这样我就不必在代码的其他部分检查它。


我尝试过的演示:

void Main()
{
    var json = @"
[
    {
        ""Name"": ""Hallo"",
        ""Text"": ""Json!""
    },
        {
        ""Name"": ""Hallo"",
    }
]
";

    var result = JsonConvert.DeserializeObject<Command[]>(json, new JsonSerializerSettings
    {
        DefaultValueHandling = DefaultValueHandling.Populate,
        ObjectCreationHandling = ObjectCreationHandling.Reuse
    });

    result.Dump(); // LINQPad
}

【问题讨论】:

  • 当它在字典上崩溃时你得到了什么异常?我想知道是不是因为你需要实例化一些东西而不仅仅是声明一个类型?
  • @BenHall 它说:Could not cast or convert from System.RuntimeType to System.Collections.Generic.Dictionary'2[System.String,System.String]. 但我刚刚注意到我使用了错误的重载,有一个像 Type, String 这样的东西也让我卡住了,因为我不相信字典可以从字符串创建。

标签: c# json json.net json-deserialization


【解决方案1】:

不要通过设置指定全局DefaultValueHandling,而是使用[JsonProperty] 属性为每个单独的属性设置DefaultValueHandling

public class Command
{
    [JsonRequired]
    public string Name { get; set; }

    [DefaultValue("Json!")]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
    public string Text { get; set; }

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    public Dictionary<string, string> Parameters { get; set; } = new Dictionary<string, string>();
}

然后,像这样反序列化:

var result = JsonConvert.DeserializeObject<Command[]>(json);

【讨论】:

  • 我尝试了其他组合,它们也有效。例如,我可以在全局范围内设置Populate 并在特定属性上设置Ignore,这样我就不必装饰所有这些属性,而只需装饰集合类型。
  • 是的,如果您有许多属性,并且您希望它们中的大多数以一种方式工作但只有少数以另一种方式工作,那么这是一个更好的解决方案。
猜你喜欢
  • 2010-12-05
  • 1970-01-01
  • 2016-11-01
  • 1970-01-01
  • 2019-01-19
  • 1970-01-01
  • 1970-01-01
  • 2019-09-26
  • 2020-05-26
相关资源
最近更新 更多