当我遇到一个有副作用的属性设置器时,出现了一个问题(这是针对关注点分离的糟糕设计(。
以下问题有点理论性,理想情况下,应该通过消除属性设置器的副作用来解决问题。
但是,如果修改DTO类不是一种选择,是否有任何机制可以防止JSON反序列化在使用 Json.NET 时引起副作用?
问题场景:
下面显示了Myclass
和两个 JSON 代码段。
当我调用JsonConvert.Deserialize<MyClass>(json)
时,根据JSON属性的顺序,我得到不同的结果。
数据传输类:
public class MyClass
{
private string _evilField1;
public string EvilField1
{
get
{
return _evilField1;
}
set
{
_evilField1 = value;
Info = "EvilField1.Set messed Info";
}
}
private string _evilField2;
public string EvilField2
{
get
{
return _evilField2;
}
set
{
_evilField2 = value;
Info = "EvilField2.Set messed Info";
}
}
public string Info { get; set; }
}
输入数据
{
"EvilField1": "Foo",
"EvilField2": "Foo",
"Info": "Initial value"
}
{
"EvilField1": "Foo",
"Info": "Initial value",
"EvilField2": "Foo"
}
反序列化数据
第一个 JSON 不会触发副作用,但第二个 JSON 会带来令人讨厌的输出:
{
"EvilField1": "Foo",
"Info": "Initial value",
"EvilField2": "Foo"
}
{
"EvilField1": "Foo",
"EvilField2": "Foo",
"Info": "EvilField2.Set messed Info"
}
您可以为有问题的类创建自定义JsonConverter
。 这将允许您以您需要的任何方式填充它,以解决不需要的副作用。
public class MyClassConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(MyClass);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null) return null;
JObject obj = JObject.Load(reader);
// Populate the "Info" field last so it will not be overwritten
return new MyClass
{
EvilField1 = (string)obj["EvilField1"],
EvilField2 = (string)obj["EvilField2"],
Info = (string)obj["Info"]
};
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用转换器,您可以添加一个[JsonConverter]
属性有问题的类...
[JsonConverter(typeof(MyClassConverter))]
public class MyClass
{
...
}
。或者,您可以通过设置将转换器的实例传递给DerserializeObject()
方法:
var settings = new JsonSerializerSettings();
settings.Converters.Add(new MyClassConverter());
var obj = JsonConvert.DeserializeObject<MyClass>(json, settings);
小提琴:https://dotnetfiddle.net/Ob4dPA