使用 Jackson 2.1.2(com.fasterxml.jackson
包),我试图定义一个带有 a 的通用接口,@JsonValue
它可能与关联的子类具有不同的类型,但是当接口的泛型是循环时遇到问题,即使循环generic 不直接在实现类中使用。
我有一个看起来像这样的界面:
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>>
没有错误。
我的问题是:我是否缺少一些基本的东西或一些已知的注释方法?