开发避坑短篇(一):JSONNull转型String异常分析

异常信息

java 复制代码
java.lang.ClassCastException: net.sf.json.JSONNull cannot be cast to java.lang.String

业务背景

使用net.sf.json类库解析第三方接口返回的json格式的数据的时候报错,接口返回数据jsonStr的值如下:

复制代码
{"msg":"操作成功","code":200,"data":{"bizCode":"00","bizMsg":"下单成功!","serialId":"2ae24bb1-9bb2-722b-8698-ade57f143938","detail":null}}

相关代码

java 复制代码
...
JSONObject jsonObject = JSONObject.fromObject(jsonStr);
int code = (int) jsonObject.get("code");
String msg = (String) jsonObject.get("msg");
String retJson = "";
if (200 == code) {
    JSONObject bodyData = jsonObject.getJSONObject("data");
    String bizCode = (String) bodyData.get("bizCode");
    String bizMsg = (String) bodyData.get("bizMsg");
    if ("00".equals(bizCode)) {
        String detail = (String) bodyData.get("detail");
...      
    }
}
...

异常分析

报错代码

java 复制代码
String detail = (String) bodyData.get("detail");

从异常信息看,bodyData.get("detail")拿到的是一个JSONNull,不能强转为字符串类型,所以报错了。那为什么拿到不是null或者"null"?调试的时候看到的data的值是"null"?拿bodyData.get("detail")做null判断或者与"null"比较看得不得。

java 复制代码
Object obj = bodyData.get("detail");
System.out.println(null == obj || "null".equals(obj));

输出结果是false,所以bodyData.get("detail")拿到的值不是null对象也不是"null"字符串,而是一个JSONNull类型的变量。JSONNull是org.json库中的一个特殊类,用于表示JSON中的null值。如果你尝试直接获取一个不存在的键的值,或者在解析的JSON中某个值确实是null,你可能会得到一个JSONNull实例。

解决办法

要避免尝试获取JSONNull的值引发的异常,可以做类型判断。

java 复制代码
Object obj = bodyData.get("detail");
if(!(obj instanceof net.sf.json.JSONNull)) {
	String detail = (String) bodyData.get("detail");
...
}