json icon indicating copy to clipboard operation
json copied to clipboard

BigDecimal::INFINITY and BigDecimal::NAN to_json and as_json should error out similar to Float::INFINITY and Float::NAN

Open prathamesh-sonpatki opened this issue 8 years ago • 2 comments

Currently, Float::INFINITY and Float::NAN error out when we try to convert them into JSON representation using as_json or to_json based on the following code from /ruby/ext/json/generator.c

    if (!allow_nan) {
        if (isinf(value)) {
            fbuffer_free(buffer);
            rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
        } else if (isnan(value)) {
            fbuffer_free(buffer);
            rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
        }
    }

Should same treatment be applied to BigDecimal::INFINITY and BigDecimal::NAN?

Here is the RFC link which says that

Numeric values that cannot be represented as sequences of digits such as Infinity and NaN) are not permitted

https://www.ietf.org/rfc/rfc4627.txt

prathamesh-sonpatki avatar Nov 19 '16 02:11 prathamesh-sonpatki

Also related question: What is the purpose of this file - https://github.com/flori/json/blob/master/lib/json/add/bigdecimal.rb I see it was added for BigDecimal compatability but it is not used in Ruby for BigDecimal#to_json. The to_json call currently goes through Object#to_json.

prathamesh-sonpatki avatar Nov 19 '16 02:11 prathamesh-sonpatki

Sorry for the late reply.

Float values are generated as JSON litterals. NaN and INFINITY will either error, or if allow_nan: true is passed will be generated as NaN and INFINITY (note: no quotes or anything, these are not JSON strings).

This are not valid JSON and browsers will generate a parse error.

BigDecimal are generated very differently. First, you should require json/add/bigdecimal (documentation was much improved recently). Second, these are additions, so they will be valid JSON, but to round trip you will need to use the (unsafe!) options create_additions: true.

$ ruby -r json -r bigdecimal -r json/add/bigdecimal -e "puts JSON.generate([Float::INFINITY, BigDecimal::INFINITY], allow_nan: true)"
[Infinity,{"json_class":"BigDecimal","b":"9:Infinity"}]

$ ruby -r json -r bigdecimal -r json/add/bigdecimal -e 'p JSON.parse("[Infinity,{\"json_class\":\"BigDecimal\",\"b\":\"9:Infinity\"}]", allow_nan: true, create_additions: true)'
[Infinity, Infinity]  # First is Float::INFINITY, second is BigDecimal::INFINITY

HTH

This issue can be closed.

marcandre avatar Jun 30 '20 05:06 marcandre