Search code examples
c#jsonjson.netjson-deserialization

How can I populate an optional collection property with a default value?


I'm trying to deserialize a part of a json file that represents this class.

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>();
}

where two properties are optional: Text and Parameters. I'd like them to be populated with default values.

The problem is that I cannot figure out how to make it work for both of them.

  • If I use the DefaultValueHandling.Populate option then Text will be populated but Parameters remains null.
  • If I use DefaultValueHandling.Ignore then it'll be the other way around.
  • If I set [DefaultValue(typeof(Dictionary<string, string>))] on the Parameters property it'll crash.

Quesiton: Is there a way to make it work for all properties?

I'd like to have it not-null so that I don't have to check it in other part of the code.


Demo of what I have tried:

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
}

Solution

  • Instead of specifying a global DefaultValueHandling via settings, use [JsonProperty] attributes to set the DefaultValueHandling as you need it for each individual property:

    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>();
    }
    

    Then, deserialize like this:

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