项目场景:
Spring Boot项目使用RestTemplate调用接口,使用嵌套实体对象接收的返回结果
实体对象TokenUser,其中TokenUserInfo是嵌套的对象:
@Data
public class TokenUser {
private Integer code;
private TokenUserInfo data;
private Boolean success;
}
@Data
public class TokenUserInfo {
/**
* 用户id
*/
private String userId;
/**
* 用户名
*/
private String userName;
}
使用RestTemplate调用接口
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<String> formEntity= new HttpEntity<>(requestJson, headers);
TokenUser tokenUser = null;
try {
tokenUser = restTemplate.postForObject(url, formEntity, TokenUser.class);
} catch (Exception e) {
logger.error("调用接口出错: ", e);
}
问题描述
Spring Boot项目使用RestTemplate调用接口,使用嵌套实体对象接收的返回结果
返回的嵌套对象为null不会有问题
{
"data": null,
"success": true,
"code": 200
}
但是返回的嵌套对象是''空字符串就会报错
{
"data": "",
"success": true,
"code": 200
}
报错详情:
Error while extracting response for type [class com.test.dto.TokenUser] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.test.dto.TokenUserInfo` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value (''); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.test.dto.TokenUserInfo` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('')
at [Source: (PushbackInputStream); line: 1, column: 55] (through reference chain: com.test.dto.TokenUser["data"])
原因分析:
简单来说就是 json转化成对象失败了,失败的原因是TokenUserInfo对象中虽然有一个构造器,却是全参构造器或是无参构造器,就是缺少一个只有一个String类型参数的构造器,导致在解析 ' ' 空字符串时失败了。
解决方案:
第一种:实体类加上String类型参数的构造器
同时加上@NoArgsConstructor, @AllArgsConstructor 注解,提供无参数的构造函数和全参数的构造函数
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TokenUserInfo {
/**
* 防止返回值是空字符串,用string来接收
*/
public TokenUserInfo(String userId){
this.userId = userId;
}
/**
* 用户id
*/
private String userId;
/**
* 用户名
*/
private String userName;
}
第二种:用String接收返回结果,再转json对象
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<String> formEntity= new HttpEntity<>(requestJson, headers);
TokenUser tokenUser = null;
try {
String jsonResult = restTemplate.postForObject(url, formEntity, String.class);
JSONObject userJson = JSON.parseObject(jsonResult);
tokenUser = JSONObject.toJavaObject(userJson, TokenUser.class);
} catch (Exception e) {
logger.error("调用接口出错: ", e);
}
我这里用的是alibaba的包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.44</version>
</dependency>