Json.Net在列表反序列化期间调用属性getter,导致重复项

时间:2014-08-28 16:15:56

标签: c# winforms json.net json-deserialization

我正在使用json.net为winform应用程序实现memento pattern。我正在使用memento在失败的数据库事务上回滚对象。我得到的问题是,当反序列化纪念品时,调用getter而不是setter。让我演示一下:

class MyClass
{
    public int ID { get; set; }
    public string field1 { get; set; }
    public string field2 { get; set; }

    private List<SomeObject> _someObjects;
    public List<SomeObject> SomeObjects
    {
        get
        {
            if(_someObjects == null)
            {
                _someObjects = LoadSomeObjectsFromDB();
            }
            return _someObjects;
        }
        set
        {
            _someObjects = value;
        }
    }

    private List<AnotherObject> _anotherObjects;
    public List<AnotherObject> AnotherObjects
    {
        get
        {
            if(_anotherObjects == null)
            {
                _anotherObjects= LoadAnotherObjectsFromDB();
            }
            return _anotherObjects ;
        }
        set
        {
            _anotherObjects = value;
        }
    }
}

* MyObjectSomeObjectAnotherObject扩展相同的基类Model

从上面的示例类中可以看出,如果尚未加载SomeObjects,它会使用Lazy Loading从数据库加载它。现在当我序列化这个对象时。

string memento = JsonConvert.SerializeObject(obj);

导致

{
  "ID": 1,
  "field1": "field 1",
  "field2": "field 2",
  "SomeObjects": [
    {
      "ID": 1,
    },
    {
      "ID": 2,
    },
    {
      "ID": 3,
    }
  ],
  "AnotherObjects": [
    {
      "ID": 4,
    },
    {
      "ID": 5,
    },
    {
      "ID": 6,
    }
  ]
}

然后将其反序列化。

MyObject obj = JsonConvert.DeserializeObject(memento, typeof(MyObject));

我得到一个由以下JSON

表示的对象
{
  "ID": 1,
  "field1": "field 1",
  "field2": "field 2",
  "SomeObjects": [
    {
      "ID": 1,
    },
    {
      "ID": 2,
    },
    {
      "ID": 3,
    },
    {
      "ID": 1,
    },
    {
      "ID": 2,
    },
    {
      "ID": 3,
    }
  ],
  "AnotherObjects": [
    {
      "ID": 4,
    },
    {
      "ID": 5,
    },
    {
      "ID": 6,
    },
    {
      "ID": 4,
    },
    {
      "ID": 5,
    },
    {
      "ID": 6,
    }
  ]
}

SomeObjectsAnotherObjects List

中的项目过多 调用

SomeObjects getter,这会导致List从DB初始化,然后序列化列表将附加到它。让我在列表中的项目超出预期。但是,如果我删除延迟加载部分

public List<SomeObject> SomeObjects
{
    get
    {
        /*if(_someObjects == null)
        {
            _someObjects = LoadSomeObjectsFromDB();
        }*/
        return _someObjects;
    }
    set
    {
        _someObjects = value;
    }
}

仍会调用getter,但返回null。然后json.net调用setter,其中value是一个列表,其中已经添加了正确数量的元素,而如果getter返回一个初始化列表,它会追加到它永远不会调用setter。为什么差异,如果列表已经初始化,则调用getter并附加到。但是如果没有初始化,则调用setter并使用已填充对象的列表对其进行初始化。有没有办法让json.net在反序列化List期间只调用setter?

1 个答案:

答案 0 :(得分:13)

Json.Net为此目的设置了ObjectCreationHandling。尝试将其设置为Replace,例如:

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ObjectCreationHandling = ObjectCreationHandling.Replace;

MyObject obj = JsonConvert.DeserializeObject<MyObject>(memento, settings);

演示:https://dotnetfiddle.net/rkY1pt