【发布时间】:2020-09-01 02:53:10
【问题描述】:
上下文
我有一个类要使用 Newtonsoft.Json 进行序列化和反序列化。
我的想法是在构造函数中给某些字段设置默认值,所以在反序列化过程中,如果缺少某个值,则假定为默认值。 然而,令我惊讶的是,反序列化器不会将默认值替换为 JSON 字符串中的值。
代码
public class MyClass {
public int Key { get; set; }
private void LoadDefaults() {
Key = 1;
}
public MyClass() {
LoadDefaults();
}
}
从上面的类中序列化一个实例后,我得到了这个 JSON:
{ "Key": 2 }
然后我用这个反序列化它:
public void Deserialize(Stream input, out MyClass output) {
using (var sr = new StreamReader(input)) {
using (var jr = new JsonTextReader(sr)) {
var serializer = new JsonSerializer();
output = serializer.Deserialize<MyClass>(jr);
}
}
}
我希望反序列化器首先调用“MyClass”的构造函数,然后调用 LoadDefaults(); 一切似乎都按预期发生。但是,在构造函数完成后,我期待反序列化器 将 Key=1 的默认值(在构造函数中设置)替换为从 JSON 字符串反序列化的值 2。 问题是反序列化对象“输出”的属性 Key 的值是 1 而不是 2。
为什么会这样? 反序列化器在构造对象后会跳过非空属性吗?
在线示例(.NET Fiddle)
【问题讨论】:
-
为什么不用
MyClass output = JsonConvert.DeserializeObject<MyClass>(json);? -
看起来
serializer.Deserialize没有设置显式属性。如果从构造函数中删除Key = 1;,它将显示0。不知道为什么.. -
JsonTextReader在那里实际上不起作用,该类未反序列化,因此您使用构造函数中设置的值创建一个新的类对象。使用var textStream = new MemoryStream(Encoding.UTF8.GetBytes(jsonMC));(UTF-8 是默认值,而不是 UTF16-LE)。或者明确指定编码:using (var sr = new StreamReader(textStream, Encoding.Unicode)) -
请注意,在反序列化中,您可以指定,例如,
[DefaultValue(1)][JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] public int Key { get; set; }。如果 JSON 字符串中缺少 Key 属性,则将设置默认值 (1)。 -> 在上一条评论中,jsonMC是复制/粘贴错误,您的原始字符串命名为json:)