在 Java 中将 POJO 转换为表单数据
Posted
技术标签:
【中文标题】在 Java 中将 POJO 转换为表单数据【英文标题】:Converting a POJO to Form Data in Java 【发布时间】:2018-09-27 07:17:51 【问题描述】:我有一个 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,因为我已经使用 JacksonHTTPMessageConverter 配置了我的 RestTemplate Bean。所以我可以轻松地将 POJO 转换为 application/json。但是,我无法弄清楚如何使用 application/x-www-form-urlencoded 来做到这一点。
我已经搜索了一段时间了,我找到的唯一解决方案是编写自己的转换器,将我的 BaseRequest 类转换为 Spring 的 MultiValueMap,然后 Spring 的 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"
"
【问题讨论】:
所以你已经用“produces(application/x-www-form-urlencoded)”注释了你的控制器方法? @dainu 控制器方法的代码在不同的服务上,我无法在那里进行更改。该服务是用 php 编写的。我只是从我的服务(用 Java 编写)对该服务进行 API 调用。 【参考方案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)
是否是您的有效负载对象。在你的情况下它失败了,所以 FormHttpMessageConverter
跳过了。
希望对你有帮助!
【讨论】:
您好,感谢您的回复。就像我在问题中提到的那样,我想避免编写自己的转换器来将我的 POJO 转换为 MultiValueMap。我这样说是因为在 MultiValueMapMultiValueMap<String, Object>
的签名更改为MultiValueMap<String, String>
并根据您的需要手动格式化您的对象。
是的,但我想避免这样做,因为编写该转换器会很丑陋。难道没有像杰克逊这样的图书馆可以为我处理这种转换吗?还是我面临的问题太少见了?
@Qawls,Spring 已经为您完成了,它从对象中获取您的请求并执行所有转换/处理/处理回调。如果您的服务器无法以其他方式处理数据,则编写数据的特定表示并不难看。
@Qawls,如果你想要好的漂亮的解决方法,你需要修复你的 PHP 代码,这是不可能的,所以我建议你坚持工作解决方案而不是追逐“最佳”。以上是关于在 Java 中将 POJO 转换为表单数据的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Java Stream 中将 POJO 的列表转换为 Map<String,List>?
struts2+ 将表单值设置为 POJO 并将 POJO 值设置为表单
在javascript中将表单数据保存为xml时防止跨站点(XSS)