5

我正在使用基于@JsonView. ContextResolver我通常用这样的方式配置杰克逊:

@Override
public ObjectMapper getContext(Class<?> aClass) {
    // enable a view by default, else Views are not processed
    Class view = Object.class;
    if (aClass.getPackage().getName().startsWith("my.company.entity")) {
        view = getViewNameForClass(aClass);
    }
    objectMapper.setSerializationConfig(
         objectMapper.getSerializationConfig().withView(view));
    return objectMapper;
}

如果我序列化单个实体,这很好用。但是,对于某些用例,我想使用与单个实体相同的视图来序列化我的实体列表。在这种情况下,aClassis ArrayList,所以通常的逻辑没有多大帮助。

所以我正在寻找一种方法来告诉杰克逊使用哪个视图。理想情况下,我会写:

@GET @Produces("application/json; charset=UTF-8")
@JsonView(JSONEntity.class)
public List<T> getAll(@Context UriInfo uriInfo) {
    return getAll(uriInfo.getQueryParameters());
}

并在视图下进行序列化JSONEntity。RestEasy可以做到这一点吗?如果没有,我该如何模仿?

编辑:我知道我可以自己进行序列化:

public String getAll(@Context UriInfo info, @Context Providers factory) {
    List<T> entities = getAll(info.getQueryParameters());
    ObjectMapper mapper = factory.getContextResolver(
         ObjectMapper.class, MediaType.APPLICATION
    ).getContext(entityClass);
    return mapper.writeValueAsString(entities);
}

然而,这充其量是笨拙的,并且破坏了让框架处理这个样板的整个想法。

4

1 回答 1

6

事实证明,可以@JsonView简单地用(就像我的问题一样)注释特定的端点,杰克逊将使用这个视图。谁会猜到。

您甚至可以以通用方式执行此操作(在我的另一个问题中有更多上下文),但这将我与 RestEasy 联系在一起:

@Override
public void writeTo(Object value, Class<?> type, Type genericType, 
        Annotation[] annotations,  MediaType mediaType, 
        MultivaluedMap<String, Object> httpHd, 
        OutputStream out) throws IOException {
    Class view = getViewFromType(type, genericType);
    ObjectMapper mapper = locateMapper(type, mediaType);

    Annotation[] myAnn = Arrays.copyOf(annotations, annotations.length + 1);
    myAnn[annotations.length] = new JsonViewQualifier(view);

    super.writeTo(value, type, genericType, myAnn, mediaType, httpHd, out);
}

private Class getViewFromType(Class<?> type, Type genericType) {
    // unwrap collections
    Class target = org.jboss.resteasy.util.Types.getCollectionBaseType(
            type, genericType);
    target = target != null ? target : type;
    try {
        // use my mix-in as view class
        return Class.forName("example.jackson.JSON" + target.getSimpleName());
    } catch (ClassNotFoundException e) {
        LOGGER.info("No view found for {}", target.getSimpleName());
    }
    return Object.class;
}
于 2014-01-22T21:37:10.060 回答