Just_Stacking
Just_Stacking

Reputation: 405

JSON.net, C#, unable to set default values in data model

I am using JsonConvert.DeserializeObject(json.ToString()); to deserialise a JSON and populate my fields in a related model. This works well until there is data missing in the JSON. Basically instead of having "key : value" I will just have "key : null".

My understanding about the JsonConverter was that it would create an object, in which I should be able to populate fields with a default value either through the constructor (not being called in my case for unknown reasons), or through the tags as mentioned here: Default value for missing properties with JSON.net or here: Why when I deserialize with JSON.NET ignores my default value?

I have tried both and neither results in the related fields being initialised. Of course if there is no data in the JSON, nothing can be deserialised to the related model. However I would expect that I still could initialise some values with defaults, which would then just be ignored (not overwritten) by JsonConverter (just like what happens now). This however, does not seem to be possible?

Source code of previous attempts

Model class

namespace Project.MyJob
{
    public class JsonModel
    {
        public JsonModel()
        {
            Type_X type_x = new Type_X();
            // This is not doing anything. I would have expected that the 
            // class' constructor would be called but, no.
        }
        public string objectNumber { get; set; }
        public string objectFamily { get; set; }
        public string objectOrder { get; set; }
        public string location { get; set; }
        public string place { get; set; }
        public string inventionTime { get; set; }
        public string lastUpdate { get; set; }
        public string condition { get; set; }

        public Type_X Type_X { get; set; }
        public List<Actions> actions { get; set; }         
    }

    public class Actions
    {
        public string count { get; set; }
        public string datetime { get; set; }
        public string place { get; set; }
        public string status { get; set; }
    }

    public class Type_X
    {  

        public Type_X
        {
          // This should be executed when a new Type_X object is created? Also 
          // not.
          partA = "null";
        }

        [DefaultValue("null")]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
        public string partA { get; set; }

        // Trying public string partA { get; set; } = "null"; also does 
        // nothing.

        [DefaultValue("null")]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
        public string PartB { get; set; }

        [DefaultValue("null")]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
        public string partC { get; set; }

        [DefaultValue("null")]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
        public string partD { get; set; }

        [DefaultValue("null")]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
        public string partE { get; set; }
    }
}

Creation of JSON object with default values (defaults not working)

JObject = JsonConvert.DeserializeObject<JsonModel>(json.ToString(), new 
JsonSerializerSettings {DefaultValueHandling = 
DefaultValueHandling.Populate});

Example of downstream usage of the created objects

JObject.actions[i].count + "more text"

Above works when not relying on defaults.

Upvotes: 3

Views: 7591

Answers (1)

Brian Rogers
Brian Rogers

Reputation: 129777

You are using the wrong setting.

If you want null values in the JSON to be ignored during deserialization, you need to set NullValueHandling = NullValueHandling.Ignore in the settings. The default is Include, which means that if the JSON has an explicit null in it for a particular property, that property will be set to null on your object, overwriting any default you may have set.

DefaultValueHandling.Populate means if the key is missing altogether in the JSON (which is different from being set to null), then it will use the value provided by the [DefaultValue] attribute. Note that if the JSON has an explicit null in it, this setting will not use the default value from the attribute, even if NullValueHandling is set to Ignore. So if you want a default value in that situation, the best way to do that is by setting it in the constructor.

So, in short, to get the behavior you want:

  • Use the NullValueHandling.Ignore setting.
  • Provide your default values via the constructor.
  • You don't need the DefaultValueHandling setting or the [DefaultValue] attribute.

Demo fiddle: https://dotnetfiddle.net/kyUjFz

Upvotes: 11

Related Questions