Oj: Rails 6 (under Ruby 2.6.3): unexpected behaviour for Oj.dump

Created on 12 Jul 2019  路  9Comments  路  Source: ohler55/oj

When dumping a hash with symbol-keys, under Rails 6, they hash-keys have : and ":
(everything run under ruby 2.6.3)

Rails 5

test = {foo: "hello from rails #{Rails.version}"}
# => {:foo=>"hello from rails 5.2.3"}

Oj.dump(test)
# => "{\"foo\":\"hello from rails 5.2.3\"}"

Rails 6

test = {foo: "hello from rails #{Rails.version}"}
# => {:foo=>"hello from rails 6.0.0.rc1"}

Oj.dump(test)
# => "{\":foo\":\"hello from rails 6.0.0.rc1\"}"
# note the additional `:` infront of the foo-key

Why is this a problem? MD5 hashing is broken in Rails 6 (Rails 5 returns the same digest, i.e. 9bb58f26192e4ba00f01e2e7b136bbd8):

test_2 = {foo: 'bar'}
# => {:foo=>"bar"}

md5 = Digest::MD5.new
# => #<Digest::MD5: d41d8cd98f00b204e9800998ecf8427e>

md5 << Oj.dump(test_2)
# => #<Digest::MD5: ac1fce2974bc71a06a0f1aafe21672f7>

md5.to_s
# => "ac1fce2974bc71a06a0f1aafe21672f7"


md5_2 = Digest::MD5.new
# => #<Digest::MD5: d41d8cd98f00b204e9800998ecf8427e>

irb(main):063:0> md5_2 << Oj.dump(test_2.stringify_keys)
# => #<Digest::MD5: 9bb58f26192e4ba00f01e2e7b136bbd8>

md5_2.to_s
# => "9bb58f26192e4ba00f01e2e7b136bbd8"

Most helpful comment

I'm trying to reproduce it but I think I am making some bad assumptions. The default mode for Oj is :object mode. In that mode what you are seeing is expected. In :rails mode I don't see that behaviour. Can you check the Oj.default_options and see what the mode is? If it is not :compatible or :rails then I suspect the scaffolding does not include putting Oj into rails more. That is probably what you want.

All 9 comments

I'll have to look at this. It appears as if Rails 6 is monkey patching Symbol#to_s or something along those lines.

What is the status of this? Is it still an issue?

What is the status of this? Is it still an issue?

A quick test with rails 6.0.0 & ruby 2.6.4:

test = { foo: "hello from rails #{Rails.version}" }
# => {:foo=>"hello from rails 6.0.0"}

Oj.dump(test)
# => "{\":foo\":\"hello from rails 6.0.0\"}"

RUBY_VERSION
# => "2.6.4"

it still seems to be an issue.

To be honest there has been no progress. I'll try and get to it this week.

Can you tell me how you are setting up the test? What is required and what calls were made to set the Oj defaults?

I did not configure anything. Just scaffold a new rails (API mode) app and throw in Oj into the Gemfile, run bundle install, then enter the rails console. That's it. Btw. Oj.load(Oj.dump({ foo: "bar" })) works, i.e. Oj.load correctly resolves the JSON string "{\":foo\":\"bar\"\}"

I'm trying to reproduce it but I think I am making some bad assumptions. The default mode for Oj is :object mode. In that mode what you are seeing is expected. In :rails mode I don't see that behaviour. Can you check the Oj.default_options and see what the mode is? If it is not :compatible or :rails then I suspect the scaffolding does not include putting Oj into rails more. That is probably what you want.

Thanks! You are right. Oj.default_options.dig(:mode) returns :object. Most of my applications are still running on Rails 5.2.3, and for those, the mode is :compat by default (just adding the Oj gem to a rails application without further configuration as I did now for this Issue with Rails 6.0).

Reading about the existing issues with rails' ActiveSupport::JSON::Encoding vs. the JSON gem, I would tend to use :compat mode over :rails mode, but I didn't research much yet about how much of the implementation changed in Rails 6.

I've now added an initializer

# config/initializers/oj.rb

Oj.default_options = { mode: :compat }

which solves the problem; further reading on modes (for all the future readers): http://www.ohler.com/oj/doc/file.Options.html

Super, glad it was an easy fix. The whole Rails vs JSON gem for JSON handling is a mess. Oj attempts to get the behaviour right depending on which is in control but some edge cases pop up every now and then.

Good to close?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dgollahon picture dgollahon  路  5Comments

gottfrois picture gottfrois  路  13Comments

orien picture orien  路  18Comments

trevorrowe picture trevorrowe  路  3Comments

ohler55 picture ohler55  路  21Comments