使用Newtonsoft Json序列化循环引用

时间:2019-07-19 13:17:38

标签: c# serialization json.net deserialization

我要序列化和反序列化的实体:

public class Car
{
    public string Model { get; set; }
    public DateTime Year { get; set; }
    public List<string> Features { get; set; }

    private Car _car;
    public Car Car1
    {
        get
        {
            return _car != null ? _car : new Car();
        }
        set
        {
            _car = value;
        }
    }
}

我正在使用Newtonsoft Json库对上述实体进行序列化和反序列化。 在对该实体进行序列化和反序列化时,我不能忽略任何属性。

直接对实体进行序列化时会引发StackOverflow异常。

JsonConvert.SerializeObject(car)

使用下面的解决方案提到的大多数其他地方,但没有一个对我有用。

var _jsonSettings = new JsonSerializerSettings()
{
    TypeNameHandling = TypeNameHandling.Auto,
    ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
    ObjectCreationHandling = ObjectCreationHandling.Auto
};

var settings = new JsonSerializerSettings
{
    PreserveReferencesHandling = PreserveReferencesHandling.Objects
};

settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;

var serialize = JsonConvert.SerializeObject(car, _jsonSettings);

or

var serialize = JsonConvert.SerializeObject(car, settings);

我知道此属性存在问题

private Car _car;
    public Car Car1
    {
        get
        {
            return _car != null ? _car : new Car();
        }
        set
        {
            _car = value;
        }
    }

但是我暂时不能摆脱它。

修改后的问题:

public interface IEntity
    {
        int Id { get; set; }
    }
    public class Base1 : IEntity
    {
        public virtual int Id { get; set; }
    }
public class Car : Base1
    {//same properties as defined above in above Car class + below property
        private int _carId;
        public int CarId
        {
            get { return _carId; }
            set { _carId = value; Id = value; }
        }
    }

            var car = new Car();
            car.Model = "Amaze";
            car.Year = new DateTime(2016, 1, 1);
            car.Features = new List<string> { "Light", "1", "2" };
            car.CarId = 1;

此处的基类ID始终为零,派生的值始终设置为非零值。 是否可以编写自定义转换器(通过检查属性ID是否具有零值,然后不进一步序列化该属性(Car1属性)?) 有什么建议,如何实现?

1 个答案:

答案 0 :(得分:1)

您遇到此问题的原因有两个:

return _car != null ? _car : new Car();

如果_car的值为null,则每次返回一个新实例,这会将序列化程序发送到无限遍历,从而导致溢出。

您需要重新考虑您的设计。您应该将新实例分配给内部变量,否则将丢失引用并继续使用null

public Car Car1
{
    get
    {
        if(_car == null)
            _car = new Car();
        return _car;
    }
    set
    {
        _car = value;
    }
}

但是,由于总是存在要序列化的值,因此这种自动初始化将继续成为问题。如果没有对象,则值应为null,这将允许序列化程序执行其工作并到达对象图的末尾。

相关问题