JsonConvert 在反序列化时不初始化属性,除非 setter 是通用的
JsonConvert not initialising properties when deserializing unless setter is generic
当 getter/setter 不是 generic/default 值时,为什么 JsonConvert 无法初始化 属性 值。
例如,JsonConvert 将按原样反序列化以下 class(或者 属性 "Value")。假设我的 Json 文件包含 Value = 5,那么我的反序列化 SomeObjectX 对象将其 属性 "Value" 设置为 5:
public class SomeClass
{
public int Value { get; set; }
}
然而,如果我想让 setter 更复杂一点,做一些特别的事情,那它就不行了。这是新的 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;
}
}
}
有关信息,这是我调用 JsonConvert 以反序列化为对象的方式:
SomeClass SomeObjectX = JsonConvert.DeserializeObject<SomeClass>(File.ReadAllText(@"e:\someObject.json"), settings);
有没有办法让它发挥作用?
换句话说,如果我的 Json 包含 10 的初始化 属性 "Value",那么我应该在反序列化时将 "Value" 设置为 10。
编辑
序列化的 Json 文件如下所示:
{
"MaxValue": 10,
"MinValue": 0,
"Value": 5
}
这是我在运行时得到的未初始化对象(请注意 "Value" 是 0,而不是它应该的 5):
这是一个关于我如何创建我的对象实例、初始化它、将它保存到 Json 然后将它反序列化回一个对象的测试:
// 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);
您遇到的问题似乎与属性的反序列化排序有关。您的原始模型包含 Value
和 MaxValue
属性之间的时间耦合,并且根据您设置值的顺序,您最终会在对象上得到不同的结果。
您应该能够使用属性上的 [Order]
属性来控制反序列化顺序,但我建议改为让您的模型不可变,并通过构造函数传递所有 3 个值。这样,您还可以完全避免时间耦合,从而实现更好的设计。
正在使用 julealgon 的输入回答我的问题。
按照以下示例设置 "JsonProperty Order" 属性("Value" 需要使用最高订单号):
using Newtonsoft.Json;
public class SomeClass
{
[JsonProperty(Order = 1)]
public int MinValue { get; set; }
[JsonProperty(Order = 2)]
public int MaxValue { get; set; }
private int _value;
[JsonProperty(Order = 3)]
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;
}
}
}
这样 JsonConvert 将在反序列化 Value 之前先反序列化 MinValue 和 MaxValue。
或者使用不可变属性:
public class SomeClass
{
// Constructor
public SomeClass(int, value, int minValue, int maxValue)
{
MinValue = minValue;
MaxValue = maxValue;
// Set value after Min/MaxValue
Value = value;
}
public int MinValue { get; }
public int MaxValue { get; }
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;
}
}
}
当 getter/setter 不是 generic/default 值时,为什么 JsonConvert 无法初始化 属性 值。
例如,JsonConvert 将按原样反序列化以下 class(或者 属性 "Value")。假设我的 Json 文件包含 Value = 5,那么我的反序列化 SomeObjectX 对象将其 属性 "Value" 设置为 5:
public class SomeClass
{
public int Value { get; set; }
}
然而,如果我想让 setter 更复杂一点,做一些特别的事情,那它就不行了。这是新的 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;
}
}
}
有关信息,这是我调用 JsonConvert 以反序列化为对象的方式:
SomeClass SomeObjectX = JsonConvert.DeserializeObject<SomeClass>(File.ReadAllText(@"e:\someObject.json"), settings);
有没有办法让它发挥作用? 换句话说,如果我的 Json 包含 10 的初始化 属性 "Value",那么我应该在反序列化时将 "Value" 设置为 10。
编辑
序列化的 Json 文件如下所示:
{
"MaxValue": 10,
"MinValue": 0,
"Value": 5
}
这是我在运行时得到的未初始化对象(请注意 "Value" 是 0,而不是它应该的 5):
这是一个关于我如何创建我的对象实例、初始化它、将它保存到 Json 然后将它反序列化回一个对象的测试:
// 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);
您遇到的问题似乎与属性的反序列化排序有关。您的原始模型包含 Value
和 MaxValue
属性之间的时间耦合,并且根据您设置值的顺序,您最终会在对象上得到不同的结果。
您应该能够使用属性上的 [Order]
属性来控制反序列化顺序,但我建议改为让您的模型不可变,并通过构造函数传递所有 3 个值。这样,您还可以完全避免时间耦合,从而实现更好的设计。
正在使用 julealgon 的输入回答我的问题。
按照以下示例设置 "JsonProperty Order" 属性("Value" 需要使用最高订单号):
using Newtonsoft.Json;
public class SomeClass
{
[JsonProperty(Order = 1)]
public int MinValue { get; set; }
[JsonProperty(Order = 2)]
public int MaxValue { get; set; }
private int _value;
[JsonProperty(Order = 3)]
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;
}
}
}
这样 JsonConvert 将在反序列化 Value 之前先反序列化 MinValue 和 MaxValue。
或者使用不可变属性:
public class SomeClass
{
// Constructor
public SomeClass(int, value, int minValue, int maxValue)
{
MinValue = minValue;
MaxValue = maxValue;
// Set value after Min/MaxValue
Value = value;
}
public int MinValue { get; }
public int MaxValue { get; }
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;
}
}
}