Преобразование POJO в данные формы на Java

У меня есть POJO вида:

@Data
public class BaseRequest {
    private String type;
    private Map<String, Object> details;
    private Map<String, Object> signature;
}

У меня работает служба, которая принимает только тип контента: «application / x-www-form-urlencoded».

Я написал клиент на Java, который использует Spring RestTemplate для выполнения вызовов.

public String getInvoice(BaseRequest req, String url) {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

    HttpEntity<BaseRequest> httpEntity = new HttpEntity<BaseRequest>(req, headers);
    String response = this.restTemplate.postForObject(url, httpEntity, String.class);
    return response;
}

Однако это вызывает ошибку:

org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [com.x.y.z.BaseRequest] and content type [application/x-www-form-urlencoded]

Это работает, если я установил тип контента как JSON:

headers.setContentType(MediaType.APPLICATION_JSON);

Я знаю, что это работает для JSON, потому что я настроил свой объект RestTemplate Bean с помощью JacksonHTTPMessageConverter. Так что я могу легко преобразовать POJO в application / json. Однако я не могу понять, как это сделать с помощью application / x-www-form-urlencoded.

Я искал это некоторое время, и единственное решение, которое я нашел, - это написать собственный конвертер для преобразования моего класса BaseRequest в Spring MultiValueMap, а затем Spring FormHttpMessageConverter автоматически обработает его. Но я не хочу этого делать. Есть ли другой способ обойти это?

Любые зацепки будут оценены. Спасибо!

Обновлено: Мой вопрос отличается от @JsonProperty не работает для Content-Type: application / x-www-form-urlencoded. Происходит преобразование о принятии данных в application / x-www-form-urlencoded и преобразовании их в POJO. Мой вопрос касается преобразования POJO в application / x-www-form-urlencoded при использовании Spring resttemplate для совершения вызовов. И, как я уже упоминал, я знаю, что могу добиться этого, написав собственный конвертер для преобразования моего POJO в Spring MultiValueMap. Однако я хочу знать, смогу ли я этого избежать.

Обновлено:

Dump of $_POST on the API when I send my data as MultiValueMap<String, Object>:

"array(0) {
}"

Dump of $_POST on the API when I send my data through Postman in the correct format:

"array(2) {
  ["type"]=>
  string(16) "abcd"
  ["details"]=>
  array(1) {
  ["template_file"]=>
  string(16) "x.html"
  }
}"

Итак, вы аннотировали свой метод контроллера с помощью «производит (application / x-www-form-urlencoded)»?

daniu 17.04.2018 13:04

@dainu Код метода контроллера находится в другом сервисе, и я не могу вносить в него изменения. И этот сервис написан на PHP. Я просто выполняю вызовы API к этой службе из моей службы (написанной на Java).

Qawls 17.04.2018 13:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
8
2
2 623
1

Ответы 1

Попробуйте преобразовать вложенный объект в полезную нагрузку запроса в org.springframework.util.MultiValueMap. Добавьте и реализуйте метод конвертера в вашем POJO

public class BaseRequest {
    // ...

    public MultiValueMap<String, Object> toMap() {
        MultiValueMap<String, Object> result = new LinkedMultiValueMap<>();
        result.add("type", type);
        result.put("details", details);
        result.put("signature", signature);
        return result;
    }
}

Теперь используйте его при создании запроса

HttpEntity<BaseRequest> httpEntity = new HttpEntity<BaseRequest>(req.toMap(), headers);

Это вызвано тем, что внутри FormHttpMessageConverter, который выполняет фактический метод преобразования, canRead(Class<?>, MediaType) проверяет, является ли MultiValueMap.class.isAssignableFrom(clazz), где clazz, вашим объектом полезной нагрузки. В вашем случае это не удалось, поэтому FormHttpMessageConverter пропустил.

Надеюсь, поможет!

Привет, спасибо за ответ. Как я уже упоминал в своем вопросе, я не хочу писать собственный конвертер для преобразования моего POJO в MultiValueMap. Я говорю это, потому что в MultiValueMap <String, Object>, если я вставлю детали (которые имеют тип Map <String, Object>), они не будут правильно отформатированы на сервере, поэтому сервер не сможет их проанализировать. . Я добавляю вывод $ _REQUEST на сервер, к которому выполняется этот вызов, в EDIT.

Qawls 17.04.2018 14:00

Вы можете изменить подпись MultiValueMap<String, Object> на MultiValueMap<String, String> и отформатировать объект вручную в соответствии с вашими потребностями.

Sergey Prokofiev 17.04.2018 14:09

да, но я не хочу этого делать, так как писать такой конвертер было бы некрасиво. Нет ли какой-нибудь библиотеки вроде Джексона, которая могла бы обработать это преобразование за меня? Или проблема, с которой я столкнулся, слишком необычна?

Qawls 17.04.2018 14:33

@Qawls, Spring уже делает это за вас, он принимает ваш запрос от объектов и выполняет все обратные вызовы преобразования / обработки / обработки. Нет ничего плохого в том, чтобы написать конкретное представление ваших данных, если ваш сервер не может обработать его иначе.

Sergey Prokofiev 17.04.2018 14:40

@Qawls, если вам нужен хороший красивый обходной путь, вам нужно исправить свой PHP-код, что невозможно, поэтому я рекомендую вам придерживаться рабочего решения, а не гнаться за «лучшим».

Sergey Prokofiev 17.04.2018 14:43

Хотел знать, есть ли что-то вроде Джексона, которое может сделать это для меня, или, может быть, что-то мне здесь не хватает. Думаю, я сам прибегну к написанию конвертера. Большое спасибо за твою помощь.

Qawls 17.04.2018 15:08

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