Why is JsonConvert not able to initialise property values when getter/setter are not the generic/default ones.
For instance, JsonConvert will deserialise the following class (or rather Property "Value") as it should. Say my Json file contains Value = 5, then my deserialised SomeObjectX object, will have its property "Value" set to 5:
public class SomeClass
{
public int Value { get; set; }
}
However if I want the setter to be a bit more complicated and do something special, then it won't work. Here is the new class:
public class SomeClass
{
public int MinValue { get; set; }
public int MaxValue { get; set; }
private int _value;
public int Value
{
get { return _value; }
set
{
// Restrict range to Min/Max
if (MaxValue < value)
_value = MaxValue;
else if (MinValue > value)
_value = MinValue;
else
_value = value;
}
}
}
For info, here is how I am calling JsonConvert for the deserialisation into objects:
SomeClass SomeObjectX = JsonConvert.DeserializeObject<SomeClass>(File.ReadAllText(@"e:\someObject.json"), settings);
Is there a way to get that to work? In other word, if my Json contains an initialisation property "Value" of 10, then I should get "Value" set to 10 when deserialising.
Serialised Json file looks like this:
{
"MaxValue": 10,
"MinValue": 0,
"Value": 5
}
Here is the non initialised object I am getting at runtime (see that "Value" is 0 not 5 as it should):
Here is a test on how I created my object instance, initialised it, saved it to Json and then deserialised it back into an object:
// Create and init object
var param = new SomeClass();
param.MaxValue = 10;
param.Value = 5;
// Settings - Not making any difference with or without
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
ObjectCreationHandling = ObjectCreationHandling.Replace
};
// Serialise into Json
File.WriteAllText(@"e:\param.json", JsonConvert.SerializeObject(param, settings));
// Deserialise back into object
SomeClass obj = JsonConvert.DeserializeObject<SomeClass>(File.ReadAllText(@"e:\param.json"), settings);
The problem you are facing appears to be related to deserialization ordering of the properties. Your original model contains a temporal coupling between the Value
and MaxValue
properties, and depending on the order that you set the values, you'll end up with different results on your object.
You should be able to control the deserialization ordering using a [Order]
attribute on the properties, but I'd recommend instead making your model immutable, and passing all 3 values through the constructor. That way, you also avoid the temporal coupling altogether, which leads to better design.