Reputation: 190
I'm using Newtonsoft.Json (a.k.a. Json.Net) for serialization of my class:
public class ClassWithCustomProperty
{
private ImmutableValue value;
public ImmutableValue Value
{
get => value = (value ?? new ImmutableValue(0));
set => this.value = value;
}
}
public class ImmutableValue
{
public readonly int Value;
public ImmutableValue(int value) => Value = value;
}
But when I serialize and deserialize the object I don't receive the expected value:
public static class Program
{
public static void Main()
{
var json = JsonConvert.SerializeObject(new ClassWithCustomProperty
{
Value = new ImmutableValue(42)
});
// JSON is {"Value": {"Value": 42}} as expected
var obj = JsonConvert.DeserializeObject<ClassWithCustomProperty>(json);
Console.WriteLine(obj.Value?.Value);
// But after deserialization obj.Value.Value is 0, instead of 42
}
}
What is wrong, or how to change this behavior?
I noticed that if I serialize and deserialize an ImmutableValue
by itself, it works fine:
var json = JsonConvert.SerializeObject(new ImmutableValue(42));
var obj = JsonConvert.DeserializeObject<ImmutableValue>(json);
Console.WriteLine(obj.Value); // 42
Upvotes: 1
Views: 1002
Reputation: 129697
The culprit is this line in your ClassWithCustomProperty
class:
get => value = (value ?? new ImmutableValue(0));
Json.Net's default behavior is to reuse existing objects rather than replace them. So when it is time to deserialize the ImmutableValue
on ClassWithCustomProperty
, the serializer first checks whether there is an existing value. The accessor (above) finds that there isn't, so it creates one with value 0
, which is returned to the serializer. The serializer then attempts to reuse this existing object, but since it is readonly, there is no way to set the value 42
on it. So the value remains zero.
There is an ObjectCreationHandling
setting which can be used to change this behavior. If you set it to Replace
, it will work the way you want. Try like this:
var settings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Replace
};
var obj = JsonConvert.DeserializeObject<ClassWithCustomProperty>(json, settings);
Fiddle: https://dotnetfiddle.net/UVDMsL
Upvotes: 3