Заставьте Spring использовать Джексона для преобразования закодированного в JSON @RequestParam в конечную точку GET - PullRequest
0 голосов
/ 07 ноября 2019

Это мой первый вопрос в stackoverflow, поэтому, пожалуйста, будьте осторожны:)

Существует конечная точка GET, которая будет преобразована в POST. Его необходимо расширить, чтобы принять параметр запроса filterKeys, который будет содержать данные в кодировке JSON. Этот подход не очень распространен, но он используется некоторыми большими API. Рабочий подход заключается в том, чтобы сопоставить параметр запроса со строкой и затем десериализовать в объект Java с помощью объекта Jackson ObjectMapper в методе контроллера. Есть ли способ применить эту десериализацию Джексона где-нибудь в фоновом режиме, точно так же, как она поддерживается для @RequestBody из коробки Spring?

Пример для JSON в кодировке filterKeys:

[
  {
    "parameter": "datetime",
    "value": {
      "type": "INT_RANGE",
      "start": 1275782400,
      "end": 1571443199
    }
  },
  {
    "parameter": "value",
    "value": {
      "type": "LONG_RANGE",
      "start": 100,
      "end": 200
    }
  }
]

Объект Java:

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Getter;

import javax.validation.constraints.NotNull;
import java.util.List;

@Getter
@AllArgsConstructor
@JsonInclude
public class FilterKeyRequest {

    @NotNull
    private String parameter;
    @NotNull
    private FilterValue value;

}

Я попытался просто сопоставить filterKeys с FilterKeyRequest, что, конечно, не работает. Текущее решение состоит в том, чтобы выполнить десериализацию внутри метода контроллера:

@GetMapping("/data")
public List<TransferResponse> getData(@RequestParam(required = false) int someOtherParam,
                                          @RequestParam(required = false) String filterKeys) throws BadFilterKeyParameter {

        List<FilterKeyRequest> filters = List.of();
        try {
            filters = objectMapper.readValue(filterKeys, new TypeReference<List<FilterKeyRequest>>() {});
        } catch (IOException e) {
            throw new BadFilterKeyParameter("The filterKeys parameters couldn't be encoded due do bad JSON format");
        }

        return someService.getData(someOtherParam, filters);
    }

Я бы действительно хотел элегантно справиться с этим где-нибудь на заднем плане. Это может быть возможно с org.springframework.core.convert.converter.Converter или org.springframework.web.method.support.HandlerMethodArgumentResolver как-то. Желательно без явного вызова объекта сопоставления объектов Джексона.

ОБНОВЛЕНИЕ: Я нашел решение с Converter, но это все еще означает явное обращение к Джексону ObjectMapper, но я могу жить с этим:

@Slf4j
@RequiredArgsConstructor
@Component
public class FilterKeyConverter implements Converter<String, List<FilterKeyRequest>> {

    private final ObjectMapper mapper;

    @Override
    public List<FilterKeyRequest> convert(String source) {
        List<FilterKeyRequest> filters = List.of();
        try {
            filters = mapper.readValue(source, new TypeReference<List<FilterKeyRequest>>() {});
        } catch (IOException e) {
            log.warn("The parameter couldn't be encoded due do bad JSON encoding");
        }
        return filters;
    }
}

1 Ответ

0 голосов
/ 07 ноября 2019

Ваш метод getData () должен быть определен внутри аннотируемого класса @ RestController (и не @Controller)

@RestController
public DataController {
    @GetMapping("/data")
    public List<TransferResponse> getData(@RequestParam(required = false) int someOtherParam,
                                          @RequestParam(required = false) String filterKeys) throws BadFilterKeyParameter {

        List<FilterKeyRequest> filters = List.of();
        try {
            filters = objectMapper.readValue(filterKeys, new TypeReference<List<FilterKeyRequest>>() {});
        } catch (IOException e) {
            throw new BadFilterKeyParameter("The filterKeys parameters couldn't be encoded due do bad JSON format");
        }

        return someService.getData(someOtherParam, filters);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...