我正在使用Newtonsoft.Json(又称Json.Net)对我的课程进行序列化:
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;
}
但是当我序列化和反序列化对象时,我没有收到期望的值:
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
}
}
出什么问题了,或者如何改变这种行为?
我注意到,如果我自己对ImmutableValue
进行序列化和反序列化,则可以正常工作:
var json = JsonConvert.SerializeObject(new ImmutableValue(42));
var obj = JsonConvert.DeserializeObject<ImmutableValue>(json);
Console.WriteLine(obj.Value); // 42
答案 0 :(得分:3)
罪魁祸首是您的ClassWithCustomProperty
类中的这一行:
get => value = (value ?? new ImmutableValue(0));
Json.Net的默认行为是重用现有对象,而不是替换它们。因此,当需要对ImmutableValue
上的ClassWithCustomProperty
进行反序列化时,串行器首先检查是否存在现有值。 (上面的)访问器发现没有访问器,因此它创建了一个值为0
的访问器,并将其返回给序列化器。然后,串行器尝试重用此现有对象,但是由于它是只读的,因此无法在其上设置值42
。因此该值保持为零。
有一个ObjectCreationHandling
设置可用于更改此行为。如果将其设置为Replace
,它将按照您想要的方式工作。尝试这样:
var settings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Replace
};
var obj = JsonConvert.DeserializeObject<ClassWithCustomProperty>(json, settings);