如何告诉杰克逊不要包含收集类型信息?

时间:2014-09-11 20:47:33

标签: java json jackson

我遇到了"多态反序列化问题"所以我配置jackson为非具体类添加类型信息作为属性,如下所示:

ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
mapper.setVisibilityChecker(mapper.getSerializationConfig().getDefaultVisibilityChecker()
        .withFieldVisibility(JsonAutoDetect.Visibility.NONE)
        .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
        .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
        .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
        .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE))
mapper.enableDefaultTypingAsProperty(DefaultTyping.NON_CONCRETE_AND_ARRAYS, "__class__")

它运行良好,但是对于集合实例(例如List),它创建了一个双元素数组,第一个位置包含一个字符串,其中包含集合的类型信息(java.util.ArrayList)。

这会影响客户端(Javascript)期望的json的结构,因为它预期数组的位置,现在有一个数组,其中另一个位于第二个位置。

我希望Jackson只为非集合而非具体类型插入类型信息,因为框架本身并不需要集合实现类型才能正确反序列化集合属性。

这是否可以以可配置的方式进行?

1 个答案:

答案 0 :(得分:2)

您可以创建ObjectMapper.DefaultTypeResolverBuilder的自定义版本并覆盖useForType()方法。

以下是默认方法的实现:

    public boolean useForType(JavaType t)
    {
        switch (_appliesFor) {
        case NON_CONCRETE_AND_ARRAYS:
            while (t.isArrayType()) {
                t = t.getContentType();
            }
            // fall through
        case OBJECT_AND_NON_CONCRETE:
            return (t.getRawClass() == Object.class) || !t.isConcrete();
        case NON_FINAL:
            while (t.isArrayType()) {
                t = t.getContentType();
            }
            return !t.isFinal(); // includes Object.class
        default:
        //case JAVA_LANG_OBJECT:
            return (t.getRawClass() == Object.class);
        }
    }

在您的版本中,只需添加此前提条件

即可
if (t.isCollectionLikeType()) {
    return false;
}

告诉Jackson跳过类似Collection的类型以插入类型信息。

并使用TypeResolverBuilder

设置新的ObjectMapper.setDefaultTyping(myCustomTyper);