问题:
导致报错代码大致如下:FixMe 标识部分会报错。
public static void test(){
JSONObject resultJson = xxxService.xxMethond(xxParam);
logger.info("返回参数为:{}", resultJson.toJSONString());
// 返回参数打印日志如下:{"code":"1002","content":{"msg":"密码错误次数超限"},"errorMsg":"XXXX"}
resultJson.getJSONObject("content").getString("msg");
// FixMe 下面代码会报错,因为这里我混淆了概念
JSON.parseObject(resultJson.getString("content")).getString("msg");
}
报错内容:
expect ':' at 0, actual = com.alibaba.fastjson.JSONException: expect ':' at 0, actual =
原因:
原因在于 resultJson 中的 content 虽然日志打印出来的是 JSONObject 格式,但是不代表 content 是 JSONObject.由于我假想 content 是JSONObject。所以 JSON.parseObject(resultJson.getString("content")) 报错了。
如下代码就一定会报错:
public static void main(String[] args) {
JSONObject resultJson = new JSONObject();
Map content = new HashMap<>();
content.put("msg", "saasa");
resultJson.put("content", (Object) content);
System.out.println(resultJson.getString("content"));
System.out.println(JSON.parseObject(resultJson.getString("content")));
System.out.println(resultJson.getJSONObject("content").getString("msg"));
}
运行结果如下:
{msg=saasa}
Exception in thread "main" com.alibaba.fastjson.JSONException: expect ':' at 0, actual =
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:310)
at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1335)
at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1301)
at com.alibaba.fastjson.JSON.parse(JSON.java:148)
at com.alibaba.fastjson.JSON.parse(JSON.java:139)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:212)
在这里记录一下 JSON 的 toString() 、toJSONString() 、getJSONObject() 方法,避免自己之后再犯这种低级假想错误。
- JSONObject 继承自 JSON。JSONObject 的 toString()、toJSONString() 是调用的父类 JSON 的方法。
- JSON.toString() 调用的是 toJSONString()
@Override
public String toString() {
return toJSONString();
}
public String toJSONString() {
SerializeWriter out = new SerializeWriter();
try {
new JSONSerializer(out).write(this);
return out.toString();
} finally {
out.close();
}
}
- getJSONObject()
public JSONObject getJSONObject(String key) { Object value = map.get(key); if (value instanceof JSONObject) { return (JSONObject) value; } if (value instanceof String) { return JSON.parseObject((String) value); } return (JSONObject) toJSON(value); }
分析上面的错误示例 main 方法中,resultJson.getJSONObject("content") ,content 的实际类型是 Map,所以执行的是 (JSONObject) toJSON(value)。看到下图红色箭头指向的部分,就可以明白为什么 resultJson.getJSONObject("content") 是可以成功获取 JSONObject 对象了。toJSON 方法里做了很多类型的兼容和判断。正确使用工具类的前提是熟悉工具类的大致原理。