Dynamic Selection Of JsonView in Spring MVC Controller

你说的曾经没有我的故事 提交于 2019-11-27 17:52:46

On the off chance someone else wants to achieve the same thing, it actually is very simple.

You can directly return aorg.springframework.http.converter.json.MappingJacksonValue instance from your controller that contains both the object that you want to serialise and the view class.

This will be picked up by the org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#writeInternal method and the appropriate view will be used.

It works something like this:

@RequestMapping(value = "/accounts/{id}", method = GET, produces = APPLICATION_JSON_VALUE)
public MappingJacksonValue getAccount(@PathVariable("id") String accountId, @AuthenticationPrincipal User user) {
    final Account account = accountService.get(accountId);
    final MappingJacksonValue result = new MappingJacksonValue(account);
    final Class<? extends View> view = accountPermissionsService.getViewForUser(user);
    result.setSerializationView(view);
    return result;
}

Here is a variation of the above answer which helped me. I found issues returning MappingJacksonValue directly while using Spring HATEOAS payloads. If I return it directly from the controller's handler, for some reason the Resources and ResourceSupport mixins don't get applied correctly and JSON HAL _links is rendered as links. Also Spring ResponseEntity is not rendered as it should showing body and status objects in the payload.

Using ControllerAdvice to achieve the same helped with that and now my payloads are rendered correctly and the views are applied as needed

@ControllerAdvice(assignableTypes = MyController.class)
public class MyControllerAdvice extends AbstractMappingJacksonResponseBodyAdvice {

  @Override
  protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType, MethodParameter returnType,
                                         ServerHttpRequest req, ServerHttpResponse res) {
    ServletServerHttpRequest request = (ServletServerHttpRequest)req;
    String view = request.getServletRequest().getParameter("view");
    if ("hello".equals(view)) {
      bodyContainer.setSerializationView(HelloView.class);
    }
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!