【问题标题】:Circular Json serializing循环Json序列化
【发布时间】:2013-12-14 14:48:36
【问题描述】:

我有一个带有两个实体的 javaEE 应用程序,它们在数据库中获得持久化。两个实体都有双向关联。

第一个实体:

@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Child.class)
public class Child implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne(fetch= FetchType.LAZY)
    private Father father;
}

第二个实体

@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Father.class)
public class Father implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne(fetch= FetchType.LAZY)
    private Child child;
}

两者都通过以下资源公开:

@Path("father")
@Stateless
public class FatherResource{

    @Context
    private UriInfo uri;

    @Inject FatherDao fatherDao;

    public FatherResource() {
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Father> getFathers() {
        //TODO return proper representation object
        return fatherDoa.getFathers();
    }
}

还有一个 DAO,它只是从数据库中获取父对象。

现在的问题是,我得到了一个循环的 json 结构。 就像这样:

{ "id":"1", "child": {"id":"1", "father": {"id":"1", "child":{"id":"1", [...] 

我只想见孩子一次。

我尝试使用:

@JsonIgnoreProperties({"child"})  //above the class
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")  //above the class
@JsonIgnore    //above the property

我想得到的是:

{ "id":"1", "child": {"id":"1"}}

我正在使用

JDK 7
JaxRS
Jackson
Hibernate/Eclipselink
Glassfish 4.0

另一个不起作用的测试:

@Entity
@JsonSerialize
@JsonIdentityInfo(generator=ObjectIdGenerators.UUIDGenerator.class, property="id", scope=Object.class)
public class Father implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne(fetch= FetchType.LAZY)
    private Child child;
}

ApplicationConfig.java:

public class ApplicationConfig extends Application {

@Override
public Set<Class<?>> getClasses() {
    Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
    // following code can be used to customize Jersey 2.0 JSON provider:

    try {
        Class jsonProvider = Class.forName("org.glassfish.jersey.jackson.JacksonFeature");

    } //...
//..

beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="annotated">
</beans>

【问题讨论】:

  • 您的问题是什么?特别是,您希望发生什么?
  • 我想得到:{ "id":"1", "child": {"id":"1"}}
  • 您尝试过 Jackson 的 ObjectIdentity 功能吗? wiki.fasterxml.com/JacksonFeatureObjectIdentity
  • 好吧,这行不通。
  • 如果您举例说明您尝试过的事情以及它们如何不起作用,这可能会有所帮助。

标签: json jakarta-ee jackson jax-rs java-ee-7


【解决方案1】:

您可以编写一个循环,在返回列表之前将father 设置为空。这样您就不会为 JSON 序列化程序提供循环数据结构。

这个解决方案可能看起来不太干净,但它确实有效,因为没有其他人回答过这个问题,但我认为值得一提。

【讨论】:

    【解决方案2】:

    这是一个示例,它可以解决您的问题。 Jackson 能够序列化您的递归。看看这个:

    3 个 POJO(A、B、C)和一个测试。用杰克逊 2.2.3 测试。

    import com.fasterxml.jackson.annotation.JsonIdentityInfo;
    import com.fasterxml.jackson.annotation.ObjectIdGenerators;
    
    @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
    public class RecClassA {
    
        private RecClassA mySelf;
        private RecClassB b;
    
        private String value = "AV";
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
        public RecClassA getMySelf() {
            return mySelf;
        }
    
        public void setMySelf(RecClassA mySelf) {
            this.mySelf = mySelf;
        }
    
        public RecClassB getB() {
            return b;
        }
    
        public void setB(RecClassB b) {
            this.b = b;
        }
    
    }
    
    import com.fasterxml.jackson.annotation.JsonIdentityInfo;
    import com.fasterxml.jackson.annotation.ObjectIdGenerators;
    
    @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
    public class RecClassB {
    
        private String value = "BV";
        private RecClassC c;
        private RecClassA a;
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
        public RecClassC getC() {
            return c;
        }
    
        public void setC(RecClassC c) {
            this.c = c;
        }
    
        public RecClassA getA() {
            return a;
        }
    
        public void setA(RecClassA a) {
            this.a = a;
        }
    
    }
    
    import com.fasterxml.jackson.annotation.JsonIdentityInfo;
    import com.fasterxml.jackson.annotation.ObjectIdGenerators;
    
    @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
    public class RecClassC {
    
        private String value = "CV";
        private RecClassA a;
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
        public RecClassA getA() {
            return a;
        }
    
        public void setA(RecClassA a) {
            this.a = a;
        }
    
    }
    
    import org.testng.annotations.Test;
    
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class ObjectMapperRecursionTest {
    
        private ObjectMapper om = new ObjectMapper();
    
        @Test
        public void simpleWriteTest() throws JsonProcessingException{
            RecClassA a = new RecClassA();
    
            String result = om.writeValueAsString(a);
            System.out.println("simpleWriteTest: " + result);
        }
    
        @Test
        public void simpleRecursionWriteTest() throws JsonProcessingException{
            RecClassA a = new RecClassA();
            a.setMySelf(a);
            String result = om.writeValueAsString(a);
            System.out.println("simpleRecursionWriteTest: " + result);
        }
    
        @Test
        public void abbaRecursionWriteTest() throws JsonProcessingException{
            RecClassA a = new RecClassA();
            RecClassB b = new RecClassB();
    
            a.setB(b);
            b.setA(a);
    
            String result = om.writeValueAsString(a);
            System.out.println("abbaRecursionWriteTest: " + result);
        }
    
        @Test
        public void abcaRecursionWriteTest() throws JsonProcessingException{
            RecClassA a = new RecClassA();
            RecClassB b = new RecClassB();
            RecClassC c = new RecClassC();
    
            a.setB(b);
            b.setC(c);
            c.setA(a);
    
            String result = om.writeValueAsString(c);
            System.out.println("abcaRecursionWriteTest: " + result);
        }
    
    }
    

    这里是测试结果:

    abbaRecursionWriteTest: {"@id":1,"mySelf":null,"b":{"@id":2,"value":"BV","c":null,"a":1},"value":"AV"}
    abcaRecursionWriteTest: {"@id":1,"value":"CV","a":{"@id":2,"mySelf":null,"b":{"@id":3,"value":"BV","c":1,"a":null},"value":"AV"}}
    simpleRecursionWriteTest: {"@id":1,"mySelf":1,"b":null,"value":"AV"}
    simpleWriteTest: {"@id":1,"mySelf":null,"b":null,"value":"AV"}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多