仅将 Spring MVC 中提到的字段序列化为 JSON 响应

2023-12-30

我正在使用 spring 编写休息服务MVC产生JSON回复。它应该允许客户端仅选择响应中的给定字段,这意味着客户端可以将他感兴趣的字段作为 url 参数提及,例如?fields=field1,field2.

使用 Jackson 注释并不能提供我想要的东西,因为它不是动态的,而且 Jackson 中的过滤器似乎也没有足够的前景。 到目前为止,我正在考虑实现一个自定义消息转换器来解决这个问题。

还有其他更好的方法来实现这一目标吗?我希望这个逻辑不与我的服务或控制器耦合。


从 Spring 4.2 开始,@JsonFilterMappingJacksonValue 支持

  • Issue : SPR-12586:支持杰克逊@JsonFilter https://jira.spring.io/browse/SPR-12586
  • 犯罪 :ca06582 https://github.com/spring-projects/spring-framework/commit/ca06582f2af2e31b23031d8650148d95129ce4a1?ts=4

您可以直接将 PropertyFilter 注入到控制器中的 MappingJacksonValue 中。

@RestController
public class BookController {
    private static final String INCLUSION_FILTER = "inclusion";

    @RequestMapping("/novels")
    public MappingJacksonValue novel(String[] include) {
        @JsonFilter(INCLUSION_FILTER)
        class Novel extends Book {}

        Novel novel = new Novel();
        novel.setId(3);
        novel.setTitle("Last summer");
        novel.setAuthor("M.K");

        MappingJacksonValue res = new MappingJacksonValue(novel);
        PropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept(include);
        FilterProvider provider = new SimpleFilterProvider().addFilter(INCLUSION_FILTER, filter);
        res.setFilters(provider);
        return res;
    }

或者您可以通过 ResponseBodyAdvice 声明全局策略。下面的例子通过“exclude”参数实现过滤策略。

@ControllerAdvice
public class DynamicJsonResponseAdvice extends AbstractMappingJacksonResponseBodyAdvice {
    public static final String EXCLUDE_FILTER_ID = "dynamicExclude";
    private static final String WEB_PARAM_NAME = "exclude";
    private static final String DELI = ",";
    private static final String[] EMPTY = new String[]{};

    @Override
    protected void beforeBodyWriteInternal(MappingJacksonValue container, MediaType contentType,
            MethodParameter returnType, ServerHttpRequest req, ServerHttpResponse res) {
        if (container.getFilters() != null ) {
            // It will be better to merge FilterProvider
            // If 'SimpleFilterProvider.addAll(FilterProvider)' is provided in Jackson, it will be easier.
            // But it isn't supported yet. 
            return;
        }

        HttpServletRequest baseReq = ((ServletServerHttpRequest) req).getServletRequest();
        String exclusion = baseReq.getParameter(WEB_PARAM_NAME);

        String[] attrs = StringUtils.split(exclusion, DELI);
        container.setFilters(configFilters(attrs));
    }

    private FilterProvider configFilters(String[] attrs) {
        String[] ignored = (attrs == null) ? EMPTY : attrs;
        PropertyFilter filter = SimpleBeanPropertyFilter.serializeAllExcept(ignored);
        return new SimpleFilterProvider().addFilter(EXCLUDE_FILTER_ID, filter);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

仅将 Spring MVC 中提到的字段序列化为 JSON 响应 的相关文章

随机推荐