Json.NET 反序列化和属性资源库副作用



当我遇到一个有副作用的属性设置器时,出现了一个问题(这是针对关注点分离的糟糕设计(。

以下问题有点理论性,理想情况下,应该通过消除属性设置器的副作用来解决问题。

但是,如果修改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

相关内容

  • 没有找到相关文章

最新更新