1

使用 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>>没有错误。

我的问题是:我是否缺少一些基本的东西或一些已知的注释方法?

4

0 回答 0