如何使用默认值填充可选集合属性?

Posted

技术标签:

【中文标题】如何使用默认值填充可选集合属性?【英文标题】: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 这样的东西也让我卡住了,因为我不相信字典可以从字符串创建。 【参考方案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,这样我就不必装饰所有这些属性,而只需装饰集合类型。 是的,如果您有许多属性,并且您希望它们中的大多数以一种方式工作但只有少数以另一种方式工作,那么这是一个更好的解决方案。

以上是关于如何使用默认值填充可选集合属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取默认的系统填充值?

如何使用 PyMongo 查找所有集合的名称?

怎么求一幅图像的最小生成树

Atcoder ABC158 F - Removing Robots 线段树+选集合类dp

Magento - 如何以编程方式取消选中超级产品属性上的“使用默认值”?

如何在 Angular 中使用 Datalist Dropdown 预选值?