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
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);
}
}
}
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;
}