记代码假想导致 expect ':' at 0, actual = com.alibaba.fastjson.JSONException: expect ':' at 0, actual =

 问题:

导致报错代码大致如下: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 方法里做了很多类型的兼容和判断。正确使用工具类的前提是熟悉工具类的大致原理。

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值