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

时间:2018-04-17 10:48:59

标签: java spring resttemplate pojo form-data

我有一个形式的POJO:

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

我的服务运行只接受内容类型:&#34; application / x-www-form-urlencoded&#34;。

我用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,因为我已经使用JacksonHTTPMessageConverter配置了我的RestTemplate Bean。所以我可以轻松地将POJO转换为application / json。但是,我无法弄清楚如何使用application / x-www-form-urlencoded来做到这一点。

我现在已经搜索了一段时间了,我找到的唯一解决方案是编写自己的转换器将我的BaseRequest类转换为Spring的MultiValueMap,然后是Spring&#39 ; s FormHttpMessageConverter将自动处理它。但我想避免这样做。还有其他方法吗?

任何线索都会受到赞赏。谢谢!

编辑: 我的问题与@JsonProperty not working for 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"
  }
}"

1 个答案:

答案 0 :(得分:0)

尝试将请求有效负载中的嵌套对象转换为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被跳过了。

希望它有所帮助!