C# 使用Newtonsoft Json序列化循环引用
我尝试序列化和反序列化的实体:C# 使用Newtonsoft Json序列化循环引用,c#,serialization,json.net,deserialization,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 { re
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;
}
}
}
大多数其他地方都提到了使用下面的解决方案,但没有一个是适合我的
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;
公共接口的可扩展性
{
int Id{get;set;}
}
公共类Base1:通用性
{
公共虚拟整数Id{get;set;}
}
公车:Base1
{//与上面的汽车类+下面的属性中定义的属性相同
私人国际加勒比;
公共国际加勒比
{
获取{return\u carId;}
设置{u carId=value;Id=value;}
}
}
var car=新车();
car.Model=“Amaze”;
车年=新日期时间(2016年1月1日);
car.Features=新列表{“Light”,“1”,“2”};
car.CarId=1;
在这里,基类的Id始终为零,派生的Id始终设置为非零值。
是否可以编写自定义转换器(通过检查属性Id的值是否为零,然后不进一步序列化该属性(Car1属性)?)
有什么建议,如何做到这一点 您遇到此问题的原因有两个:
return _car != null ? _car : new Car();
如果\u car
的值为null
,则每次都返回一个新实例,这会将序列化程序发送到无限遍历中,导致溢出
你需要重新考虑你的设计。您应该将新实例分配给内部变量,否则将丢失引用并继续使用null
:
public Car Car1
{
get
{
if(_car == null)
_car = new Car();
return _car;
}
set
{
_car = value;
}
}
但是,这种自动初始化仍然是一个问题,因为总是有一个值要序列化。如果不存在对象,则该值应为
null
,这将允许序列化程序执行其工作并到达对象图的末尾。可能是输入错误,但在上面使用的代码中,设置变量具有循环处理标志。我相信这就是你想要的。换句话说,尝试更改为:var serialize=JsonConvert.SerializeObject(car,settings);所以你的车有一辆车,那辆车有一辆车,那辆车有一辆车,那。。。你确定你的班级做了你想让它做的事吗?是的。我知道问题在哪里。但是很难重新思考这个设计并使其正确。这就是为什么我问是否有任何方法可以让它工作。@Gopu_Tunas:想一想。这就是序列化程序所做的,因为属性总是有一个值。如果序列化程序在某个点停止,您将丢失信息。否则它将永远消失:(伪代码)Serialize(car)=>SerializeInternalProperty(car);=>属性(汽车);=>属性(汽车);=>属性(汽车);=>不动产(汽车);。。。永恒
。你到底要如何“修复”这个问题?@Gopu_Tunas我不知道你为什么会想要你正在创建的报废汽车场景,但是如果你愿意为序列化程序设置MaxDepth设置,你可以让序列化程序工作。@peter.edwards:正如我提到的,他会丢失信息,并在一开始就挫败了连载的目的,但你是对的。@Gopu_Tunas:你误解了连载。请再读一遍我的答案。您的修改版本仍然存在相同的问题,因为您正在尝试选择性地序列化内容。你需要重新考虑你的设计。序列化是对象图的一种表示形式,因此有选择地将自定义序列化程序中的内容省略是没有意义的。整个想法是,您希望能够具体化回完全相同的对象(图)。
public Car Car1
{
get
{
if(_car == null)
_car = new Car();
return _car;
}
set
{
_car = value;
}
}