杰克逊的@JsonView,@ JsonFilter和Spring

Eng*_*_DJ 31 java spring json spring-mvc jackson

可以使用Jackson @JsonView@JsonFilter注释来修改Spring MVC控制器返回的JSON,同时使用MappingJacksonHttpMessageConverterSpring @ResponseBody@RequestBody注释吗?

public class Product
{
    private Integer id;
    private Set<ProductDescription> descriptions;
    private BigDecimal price;
    ...
}


public class ProductDescription
{
    private Integer id;
    private Language language;
    private String name;
    private String summary;
    private String lifeStory;
    ...
}
Run Code Online (Sandbox Code Playgroud)

当客户端请求收集时Products,我想返回每个的最小版本ProductDescription,也许只是它的ID.然后在后续调用中,客户端可以使用此ID来请求ProductDescription包含所有属性的完整实例.

能够在Spring MVC控制器方法上指定它是理想的,因为调用的方法定义了客户端请求数据的上下文.

f.k*_*sis 13

最终,我们希望使用类似于StaxMan为JAX-RS显示的符号.不幸的是,Spring不支持开箱即用,所以我们必须自己做.

这是我的解决方案,它不是很漂亮,但它完成了这项工作.

@JsonView(ViewId.class)
@RequestMapping(value="get", method=RequestMethod.GET) // Spring controller annotation
public Pojo getPojo(@RequestValue Long id)
{
   return new Pojo(id);
}
Run Code Online (Sandbox Code Playgroud)
public class JsonViewAwareJsonView extends MappingJacksonJsonView {

    private ObjectMapper objectMapper = new ObjectMapper();

    private boolean prefixJson = false;

    private JsonEncoding encoding = JsonEncoding.UTF8;

    @Override
    public void setPrefixJson(boolean prefixJson) {
        super.setPrefixJson(prefixJson);
        this.prefixJson = prefixJson;
    }

    @Override
    public void setEncoding(JsonEncoding encoding) {
        super.setEncoding(encoding);
        this.encoding = encoding;
    }


    @Override
    public void setObjectMapper(ObjectMapper objectMapper) {
        super.setObjectMapper(objectMapper);
        this.objectMapper = objectMapper;
    }


    @Override
    protected void renderMergedOutputModel(Map<String, Object> model,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        Class<?> jsonView = null;
        if(model.containsKey("json.JsonView")){
            Class<?>[] allJsonViews = (Class<?>[]) model.remove("json.JsonView");
            if(allJsonViews.length == 1)
                jsonView = allJsonViews[0];
        }


        Object value = filterModel(model);
        JsonGenerator generator =
                this.objectMapper.getJsonFactory().createJsonGenerator(response.getOutputStream(), this.encoding);
        if (this.prefixJson) {
            generator.writeRaw("{} && ");
        }
        if(jsonView != null){
            SerializationConfig config = this.objectMapper.getSerializationConfig();
            config = config.withView(jsonView);
            this.objectMapper.writeValue(generator, value, config);
        }
        else
            this.objectMapper.writeValue(generator, value);
    }
}
Run Code Online (Sandbox Code Playgroud)
public class JsonViewInterceptor extends HandlerInterceptorAdapter
{

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
        Object handler, ModelAndView modelAndView) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        JsonView jsonViewAnnotation = handlerMethod.getMethodAnnotation(JsonView.class);
        if(jsonViewAnnotation != null)
            modelAndView.addObject("json.JsonView", jsonViewAnnotation.value());
    }
}
Run Code Online (Sandbox Code Playgroud)

在spring-servlet.xml中

<bean name="ViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="mediaTypes">
            <map>
                <entry key="json" value="application/json" />
            </map>
        </property>
        <property name="defaultContentType" value="application/json" />
        <property name="defaultViews">
            <list>
                <bean class="com.mycompany.myproject.JsonViewAwareJsonView">
                </bean>
            </list>
        </property>
    </bean>
Run Code Online (Sandbox Code Playgroud)

<mvc:interceptors>
    <bean class="com.mycompany.myproject.JsonViewInterceptor" />
</mvc:interceptors>
Run Code Online (Sandbox Code Playgroud)


Geo*_*lou 13

这个问题解决了!
按照这个

添加对Jackson序列化视图的支持

Spring MVC现在支持Jackon的序列化视图,用于从不同的控制器方法(例如详细页面与摘要视图)呈现相同POJO的不同子集.问题:SPR-7156

这是SPR-7156.

状态:已解决

描述

Jackson的JSONView注释允许开发人员控制方法的哪些方面是序列化的.在当前实现中,必须使用Jackson视图编写器,但是内容类型不可用.如果作为RequestBody注释的一部分,可以更好地指定JSONView.

可在Spring ver> = 4.1上获得

UPDATE

点击此链接.用一个例子解释@JsonView注释.


Sta*_*Man 12

我不知道Spring的工作原理(对不起!),但Jackson 1.9可以使用JAX-RS方法的@JsonView注释,所以你可以这样做:

@JsonView(ViewId.class)
@GET // and other JAX-RS annotations
public Pojo resourceMethod()
{
   return new Pojo();
} 
Run Code Online (Sandbox Code Playgroud)

和Jackson将使用ViewId.class标识的View作为活动视图.也许Spring有(或将有)类似的能力?使用JAX-RS,这是由标准的JacksonJaxrsProvider处理的,这是值得的.