1

Is it possible to have only values found in a Json string be assigned by the Newtonsoft Json.NET deserializer even if they are default and null values being assigned?

Using the example below, I'm attempting to find values that are added to the _values dictionary when the properties are set. In Json 1, all values are set and saved to the database. In Json 2, the identifier is set and Value is updated to null. After deserialization, I will find the values in the database and want to update only fields with a value in the dictionary. This issue is, assigning null doesn't actually set the value because it is the default value.

As of now, I seem to be able to ignore defaults but then Value: null is ignored. Or I can Include defaults and Name is assigned null even though it isn't in the Json.

I know I could add...

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]

but on serialization, I'd like to ignore defaults.

Deserializer Code

var jsonSerializer = new JsonSerializer();
var widget = jsonSerializer.Deserialize<Widget>(jsonString);

Serializer Code

var serializer = new JsonSerializer
{
     DefaultValueHandling = DefaultValueHandling.Ignore
};
var jsonString = serializer.Serialize(widget);

Example class

public class Widget
{
    [JsonProperty]
    public int Id { get { return Get<int>("Id"); } set { Set("Id", value); } }

    [JsonProperty]
    public string Name { get { return Get<string>("Name"); } set { Set("Name", value); } }

    [JsonProperty]
    public string Value { get { return Get<string>("Value"); } set { Set("Value", value); } }

    private Dictionary<sting, object> _values = new Dictionary<sting, object>();
    private object Get<T>(string name)
    {
        if (_values.TryGetValue(name, out value))
            return (T)value;
        else
            return default(T);
    }
    private void Set(string name, object value)
    {
        _values[name] = value;
    }
}

Example Json 1

{
    "Id": 6,
    "Name": "Widget 1",
    "Value": "Blue"
}

Example Json 2

{
    "Id": 6
    "Value": null
}
Ben Gripka
  • 16,012
  • 6
  • 45
  • 41
  • 1
    How are you deserializing the JSON in the first place and to what? I really don't follow what you are trying to do. – Matt Burland Sep 30 '16 at 18:33
  • You might want to take a look at [Modify existing object with new partial JSON data using Json.NET](http://stackoverflow.com/q/27511675/10263). This sounds like the same problem you are trying to solve. It uses `serializer.PopulateObject` to do a partial update. So the strategy would be: load the existing object, patch it using PopulateObject, then save the object back to your data store. – Brian Rogers Sep 30 '16 at 19:30

1 Answers1

1

You may make use of ShouldSerialize methods, e.g.

bool ShouldSerializeName() {
    return _values.ContainsKey("Name");
}

bool ShouldSerializeValue() {
    return _values.ContainsKey("Value");
}

Not pretty but it should work. Another option is a custom serializer.

Volkan Ceylan
  • 1,486
  • 13
  • 15
  • I see where you are going with this. Would need to add [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)] for deserialization and these methods for serialization. Thing is, I have 500+ properties in my project. May need to do this with IContractResolver. – Ben Gripka Sep 30 '16 at 19:06