Jackson序列化、反序列化首字母大写的json字符串问题解决

问题

对接腾讯的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反序列化时是根据publicsetXxx(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流的时候同样是以大写字母开头。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
你可以使用 Java 中的 `Jackson` 库来序列 `LocalDateTime` 对象的 JSON 字符串。首先,确保你已经在 Maven 或 Gradle 中添加了 Jackson 的依赖项。然后,按照以下步骤进行序列: 1. 创建一个包含 `LocalDateTime` 属性的 POJO 类,例如: ```java public class MyData { private LocalDateTime dateTime; // Getter and Setter methods } ``` 2. 使用 `ObjectMapper` 类来进行序列。示例代码如下: ```java import com.fasterxml.jackson.databind.ObjectMapper; public class Main { public static void main(String[] args) { String json = "{\"dateTime\":\"2022-01-01T10:00:00\"}"; try { ObjectMapper objectMapper = new ObjectMapper(); MyData myData = objectMapper.readValue(json, MyData.class); System.out.println("DateTime: " + myData.getDateTime()); } catch (Exception e) { e.printStackTrace(); } } } ``` 在上述代码中,我们创建了一个 JSON 字符串 `json`,其中包含一个 `dateTime` 属性。然后,我们使用 `ObjectMapper` 对象的 `readValue` 方法将 JSON 字符串序列为 `MyData` 对象。最后,我们打印出序列后的 `LocalDateTime` 对象。 请注意,上述代码中的日期时间格式 `"2022-01-01T10:00:00"` 符合 ISO 8601 标准,这是 `LocalDateTime` 默认的格式。如果你的 JSON 字符串使用了不同的日期时间格式,你可能需要自定义一个 `DateTimeFormatter` 对象,并将其与 `ObjectMapper` 对象一起使用。 希望这可以帮助到你!如有任何疑问,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值