问题
对接腾讯的TIM接口,接口返回的应答包体的字段都是首字母大写的,如下:
{
"ActionStatus":"OK",
"ErrorInfo":"",
"ErrorCode":0
}
于是我就定义了一个对应的Bean:
@Data
public class TimResult {
private String ActionStatus;
private String ErrorInfo;
private Integer ErrorCode;
}
但是在使用RestTemplate#postForEntity()
进行接口调用后,使用responseEntity.getBody()
得到的TimResult
对象的各个属性值都为null。
private TimResult post(String serviceName, String cmdName, JSONObject reqBody) throws UserSigException {
final String adminUserSig = adminUserSigHelper.getSignature();
final long random = ThreadLocalRandom.current().nextInt() & 0xffffffffL;
String url = String.format(URL_FORMAT, HOST, serviceName, cmdName, tlsSigAPIv2.getSdkappid(), timProperties.getAdminIdentifier(), adminUserSig, random);
final ResponseEntity<TimResult> responseEntity = httpClientTemplate.postForEntity(url, reqBody, TimResult.class);
final int statusCodeValue = responseEntity.getStatusCodeValue();
if (statusCodeValue != 200) {
log.error("调用TIM后台REST接口失败,url = {},reqBody = {},statusCodeValue = {}", url, reqBody, statusCodeValue);
throw new RuntimeException("调用TIM后台REST接口失败");
}
final TimResult timResult = responseEntity.getBody();
return timResult;
}
分析原因
通过debug分析发现,是因为RestTemplate
要将响应的json字符串反序列化为TimResult
对象时,从容器中的类型转换器中匹配到了Jackson转换器,然后Jackson进行反序列化时,都没有匹配到TimResult
的各个属性。然后查阅资料发现Jackson默认的属性发现规则将会查找到如下所述的属性:
- 所有被
public
修饰的成员变量; - 所有被
public
修饰的getXxx()
方法; - 所有被
public
修饰的setXxx(value)
方法;
由于我们定义的TimResult
的属性都是private
的,所以Jackson
反序列化时是根据public
的setXxx(value)
方法名得到首字母小写的属性,但是实际上TimResult
的属性都是首字母大小写的,所以都没赋值成功。
若使用FastJson进行序列化、反序列化,就没有这个问题。
解决
解决方法有两种:
- 直接将bean对象中的属性改为public,属性名命名为首字母大写,比如
{"Name":"nomouse","Age":12}
,定义相应的bean为:
public class TimResult {
public String ActionStatus;
public String ErrorInfo;
public Integer ErrorCode;
}
- 但是第一种方法不符合Java的命名规范,所以可以用第二种方法,在属性上添加
@JsonProperty
注解:
@Data
public class TimResult {
@JsonProperty(value = "ActionStatus")
private String actionStatus;
@JsonProperty(value = "ErrorInfo")
private String errorInfo;
@JsonProperty(value = "ErrorCode")
private Integer errorCode;
}
采用上面两种方式不仅在解析json的时候有效,在输出json流的时候同样是以大写字母开头。