ohler55 / oj

Optimized JSON
http://www.ohler.com/oj
MIT License
3.12k stars 250 forks source link

How do you get Oj to dump a big decimal as a number not in scientific notation? #917

Closed pjb3 closed 3 months ago

pjb3 commented 3 months ago

Shouldn't this output the value as a number, not a string?

$ irb -r oj
>> puts(Oj.dump({ price: BigDecimal("1.25") }, mode: :compat, bigdecimal_as_decimal: true))
{"price":"0.125e1"}
=> nil
>> Oj::VERSION
=> "3.16.3"
>> RUBY_VERSION
=> "3.3.0"

And also, how do I get it to output it as {"price": 1.25} and not {"price": 0.125e1}?

ohler55 commented 3 months ago

You control that with the options. Check out the :bigdecimal_as_decimal option.

pjb3 commented 3 months ago

@ohler55 But in that code I posted above I'm passing bigdecimal_as_decimal as true to that call to dump, right? Shouldn't that make it output as a number and not a string?

pjb3 commented 3 months ago

Setting it as a default option doesn't seem to be working either:

$  irb -r oj
>> Oj.default_options = { mode: :compat, bigdecimal_as_decimal: true }
=> {:mode=>:compat, :bigdecimal_as_decimal=>true}
>> puts(Oj.dump({ price: BigDecimal("1.25") }))
{"price":"0.125e1"}
ohler55 commented 3 months ago

Right but you also specified :compat which overrides : bigdecimal_as_decimal since the behavior of the JSON gem is to emit a string.

pjb3 commented 3 months ago

ah, ok but then without that there is a colon in the name of the key:

>> puts(Oj.dump({ price: BigDecimal("1.25") }, bigdecimal_as_decimal: true ))
{":price":0.125e1}

How do I get rid of that? And also is there a way to get it to output 1.25 instead of 0.125e1?

ohler55 commented 3 months ago

Try the other modes. :custom should be more friendly. As for getting BigDecimal to emit non-scientific I'm not sure. That's really a characteristic of BigDecimal.

pjb3 commented 3 months ago

Ok, this seems to work:

$ irb -r oj
>> class BigDecimal; def to_json(*); to_f.to_s; end; end
=> :to_json
>> puts(Oj.dump({ price: BigDecimal("1.25") }, mode: :compat))
{"price":1.25}
ohler55 commented 3 months ago

That would work, yes.

pjb3 commented 3 months ago

:+1: