如何在 Grails 控制器中处理 JSONObject 中的 post 一个 BigInteger?

How to handle post a BigInteger in JSONObject in grails controller?

这是我的例子:

class MyController {

    def index() {
        JSONObject json = request.JSON
        log.info('{}', json)
        respond json
    }

}

如何处理 json 中的 BigInteger?像这样:

curl -H 'content-type: application/json' -d '{"largeNum": 99999999999999999999999}' http://localhost:8080/

JSONObject 会将此 largeNum 转换为 Double,如下所示:

{"largeNum":9.999999999999999E22}

但是我想得到一个BigInteger,怎么办?

问题出在 Grails JSON 实现中。

request.JSON 调用 grails.converters.JSON,后者又使用 org.grails.web.json.JSONTokener class 解析输入。

重要的代码形式org.grails.web.json.JSONTokener#nextValue是:

            try {
                return Integer.valueOf(s);
            } catch (Exception e) {
                try {
                    return Long.valueOf(s);
                } catch (Exception f) {
                    try {
                        return Double.valueOf(s);
                    } catch (Exception g) {
                        return s;
                    }
                }
            }

这将导致精度丢失并且无法更改行为, 因为这个分词器是在自定义编组器发挥作用之前使用的。

我想到的唯一解决方案是使用GSON or Jackson

代码取自grails 3.3.0。不知道是不是从那以后。

约JSON个数: 如果没有具体的格式,java 中的大多数 json 解析器会将 json 数字视为 BigDecimal,因为 json 数字没有限制,而 BigDecimal是唯一能够正确表示的 java 类型 - 请参阅 JSON Spec

这可能看起来很尴尬,因为 JSON 代表 Java Script Object Notation 而 Javascript 无法处理这些数字。

谢谢你们。我推送一个 PR 来解决这个问题:https://github.com/grails/grails-core/pull/11334

等待上游合并。