我有两个班级:
Expression 有一个字符串 Name 和一个名为 Literal 的 LiteralModel。
public class ExpressionModel
{
private string name;
public string Name { get => name ?? ""; set => name = value; }
private LiteralModel literal;
public LiteralModel Literal
{
get => literal ?? new LiteralModel();
set => literal = value;
}
}
public class LiteralModel
{
private string value;
public string Value { get => value ?? ""; set => this.value = value; }
}
Run Code Online (Sandbox Code Playgroud)所有都是具有公共 getter 和 setter 的公共属性,因此我希望它们都可以轻松序列化和反序列化,即使使用空值守卫也是如此,而且在大多数情况下,它们确实如此。
ExpressionModel 的 Literal 属性没有正确反序列化。以下是演示该问题的最小测试:
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
}
Run Code Online (Sandbox Code Playgroud)
如您所见,JSON 看起来像我想要/期望的那样(包装字符串“61”),但是当我将其反序列化回 ExpressionModel 时,Literal 测试失败——它得到一个空字符串的 LiteralModel。
如果我删除表达式模型的 Literal getter 的智能,它会按预期运行——所有测试都通过。但是智能属性确实适用于字符串属性。那么为什么不在我的 LiteralModel 对象上呢?
更奇怪的是,如果我将空检查移动到 setter 而不是 getter,则所有测试都会通过,如下所示:
public LiteralModel Literal
{
get => literal;
set => literal = value ?? new LiteralModel();
}
Run Code Online (Sandbox Code Playgroud)
简而言之,序列化程序和智能 setter 没有任何阶段,但智能 getter 会破坏反序列化,除了string.
这似乎是非常随意的行为。有谁知道为什么会这样,或者是否有任何方法可以让这些类按编写的方式工作?
我怀疑问题在于 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";
Run Code Online (Sandbox Code Playgroud)
根据您的代码的工作方式,您的Literalgetter 正在创建一个新的LiteralModel,但随后将其丢弃。撇开 Json.NET 不谈,这仍然很令人困惑。例如:
var expression = new Expression();
expression.Literal.Value = "foo";
Console.WriteLine(expression.Literal.Value); // Empty string
Run Code Online (Sandbox Code Playgroud)
如果创建了一个属性,您可以更改ExpressionModel代码以将新创建的属性分配给该属性:LiteralModel
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";
Run Code Online (Sandbox Code Playgroud)
这将避免“简单代码”行为如此令人困惑 - 我希望它也能修复 Json.NET 行为。
| 归档时间: |
|
| 查看次数: |
264 次 |
| 最近记录: |