ohler55 / oj

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

Default options changing after generating json #730

Closed kukicola closed 9 months ago

kukicola commented 2 years ago

Hello Please take a look at code below, for some reason mode before calling Oj.generate is :object but it becomes :compatafterwards (other options change as well). I assume it's not the desired behavior? Version: 3.13.10

irb(main):001:0> require 'oj'
=> true
irb(main):002:0> Oj.default_options
=> 
{:indent=>0,
 :second_precision=>9,
 :circular=>false,
 :class_cache=>true,
 :auto_define=>false,
 :symbol_keys=>false,
 :bigdecimal_as_decimal=>nil,
 :create_additions=>false,
 :use_to_json=>false,
 :use_to_hash=>false,
 :use_as_json=>false,
 :use_raw_json=>false,
 :nilnil=>false,
 :empty_string=>true,
 :allow_gc=>true,
 :quirks_mode=>true,
 :allow_invalid_unicode=>false,
 :allow_nan=>true,
 :trace=>false,
 :safe=>false,
 :float_precision=>16,
 :cache_str=>0,
 :ignore_under=>false,
 :cache_keys=>true,
 :mode=>:object,
 :integer_range=>nil,
 :escape_mode=>:json,
 :time_format=>:unix,
 :bigdecimal_load=>:auto,
 :compat_bigdecimal=>false,
 :create_id=>"json_class",
 :space=>nil,
 :space_before=>nil,
 :object_nl=>nil,
 :array_nl=>nil,
 :nan=>:auto,
 :omit_nil=>false,
 :hash_class=>nil,
 :array_class=>nil,
 :ignore=>nil}
irb(main):003:0> Oj.generate({a: 1})
=> "{\"a\":1}"
irb(main):004:0> Oj.default_options
=> 
{:indent=>0,
 :second_precision=>3,
 :circular=>false,
 :class_cache=>false,
 :auto_define=>false,
 :symbol_keys=>false,
 :bigdecimal_as_decimal=>false,
 :create_additions=>false,
 :use_to_json=>true,
 :use_to_hash=>false,
 :use_as_json=>false,
 :use_raw_json=>false,
 :nilnil=>false,
 :empty_string=>false,
 :allow_gc=>true,
 :quirks_mode=>true,
 :allow_invalid_unicode=>true,
 :allow_nan=>false,
 :trace=>false,
 :safe=>false,
 :float_precision=>0,
 :cache_str=>0,
 :ignore_under=>false,
 :cache_keys=>true,
 :mode=>:compat,
 :integer_range=>nil,
 :escape_mode=>:unicode_xss,
 :time_format=>:ruby,
 :bigdecimal_load=>:auto,
 :compat_bigdecimal=>false,
 :create_id=>"json_class",
 :space=>nil,
 :space_before=>nil,
 :object_nl=>nil,
 :array_nl=>nil,
 :nan=>:raise,
 :omit_nil=>false,
 :hash_class=>nil,
 :array_class=>nil,
 :ignore=>nil}
ohler55 commented 2 years ago

The default options should not be changed. Looks like a bug.

ohler55 commented 2 years ago

I looked into it a bit more. Sadly the observed behaviour is correct. The Oj.generate call is meant to act like the JSON gem but the JSON gem relies on objects having a to_json method and using the JSON gem to encode. That requires Oj to set the global defaults.

I realized that was a problem when parsing so the Oj::Parser was created. I have not done the write or encode counterpart to that yet though.

Bottom line is that I'd have to agree that it is a bug but at a fundamental level to mimc the JSON gem. The fix is to implement an Oj::Encoder module where options are contained in the encoder. Then that encoder would be used instead of the global calls. What do you think?

kukicola commented 2 years ago

Hello, sorry for the delayed response. I don't know much about Oj internals so it's really hard for me to tell but it seems like a reasonable solution. Anyway, in my case, I just switched to Oj.dump with some additional options to avoid any unexpected behavior

ohler55 commented 2 years ago

Thanks for letting me know. The plans for an Encoder are still in the works anyway.