【问题标题】:How to handle post a BigInteger in JSONObject in grails controller?如何在 grails 控制器中处理 JSONObject 中的 BigInteger 帖子?
【发布时间】:2019-05-16 03:58:23
【问题描述】:

这是我的例子:

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,怎么做?

【问题讨论】:

  • 我会使用字符串来传输 BigDecimal/Integer,因为 JSON 数字是双倍的。
  • @cfrick:JSON 数字不是双精度数。它们没有限制。
  • @Peter 如果您的生产者/消费者可能使用最坏的情况(双重)并且您最终得到错误的数字,那么您将无济于事。我更喜欢强迫他们屈服于思考问题。
  • @cfrick:是的,没错。我想指出,这是您使用哪个解析器而不是 JSON 本身的问题。

标签: json grails


【解决方案1】:

问题出在 Grails JSON 实现中。

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

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;
                    }
                }
            }

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

我想到的唯一解决方案是使用GSONJackson

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

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

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

【讨论】:

  • 没有。 BigDecimal.valueOf(9.999999999999999E22).toBigInteger() 是99999999999999990000000
【解决方案2】:

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

等待上游合并。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    相关资源
    最近更新 更多