在Java中将POJO转换为表单数据

Qaw*_*wls 8 java spring form-data pojo resttemplate

我有一个形式的POJO:

@Data
public class BaseRequest {
    private String type;
    private Map<String, Object> details;
    private Map<String, Object> signature;
}
Run Code Online (Sandbox Code Playgroud)

我正在运行一个仅接受内容类型的服务:“ 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;
}
Run Code Online (Sandbox Code Playgroud)

但是,它将引发错误:

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]
Run Code Online (Sandbox Code Playgroud)

如果我将内容类型设置为JSON,它将起作用:

headers.setContentType(MediaType.APPLICATION_JSON);
Run Code Online (Sandbox Code Playgroud)

我知道它适用于JSON,因为我已经用JacksonHTTPMessageConverter配置了RestTemplate Bean。因此,我可以轻松地将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。我的问题是关于在使用Spring的resttemplate进行调用时将POJO转换为application / x-www-form-urlencoded。就像我提到的,我知道我可以通过编写自己的转换器将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"
  }
}"
Run Code Online (Sandbox Code Playgroud)

Ser*_*iev 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在请求创建期间使用它

HttpEntity<BaseRequest> httpEntity = new HttpEntity<BaseRequest>(req.toMap(), headers);
Run Code Online (Sandbox Code Playgroud)

这是因为在其中FormHttpMessageConverter执行实际转换方法canRead(Class<?>, MediaType)检查MultiValueMap.class.isAssignableFrom(clazz)其中 clazz 是否是您的有效负载对象。在你的情况下它失败了,所以FormHttpMessageConverter跳过了。

希望能帮助到你!