如何解决使用ReferenceLoopHandling.Ignore序列化依赖于循环的ISerializable对象时,抛出StackOverflowException
我想你会需要同时ReferenceLoopHandling.Serialize
和PreserveReferencesHandling.All
复制二进制序列化的行为。但是,生成的JSON可能不那么漂亮。
我对JSON.Net4.5r10进行了更深入的研究,发现了一个缺陷:JsonSerializerInternalWriter
不检查#ShouldWriteReference
通过获得的引用ISerializable
。
随着foreach
循环中#SerializeISerializable
,如下改写,你的对象图顺利往返。
foreach (SerializationEntry serializationEntry in serializationInfo)
{
writer.WritePropertyName(serializationEntry.Name);
var entryValue = serializationEntry.Value;
var valueContract = GetContractSafe(entryValue);
if (ShouldWriteReference(entryValue, null, valueContract, null, member))
{
WriteReference(writer, entryValue);
}
else
{
SerializeValue(writer, entryValue, valueContract, null, null, member);
}
}
解决方法
我有一个使用二进制序列化来保留数据的旧版应用程序。现在,我们想使用Json.net 4.5在不对现有类进行太多更改的情况下序列化数据。
事情一直很好,直到我们遇到了循环依赖类。有解决此问题的解决方法吗?
示例代码如下所示
[Serializable]
class Department : ISerializable
{
public Employee Manager { get; set; }
public string Name { get; set; }
public Department() { }
public Department( SerializationInfo info,StreamingContext context )
{
Manager = ( Employee )info.GetValue( "Manager",typeof( Employee ) );
Name = ( string )info.GetValue( "Name",typeof( string ) );
}
public void GetObjectData( SerializationInfo info,StreamingContext context )
{
info.AddValue( "Manager",Manager );
info.AddValue( "Name",Name );
}
}
[Serializable]
class Employee : ISerializable
{
[NonSerialized] //This does not work
[XmlIgnore]//This does not work
private Department mDepartment;
public Department Department
{
get { return mDepartment; }
set { mDepartment = value; }
}
public string Name { get; set; }
public Employee() { }
public Employee( SerializationInfo info,StreamingContext context )
{
Department = ( Department )info.GetValue( "Department",typeof( Department ) );
Name = ( string )info.GetValue( "Name",typeof( string ) );
}
public void GetObjectData( SerializationInfo info,StreamingContext context )
{
info.AddValue( "Department",Department );
info.AddValue( "Name",Name );
}
}
和测试代码
Department department = new Department();
department.Name = "Dept1";
Employee emp1 = new Employee { Name = "Emp1",Department = department };
department.Manager = emp1;
Employee emp2 = new Employee() { Name = "Emp2",Department = department };
IList<Employee> employees = new List<Employee>();
employees.Add( emp1 );
employees.Add( emp2 );
var memoryStream = new MemoryStream();
var formatter = new BinaryFormatter();
formatter.Serialize( memoryStream,employees );
memoryStream.Seek( 0,SeekOrigin.Begin );
IList<Employee> deserialisedEmployees = formatter.Deserialize( memoryStream ) as IList<Employee>; //Works nicely
JsonSerializerSettings jsonSS= new JsonSerializerSettings();
jsonSS.TypeNameHandling = TypeNameHandling.Objects;
jsonSS.TypeNameAssemblyFormat = FormatterAssemblyStyle.Full;
jsonSS.Formatting = Formatting.Indented;
jsonSS.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //This is not working!!
//jsonSS.ReferenceLoopHandling = ReferenceLoopHandling.Serialize; //This is also not working!!
jsonSS.PreserveReferencesHandling = PreserveReferencesHandling.All;
string jsonAll = JsonConvert.SerializeObject( employees,jsonSS ); //Throws stackoverflow exception
Edit1
:该问题已报告给Json(http://json.codeplex.com/workitem/23668)
Edit2 :序列化在版本4.5 R11中可以正常工作,但是反序列化仍然不起作用
Edit3 :当循环引用对象不为null时,实际上序列化本身不起作用
Edit4 :来自Json.net问题库的评论是问题在您的末端,并已解决问题。但是我找不到我的代码出了什么问题。我对此发布了另一个
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。