Динамический выбор 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 во время выполнения

Другие вопросы по тегам