上下文
我有两门课:
公共类ExpressionModel {私有字符串名称;公共字符串名称{获取=>名称?"";设置=>名称=值;}私有LiteralModel文字;公共LiteralModel文字{获取=>文字?新LiteralModel();设置=>文字=值;}公共类LiteralModel {私有字符串值;公共字符串值{获取=>值?“;设置=> this.value =值;}
所有这些都是带有公共getter和setter的公共属性,因此我希望它们都能轻松地序列化和反序列化,即使使用空保护,而且大多数情况下都是这样。
问题
ExpressionModel的文字属性不能正确反序列化。下面是一个演示这个问题的最小测试:
public void TestNewtonsoftExpressionDeserialization()
{
ExpressionModel expression = new ExpressionModel
{
Name = "test",
Literal = new LiteralModel { Value = "61" }
};
string json = JsonConvert.SerializeObject(expression);
Assert.IsTrue(json.Contains("61")); // passes
ExpressionModel sut = JsonConvert.DeserializeObject<ExpressionModel>(json);
Assert.AreEqual("test", sut.Name); // passes
Assert.AreEqual("61", sut.Literal.Value); // fails
}
正如您所看到的,JSON看起来很像我想要的/expect(包装字符串"61"),但是当我将它反序列化回一个ExpressionModel时,文字测试失败了--它得到一个空字符串的LiteralModel。
我试过的
如果我删除表达式模型的文字getter的智能性,它的行为就像预期的那样--所有测试都通过了。但是,智能属性确实可以处理字符串属性。那么为什么不在我的LiteralModel对象上呢?
更奇怪的是,如果我将空检查移到setter而不是getter,那么所有的测试都会通过:
public LiteralModel Literal
{
get => literal;
set => literal = value ?? new LiteralModel();
}
结论
简而言之,没有任何东西会分阶段序列化,智能设置器也很好,但是除了string
之外,智能getter会中断反序列化。
这似乎是极端武断的行为。有人知道为什么会这样吗,或者是否有任何方法可以让这些类按照编写的方式工作呢?
发布于 2020-01-30 16:50:50
我怀疑问题在于Json.NET正在调用属性getter,然后调用结果的setter。例如,类似这样的东西--尽管很明显,通过反射:
var expression = new ExpressionModel();
expression.Name = "test";
var literal = expression.Literal;
if (literal is null)
{
// No literal - create one and set it
literal = new LiteralModel();
expression.Literal = literal;
}
// Now literal is non-null either way, so set the value.
literal.Value = "61";
按照代码的工作方式,您的Literal
getter正在创建一个新的LiteralModel
,但随后将其丢弃。撇开Json.NET不说,这仍然是相当令人困惑的。例如:
var expression = new Expression();
expression.Literal.Value = "foo";
Console.WriteLine(expression.Literal.Value); // Empty string
您可以更改ExpressionModel
代码,以便将新创建的LiteralModel
分配给属性,如果它创建了一个:
public LiteralModel Literal
{
get => literal ?? (literal = new LiteralModel());
set => literal = value;
}
这将避免“简单代码”行为如此令人困惑--而且我希望它也能修复Json.NET行为。
https://stackoverflow.com/questions/59990623
复制相似问题