Динамический выбор JsonView в Spring MVC Controller
Я знаю, что можно комментировать методы контроллера с @JsonView(...)
статически определить один класс представления в Spring MVC. К сожалению, это означает, что мне нужна отдельная конечная точка для каждого типа представления, которое у меня может быть.
Я вижу, что другие люди спрашивали об этом раньше. Хотя этот подход может работать, у Spring часто есть много способов сделать то же самое. Иногда решение может быть гораздо более простым, чем кажется на первый взгляд, если у вас есть немного знаний о некоторых внутренних элементах.
Я хотел бы иметь одну конечную точку контроллера, которая может динамически выбирать подходящее представление на основе текущего участника. Могу ли я вернуть Model
с атрибутом, который содержит соответствующий класс представления или, возможно, MappingJacksonValue
экземпляр напрямую?
Я вижу в org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#writeInternal
есть фрагмент кода, который определяет, какое представление использовать:
if (value instanceof MappingJacksonValue) {
MappingJacksonValue container = (MappingJacksonValue) object;
value = container.getValue();
serializationView = container.getSerializationView();
}
Который, кажется, прибыл из org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice#beforeBodyWriteInternal
но у меня возникают проблемы с разработкой, если есть способ, которым я мог бы обойти это просто, возвращая определенное значение, которое содержит необходимую информацию для Jackson2HttpMessageConverter
выбрать правильный вид.
Любая помощь высоко ценится.
2 ответа
На случай, если кто-то еще захочет достичь того же самого, на самом деле это очень просто.
Вы можете напрямую вернутьorg.springframework.http.converter.json.MappingJacksonValue
экземпляр из вашего контроллера, который содержит как объект, который вы хотите сериализовать, так и класс представления.
Это будет подхвачено org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#writeInternal
метод и соответствующий вид будет использоваться.
Это работает примерно так:
@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;
}
Вот вариант ответа выше, который помог мне. Я обнаружил, что проблемы возвращаются MappingJacksonValue
непосредственно при использовании полезных нагрузок Spring HATEOAS. Если я верну его непосредственно из обработчика контроллера, по какой-то причине Resources
а также ResourceSupport
mixins не применяются правильно, а JSON HAL _links отображается как ссылки. Тоже весна ResponseEntity
не отображается как должно показывать body
а также status
объекты в полезной нагрузке.
С помощью ControllerAdvice
чтобы добиться того же, помогли с этим, и теперь мои полезные данные отображаются правильно и представления применяются по мере необходимости
@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);
}
}
}
Пожалуйста, проверьте https://github.com/monitorjbl/json-view/, с помощью этого мы решили проблему динамического выбора полей JSON во время выполнения