将bidir循环引用序列化为JSON的最佳方法

时间:2012-04-18 16:04:19

标签: json serialization spring-mvc orm jackson

我有一个数据结构BookCollection,它有一套书。每本书都引用了它所处的BookCollection。这是一种标准的一对多关系。它在服务器端运行良好,但我必须将其发送到客户端。该应用程序使用Jackson ObjectMapper进行序列化,设置为Spring Bean。问题是,你不能轻易地序列化BookCollection和Books,因为标准JSON中没有引用(我确实需要标准的JSON)。

目前的解决方案是将@JsonIgnore放在Book.collection字段上,或者将更高级的@JsonManagedReference放在BookCollection.books上,将@JsonBackReference放在Book.collection上。然而,这并没有解决我的所有问题,一些请求要求Book对象,并且也希望得到它的BookCollection。

最终,我正在寻找一些方法来告诉Serializer只包含一次对象。因此,当我得到一本书时,JSON看起来像这样:

{
  isbn: 125412416,
  title: "Introduction to JSON",
  collection: {
     name: "Programming Books",
     books: [
         {
             isbn: 18723425,
             title: "Java for experts"
         },
         {
             isbn: 82472347,
             title: "C# and its extensions"
         },
     ]
  }
}

虽然“C#及其扩展”和“专家Java”也有对集合对象的引用,但由于它已经被序列化,所以它没有被序列化。此外,集合对象不包括“JSON简介”一书,因为它已经序列化了。

当我要求BookCollection时,我明白了:

{
  name: "Programming Book",
  books: [
    {
      isbn: 125412416,
      title: "Introduction to JSON"
    },
    {
      isbn: 18723425,
      title: "Java for experts"
    },
    {
      isbn: 82472347,
      title: "C# and its extensions"
    },
  ]
}

序列化字段

虽然BookCollection很好地序列化,Book有点令人困惑,因为目录现在有一些书(缺少原版)。更好的是允许指定序列化每个字段一次。允许Book.collection序列化一次

序列化图书将如下所示:

{
  isbn: 125412416,
  title: "Introduction to JSON",
  collection: {
     name: "Programming Books",
     books: [
         {
             isbn: 18723425,
             title: "Java for experts"
         },
         {
             isbn: 82472347,
             title: "C# and its extensions"
         },
         {
             isbn: 125412416,
             title: "Introduction to JSON"
         }
     ]
  }
}

序列化书籍收藏类似:

{
  name: "Programming Book",
  books: [
    {
      isbn: 125412416,
      title: "Introduction to JSON"
    },
    {
      isbn: 18723425,
      title: "Java for experts"
    },
    {
      isbn: 82472347,
      title: "C# and its extensions"
    },
  ]
}

2 个答案:

答案 0 :(得分:1)

我最近遇到了类似的问题:Jackson - serialization of entities with birectional relationships (avoiding cycles)

因此,解决方案是升级到Jackson 2.0,并向类中添加以下注释:

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, 
                  property = "@id")
public class SomeEntityClass ...

答案 1 :(得分:0)

  namespace ConsoleApplication4
    {
        public class Teacher
        {
            public int MyProperty { get; set; }
            // [ScriptIgnore]
            public ClassRoom working { get; set; }
        }
        public class ClassRoom
        {
            public ClassRoom()
            {

            }
            public int sss { get; set; }
            public int s2 { get; set; }
            public int ddy { get; set; }
            //  [ScriptIgnore]
            public Teacher teachers { get; set; }

        }
        class Program
        {
            static void Main(string[] args)
            {  
                Console.ForegroundColor = ConsoleColor.Green;

                ClassRoom @new = new ClassRoom();
                Teacher @teacher = new Teacher();
                @new.teachers = teacher;
                @teacher.working = @new;

                JavaScriptSerializer serializer = new JavaScriptSerializer();

                List<  ClassRoom> classrooms = new List<ClassRoom>();
                classrooms.Add(@new);
                classrooms.Add(@new);
                classrooms.Add(@new);
                classrooms.Add(@new);
                classrooms.Add(@new);

                var result = (from n in classrooms
                              select n).ToList();//tolist() to convert IEnumrable to list can be modified

                for (int i = 0; i < result.Count; i++)
                {
                    result[i].teachers.working = null;//making all child's parents =null to prevent circular refrencing
                }


                Console.WriteLine(serializer.Serialize(result));

                 Console.ReadLine();
            }
        }

    }

我认为这个解决方案可以解决您的问题 它解决了我的问题 (result [i] .teachers.working = null;) 创建导致循环引用的属性= null;