使用Jackson 2.1.2(com.fasterxml.jackson
包),我试图定义一个带有@JsonValue
的公共接口,它可能与关联的子类的类型不同,但已经遇到接口的泛型是循环的问题,即使循环泛型不直接在实现类中使用。
我有一个如下所示的界面:
public interface C<S, R extends C<S,R>> {
}
(有方法,但事实证明它们对我们的目的而言并不重要。)
public class TestSet<E> extends ForwardingSet<E> implements
C<Set<E>, TestSet<E>> {
@JsonIgnore
private final Set<E> delegate = Sets.newLinkedHashSet();
@Override
protected Set<E> delegate() {
return delegate;
}
@JsonValue
public Set<E> view() {
return delegate;
}
}
当我尝试运行以下测试用例时:
@Test
public void test() throws Exception {
TestSet<String> tst = new TestSet<String>();
tst.add("one");
System.out.println(mapper.writeValueAsString(tst));
}
它会生成java.lang.StackOverflowError
:
java.lang.StackOverflowError
at java.lang.Class.getDeclaringClass(Native Method)
at com.fasterxml.jackson.databind.type.TypeBindings._resolveBindings(TypeBindings.java:269)
at com.fasterxml.jackson.databind.type.TypeBindings._resolve(TypeBindings.java:203)
at com.fasterxml.jackson.databind.type.TypeBindings.findType(TypeBindings.java:121)
at com.fasterxml.jackson.databind.type.TypeFactory._fromVariable(TypeFactory.java:807)
at ...
调查显示在这种情况下永远不会调用view()方法。
我发现了两种可能导致这种情况发生变化并显示所需行为的变化。第一种是在界面中不使用循环泛型。仅仅删除它就足以防止问题发生。第二种是使用使用mapper.writerWithType(Set.class)
创建的显式类型编写器(使用@JsonSerialize
注释as
似乎不会这样做。后者对我的用例来说并不是一个好的解决方法,除非我能以某种方式弄清楚如何在注释中反映出来。
不完全属于同一类别,但到目前为止我只在R
某种形式的java.util.Collection
时才看到它。如果我将其声明为class TestSet<E> implements CRDT<Integer, TestSet<E>>
则没有错误。
我的问题是:是否存在一些我缺少的基本内容或一些已知的注释方法?