【问题标题】:JSON schema generation with Jackson goes into infinite loop使用 Jackson 生成 JSON 模式进入无限循环
【发布时间】:2012-08-21 12:53:55
【问题描述】:

可能是我在杰克逊遗漏了一个明显的注释,但我有以下课程

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.jsonschema.JsonSchema;

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class Loop {

  private String name;
  private Loop otherLoop;

  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  public Loop getOtherLoop() { return otherLoop; }
  public void setOtherLoop(Loop otherLoop) { this.otherLoop = otherLoop; }

  public static void main(String[] args) throws Exception {
    Loop parent = new Loop();
    parent.setName("parent");

    Loop child = new Loop();
    child.setName("child");
    child.setOtherLoop(parent);

    ObjectMapper mapper = new ObjectMapper();
    System.out.println(mapper.writeValueAsString(child));

    JsonSchema jsonSchema = mapper.generateJsonSchema(Loop.class);
    System.out.println(mapper.writeValueAsString(jsonSchema));
  }
}

当我使用 Jackson 2 运行它时,它会进入无限循环

{"name":"child","otherLoop":{"name":"parent"}}
Exception in thread "main" java.lang.StackOverflowError
at com.fasterxml.jackson.databind.cfg.MapperConfig.isEnabled(MapperConfig.java:106)
at com.fasterxml.jackson.databind.SerializationConfig.getAnnotationIntrospector(SerializationConfig.java:382)
at com.fasterxml.jackson.databind.SerializerProvider.getAnnotationIntrospector(SerializerProvider.java:307)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.createContextual(BeanSerializerBase.java:318)
at com.fasterxml.jackson.databind.SerializerProvider._handleContextual(SerializerProvider.java:971)
at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:447)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:619)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:621)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:621)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:621)

任何想法,解决方法?!

【问题讨论】:

  • 你在 Loop 类中有一个 Loop 对象,所以它进入了无限循环。如果您添加@JSONIgnore,它不会进入无限循环,但这可能不是您需要的解决方案。嗯。
  • 考虑使用接口,比如公共类Loop实现AInterface,你可以有私有AInterface otherLoop;在 Loop 类中。
  • 听起来像是一个错误,最好在github.com/FasterXML/jackson-databind/issues打开错误报告
  • 报告为一个问题,将在重新设计的 Jackson 实现中修复。

标签: java json jackson jsonschema


【解决方案1】:
@XmlAccessorType(XmlAccessType.FIELD)
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class Loop {
   @XMLAttribute(name = "Name")
   private String name;
   @XMLAttribute(name = "Loops")
   private List<Loop> listLoop;

   //getters and setters    
}

【讨论】:

  • 这并没有真正的帮助,因为空界面不是那个地方所期望的。它确实是一个 Loop 对象。但是,一旦您在接口中添加“AInterface getOtherLoop()”,它就会停止使用相同的 stackoverflow。
  • 如果在类中添加同一个类对象,就是在创建无限循环,为什么在同一个类中需要同一个类对象?我不明白。您可以为此创建一个新类。
  • LinkedList 就是一个经典的例子。树也。与相同类型对象的关系很常见:配偶、孩子……以及喜欢组件复合模式的抽象。即使是更通用的 A 链接到 B 和 B 链接到 A 的情况,json 模式生成也会失败。并以传递方式添加更多级别 A -> B -> C -> A 都失败了。
  • 我同意。更新了我的答案。使用我之前建议的界面不会像您指出的那样对您的情况有所帮助。相反,您可以拥有一个杰克逊可以理解并且不会进入无限循环的对象列表。
  • 当我使用私有字段运行它时,它什么也没给我:{"type":"object","properties":{}}。将这些公开,我仍然会得到一个 stackoverflow。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多