How to prevent JSONObject from json.jar converts decimal numbers string into double

断了今生、忘了曾经 提交于 2020-01-14 13:27:05

问题


Using JSONObject to read a json response from a server. The server returns some decimal number. Normal numbers are not a problem to but the problem occurs when there is decimal number of form 0.00068. Numbers like 0.00068 are automatically stored into Double object and when an attempt is made to retrieve such number returns "computerized scientific notation" of the number , that is 6.8E4 even if the number accessed as double by getDouble(index) method or as String with getString(index) method.

Have tried this way of converting double value to string but have have eliminated this tecinique as there is some positve rounding added when Double converted to BigDecimal. This can be eliminated by rounding set while scaling to BigDecimal.ROUND_CEILING. But I don't want any scaling and want with the original values as the actual value is a small decimal number and the server guarantees the number wont exceed 6 digit after the decimal point.

BigDecimal big = new BigDecimal(new Double(0.00680));

System.out.println(big.toPlainString()); //0.006799999999999999621136392846665330580435693264007568359375

System.out.println(big.setScale(15, BigDecimal.ROUND_DOWN)); //0.006799999999999

Can there be some way to get actual string value of Double that is a number 0.00680 without scaling, or can we prevent JSONObject interpreting numbers in to their respective numeric classes.

Thanking in advance.


回答1:


Unrelated to the JSON library you use, you should not use the BigDecimal constructor taking a double parameter, since that uses the exact decimal representation of the double's binary floating-point value

Instead, use the static valueOf method since that uses the string value of the double and thus rounds correctly.

When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method.

However, for very large or small numbers the parsing to a double might already have introduced rounding errors, in that case the only solution would be to use a different JSON library that supports parsing numbers as BigDecimals.




回答2:


In org.json.JSONObject class comment out lines in method stringToValue(String string)

    /*
     * If it might be a number, try converting it. If a number cannot be
     * produced, then the value will just be a string.
     */

    char initial = string.charAt(0);
    if ((initial >= '0' && initial <= '9') || initial == '-') {
        try {
            // if we want full Big Number support this block can be replaced with:
            // return stringToNumber(string);
            if (isDecimalNotation(string)) {
                Double d = Double.valueOf(string);
                if (!d.isInfinite() && !d.isNaN()) {
                    return d;
                }
            } else {
                Long myLong = Long.valueOf(string);
                if (string.equals(myLong.toString())) {
                    if (myLong.longValue() == myLong.intValue()) {
                        return Integer.valueOf(myLong.intValue());
                    }
                    return myLong;
                }
            }
        } catch (Exception ignore) {
        }
    }



回答3:


String str = BigDecimal.valueOf(Obj.getDouble("StringName")).toPlainString();


来源:https://stackoverflow.com/questions/8710450/how-to-prevent-jsonobject-from-json-jar-converts-decimal-numbers-string-into-dou

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!