杰克逊:以编程方式确定子类型

时间:2013-10-01 22:52:08

标签: java json polymorphism jackson

给定一个任意Class个对象,确定杰克逊注册的那个类的子类型的最佳方法是什么?

例如,这是一个简单的案例,其中类LionPenguinAnimal的子类型:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
        @JsonSubTypes.Type(Lion.class),
        @JsonSubTypes.Type(Penguin.class)})
public static abstract class Animal {}

@JsonTypeName("Lion")
public static class Lion extends Animal {}

@JsonTypeName("Penguin")
public static class Penguin extends Animal {}

我的梦想功能如下:

List<Class> getSubTypeClasses(Class c) {...}

getSubTypeClasses(Animal.class)将返回LionPenguin

如果Jackson API没有提供获取此信息的便捷方式,我将手动阅读注释,但是知道与任何 {{1实施。

4 个答案:

答案 0 :(得分:2)

您可以使用ai.findSubTypes(ac)代替mapper.getSubtypeResolver().collectAndResolveSubtypes(ac, config, ai)。 我没有使用已注册的子类型测试它,但查看它应该工作的代码。

答案 1 :(得分:1)

目前没有这样做的机制。但是你可以提交一个添加这样的东西的请求:给定一个基类,返回一组已知的子类型以及用于它们的类型id,以及默认的实现用法。这似乎是一个合理的事情来提供访问。

与此同时(新功能可用于2.3,所以需要一些时间),请查看AnnotationIntrospector,看看那里有哪些方法,以及jackson-databind如何使用它构建映射信息。即使没有访问器,您也不必手动编写所有内容。

答案 2 :(得分:0)

感谢StaxMan让我朝着正确的方向努力。这是Jaxen 2.2.3的解决方案:

public static List<Class> getSubtypeClasses(ObjectMapper mapper, Class c) {
    return getSubtypeClasses(mapper.getDeserializationConfig(), c);
}

public static List<Class> getSubtypeClasses(MapperConfig config, Class c) {
    AnnotationIntrospector ai = config.getAnnotationIntrospector();
    AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(c, ai, config);
    List<NamedType> subtypes = ai.findSubtypes(ac);

    List<Class> result = new ArrayList<>();

    if (subtypes != null) {
        for (NamedType subtype : subtypes) {
            result.add(subtype.getType());
        }
    }

    return result;
}

答案 3 :(得分:0)

要访问超类的SubTypes注释,您可以使用JacksonAnnotationIntrospector:

    AnnotationIntrospector annotationInspector = new JacksonAnnotationIntrospector();

    JavaType superClassType = TypeFactory.defaultInstance().uncheckedSimpleType(Animal.class);

    AnnotatedClass annotatedClass = AnnotatedClass.construct(superClassType,new ObjectMapper().getSerializationConfig());

    List<NamedType> subtypes = annotationInspector.findSubtypes(annotatedClass);