Json.net:序列化/ Deserialisation不工作的,有循环引用ISerializable的对象 [英] Json.net: Serialisation/Deserialisation not working for ISerializable object that has circular reference

查看:246
本文介绍了Json.net:序列化/ Deserialisation不工作的,有循环引用ISerializable的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一段时间后,我已经报道了<一href="http://stackoverflow.com/questions/13412359/json-net-issues-stackoverflowexception-is-thrown-when-serialising-circular-depe">issue为此我有在Json.net 4.5 R11修复。

如果我的循环引用属性管理​​为NULL,则系列化和deserialisation工作正常。

但是,当循环引用属性管理​​设置为非NULL值,那么它被忽略了序列化的字符串,因此它抛出deserialisation异常。

Json.net问题的基础说,问题是在code,但我无法弄清楚。有人可以帮助我在这里?

问题:

  1. 有没有与下面的code什么问题?
  2. 如果是我应该怎么做才能解决这个问题?
  3. 如果没有,那么应该怎样在Json.net code做来解决这个问题?

一些更多的更新: 这是需要在目前使用二进制序列化的传统应用程序。因为变化是巨大的,标志认证的所有参与序列化与JSON序列标签,私人领域是太辛苦了。由于Json.net可以做ISerializable的对象的序列化,我们希望做到这一点。这工作如果没有循环引用的对象。

我的班

  [Serializable接口]
类部:ISerializable的
{
    公务员管理器{获得;组; }
    公共字符串名称{;组; }

    公共部门(){}

    公共部门(SerializationInfo中的信息,的StreamingContext上下文)
    {
        经理=(雇员)info.GetValue(经理人的typeof(员工));没有找到// Manager的数据,因为JSON字符串本身并不具有员工属性
        名称=(字符串)info.GetValue(姓名,typeof运算(字符串));
    }
    公共无效GetObjectData使用(SerializationInfo中的信息,的StreamingContext上下文)
    {
        info.AddValue(经理人,经理);
        info.AddValue(姓名,姓名);
    }
}

[可序列化]
一流的员工:ISerializable的
{
    公共部门部门{获得;组; }
    公共字符串名称{;组; }

    公务员(){}

    公务员(SerializationInfo中的信息,的StreamingContext上下文)
    {
        部=(部)info.GetValue(部门中的typeof(系));
        名称=(字符串)info.GetValue(姓名,typeof运算(字符串));
    }

    公共无效GetObjectData使用(SerializationInfo中的信息,的StreamingContext上下文)
    {
        info.AddValue(部门,部);
        info.AddValue(姓名,姓名);
    }
}
 

我的测试code:

  JsonSerializerSettings jsonSS =新JsonSerializerSettings();
jsonSS.Formatting = Formatting.Indented;
jsonSS.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //如果有被引用对象然后它未在JSON序列示
//jsonSS.ReferenceLoopHandling = ReferenceLoopHandling.Serialize; //抛出计算器错误
jsonSS preserveReferencesHandling = preserveReferencesHandling.All。


教研室=新部门();
department.Name =DEPT1;

员工EMP1 =新员工{名称=EMP1,系=部门};
department.Manager = NULL;

字符串json1 = JsonConvert.SerializeObject(EMP1,jsonSS);
// json1 =
// {
//的$ id:1,
//  部门: {
//的$ id:2,
//经理人:空,
//名:DEPT1
//},
//名:EMP1
//}

员工empD1 = JsonConvert.DeserializeObject&LT;员工&GT;(json1,jsonSS); //管理器设置为空

department.Manager = EMP1; //非空经理设置
字符串json2 = JsonConvert.SerializeObject(EMP1,jsonSS); // SEE经理属性缺失

// json2 = {
//的$ id:1,
//  部门: {
//的$ id:2,
//名:DEPT1
//},
//名:EMP1
//}

员工empD2 = JsonConvert.DeserializeObject&LT;员工&GT;(json2,jsonSS); //抛出异常
 

解决方案

我会尽量简短:)

  1. 看来,它的 ISerializable的接口螺丝起来。如果你删除它,一切都完美。

  2. 你有一个<一个href="http://stackoverflow.com/questions/8933187/is-implementing-iserializable-interface-necessary-when-not-implementing-any-cust">REALLY很好的理由为实施 ISerializable的接口员工?如果没有,只是将其删除。如果你这样做,GOTO 3;)

  3. 我不知道的 Newtonsoft.Json 的内部,但不知何故,它没有实施治疗时,循环引用正确 ISerializable的。在 GitHub上你或许应该文件中的问题。

Some time back i have reported an issue for which i have got a fix in Json.net 4.5 R11.

If my circular referenced property Manager is NULL then serialisation and deserialisation works fine.

But when circular reference property Manager is set to NON NULL value then it gets ignored in the serialised string and hence it throws an exception in deserialisation.

Json.net issue base says the problem is in your code but i could not figure out. Can somebody help me here?

Questions:

  1. Is there any problem with the code below?
  2. If yes what should I do to solve the problem?
  3. If not then what should be done in Json.net code to solve this problem?

Some more updates: This is needed in the legacy application which is currently using Binary serialization. Since changes are huge, marking all the private fields that are involved in serialization with the Json serialization tag is too much work. Since Json.net can do serialization of ISerializable object we want to do this. This works if there are no circular reference objects.

My classes

[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 ) ); //Manager's data not found since json string itself does not have Employee property
        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
{
    public Department Department { get; set; }
    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 );
    }
}

My Test code:

JsonSerializerSettings jsonSS= new JsonSerializerSettings();
jsonSS.Formatting = Formatting.Indented;
jsonSS.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //If there is referenced object then it is not shown in the json serialisation
//jsonSS.ReferenceLoopHandling = ReferenceLoopHandling.Serialize; //Throws stackoverflow error
jsonSS.PreserveReferencesHandling = PreserveReferencesHandling.All;


Department department = new Department();
department.Name = "Dept1";

Employee emp1 = new Employee { Name = "Emp1", Department = department };
department.Manager = null;

string json1 = JsonConvert.SerializeObject( emp1, jsonSS );
//json1 = 
//            {
//  "$id": "1",
//  "Department": {
//    "$id": "2",
//    "Manager": null,
//    "Name": "Dept1"
//  },
//  "Name": "Emp1"
//}

Employee empD1 = JsonConvert.DeserializeObject<Employee>( json1, jsonSS ); //Manager is set as null

department.Manager = emp1; //Non null manager is set
string json2 = JsonConvert.SerializeObject( emp1, jsonSS ); //SEE Manager property is missing

//  json2 =          {
//  "$id": "1",
//  "Department": {
//    "$id": "2",
//    "Name": "Dept1"
//  },
//  "Name": "Emp1"
//}

Employee empD2 = JsonConvert.DeserializeObject<Employee>( json2, jsonSS );  //Throws exception

解决方案

I'll keep it short :)

  1. It seems that it's the ISerializable interface that screws it up. If you remove it, everything works perfectly.

  2. Do you have a REALLY good reason for implementing the ISerializable interface in Employee and Department? If not, just remove it. If you do, GOTO 3 ;)

  3. I don't know Newtonsoft.Json internals, but somehow it's not treating circular references properly when implementing ISerializable. You should probably file an issue at GitHub.

这篇关于Json.net:序列化/ Deserialisation不工作的,有循环引用ISerializable的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆