Dynamic Selection Of JsonView in Spring MVC Controller

前端 未结 2 693
予麋鹿
予麋鹿 2020-11-29 23:14

I am aware that it is possible to annotate controller methods with @JsonView(...) to statically define a single view class in Spring MVC. Unfortunately this mea

相关标签:
2条回答
  • 2020-11-29 23:53

    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);
        }
      }
    }
    
    0 讨论(0)
  • 2020-11-29 23:54

    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;
    }
    
    0 讨论(0)
提交回复
热议问题