记一次 net.sf.json.JSONObject,使用 getLong() 获取属性值得坑

场景如下: web端传递一个JSON 至服务端,服务端进行解析并处理时,出现了一个诡异的现象。
  1. 在我们日常的项目中,为了解决浏览器端处理 long 类型参数时,存在精度都丢失的问题,我们通常会将long转为string 再传递给前端

  2. 正常的情况下,当我们向服务器发起请求时,我们服务端使用 DTO接收参数,spring 会自动做对象转换,此时也不会出现什么异常。

  3. 问题是,当你觉得参数不多,定义个DTO又麻烦,干脆用 String 接收参数,再自行转换为对象,进行数据取值时,问题就来了。

    如:前端请求参数为:

{
  "id": "445065833448300548",
  "note": "不合格!"
}

当你使用 net.sf.json.JSONObject 进行处理时,你会发现…

 String content = "{ \"id\": \"445065833448300548\", \"note\": \"不合格!\" }";
 net.sf.json.JSONObject obj = net.sf.json.JSONObject.fromObject(content);
 Long id = obj.getLong("id");
 System.out.println(id);
 System.out.println(id.compareTo(445065833448300548L) == 0);

啥? 啥情况?
在这里插入图片描述
你没看错,输出的结果,根本不是同一个值

究其根本原因,是net.sf.json.JSONObjectgetLong()方法在处理数据时,如果参数类型不为Number,那它就先使用Double.parseDouble()方法,先将值转为 double类型,再强制转为 long 类型。在这个double 转为 long 的过程中,精度丢失了。(至于精度丢失的原因,有兴趣的小伙伴可以自行Google深度了解一下!)

package net.sf.json;
public final class JSONObject extends AbstractJSON implements JSON, Map, Comparable {

    // ....

	public long getLong(String key) {
        this.verifyIsNull();
        Object o = this.get(key);
        if (o != null) {
            return o instanceof Number ? ((Number)o).longValue() : (long)this.getDouble(key);
        } else {
            throw new JSONException("JSONObject[" + JSONUtils.quote(key) + "] is not a number.");
        }
    }

    // ....

    public double getDouble(String key) {
        this.verifyIsNull();
        Object o = this.get(key);
        if (o != null) {
            try {
                return o instanceof Number ? ((Number)o).doubleValue() : Double.parseDouble((String)o);
            } catch (Exception var4) {
                throw new JSONException("JSONObject[" + JSONUtils.quote(key) + "] is not a number.");
            }
        } else {
            throw new JSONException("JSONObject[" + JSONUtils.quote(key) + "] is not a number.");
        }
    }
}
  1. fastjson 或者 Gson 也存在这个问题吗?
public static void main(String[] args) {
        String content = "{ \"id\": \"445065833448300548\", \"note\": \"不合格!\" }";

        System.out.println("------------------ net.sf.json ------------------");

        net.sf.json.JSONObject obj = net.sf.json.JSONObject.fromObject(content);
        Long id = obj.getLong("id");
        System.out.println(id);
        System.out.println(id.compareTo(445065833448300548L) == 0);


        System.out.println("------------------ com.alibaba.fastjson ------------------");

        com.alibaba.fastjson.JSONObject obj2 = com.alibaba.fastjson.JSONObject.parseObject(content);
        Long id2 = obj2.getLong("id");
        System.out.println(id2);
        System.out.println(id2.compareTo(445065833448300548L) == 0);


        System.out.println("------------------ com.google.gson ------------------");

        com.google.gson.JsonObject obj3 = new com.google.gson.JsonParser().parse(content).getAsJsonObject();
        Long id3 = obj3.get("id").getAsLong();
        System.out.println(id3);
        System.out.println(id3.compareTo(445065833448300548L) == 0);
    }

在这里插入图片描述

经测试,fastjsonGson 都正常,妥妥的!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值