Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
/ojPublic

Rails and ActiveSupport Notes#739

ohler55 started this conversation inGeneral
Jan 15, 2022· 2 comments· 2 replies
Discussion options

Please place notes about dealing with Rails and ActiveSupport in this discussion topic.

You must be logged in to vote

Replies: 2 comments 2 replies

Comment options

What is the main difference betweenOj.dump andOj::Rails.encode?

You must be logged in to vote
2 replies
@HeyNonster
Comment options

Oj.dump, using the default settings, will not return the same format that Rails'ActiveSupport will.

ActiveSupport::JSON.encode(Time.now.utc)                      => "2022-01-20T09:32:27.708Z"Oj.dump(Time.now.utc)                                         => {"^t":1642671147.709}

However,Oj::Rails.encode will mimic the format ofActiveSupport:

ActiveSupport::JSON.encode(Time.now.utc)                      => "2022-01-20T09:32:27.708Z"Oj::Rails.encode(Time.now.utc)                                => "2022-01-20T09:32:27.708Z"

But if you setOj withmode: :rails thenOj.dumpwill also mimicActiveSupport.

ActiveSupport::JSON.encode(Time.now.utc)                      => "2022-01-20T09:36:15.727Z"Oj.dump(Time.now.utc)                                         => "2022-01-20T09:36:15.727Z"

Basically, if you don't want to setmode: :rails but still wantOj to return the same format asActiveSupport then you can useOj::Rails.encode. I'm pretty sure that's how it works, at least.

@ohler55
Comment options

ohler55Jan 22, 2022
Maintainer Author

The interaction between Rails and the JSON gem can be somewhat unpredictable. Oj does it's best to reproduce that. As pointed outOj.dump is different than the ActiveSupport calls and different than the JSON gem although with the options set correctly it can give the same results. The options are the key.

Comment options

Hey, everyone, this write-up mostly relates to a caveat when usingOj version <= 3.10.0 withRails/ActiveSupport andOj.optimize_rails but may also provide insight into whatOj is doing under the hood if that's of interest.

TL/DR: InOj version <= 3.10.0 passing a time object toJSON.dump and passing a time object nested inside an array or hash toJSON.dump will not return the same time format. This is because of all the monkey patching that ActiveSupport does and was fixed inOj 3.10.1

Extended details below:

My understanding is that withOj.optimize_rails Oj will replaceJSON.dump &&ActiveSupport::JSON.encode with faster implementations written in C. WithoutOj.optimize_rails Oj will provide fastOj.dump methods but otherwise leave everything else alone.

Here's a demonstration with these Oj settings:Oj.default_options = { mode: :rails, trace: true } and withActiveSupport

# Oj version 3.10.0#JSON.dumpJSON.dump(Time.now.utc)=>"2022-01-11 12:17:36 UTC"# ActiveSupport::JSON.encodeActiveSupport::JSON.encode(Time.now.utc)=>"2022-01-11T12:17:36.614Z"# Oj.dump#0:      rails.c:1468:Oj:}: dump Time#0:      rails.c:517:Oj:>:   as_json Time#0:      rails.c:527:Oj:<:   as_json Time#0:      rails.c:1468:Oj:}: dump String#0:      rails.c:1479:Oj:{: dump String#0:      rails.c:1479:Oj:{: dump TimeOj.dump(Time.now.utc)=>"2022-01-11T12:17:36.614Z"

Notice above theOj.dump(Time.now.utc) line. Thetrace: true Oj option gives you a window into what Oj is doing and you can see here thatOj.dump utilizes the fast C code. Notably, the file israils.c. This is because we setmode: :rails in thedefault_options which tells Oj to render the JSON in the same format that ActiveSupport would.

Now, if we run the same code but addOj.optimize_rails:

# Oj version 3.10.0#JSON.dump#0:dump_compat.c:940:Oj:}: dump Time#0:dump_compat.c:965:Oj:{: dump TimeJSON.dump(Time.now.utc)=>"2022-01-11 12:27:17 UTC"# ActiveSupport::JSON.encode#0:      rails.c:1468:Oj:}: dump Time#0:      rails.c:1479:Oj:{: dump TimeActiveSupport::JSON.encode(Time.now.utc)=>"2022-01-11T12:27:17.051Z"# Oj.dump#0:      rails.c:1468:Oj:}: dump Time#0:      rails.c:1479:Oj:{: dump TimeOj.dump(Time.now.utc)=>"2022-01-11T12:27:17.051Z"

BothJSON.dump andActiveSupport::JSON.encode now run through faster C implementations.JSON.dump,
however runs through the filedump_compat.c instead ofrails.c. This is intended so thatJSON.dump with Oj andJSON.dumpwithout Oj return the same time format, the Oj implementation is just faster.

The bug inOj < 3.10.1 occured when you passed a Hash or Array with time objects toJSON.dump

# Oj version 3.10.0# JSON.dump#0:dump_compat.c:940:Oj:}: dump Hash#0:dump_compat.c:940:Oj:}:   dump Time#0:dump_compat.c:123:Oj:>: to_json Time#0:      rails.c:1468:Oj:}: dump Time#0:      rails.c:1479:Oj:{: dump Time#0:dump_compat.c:131:Oj:<: to_json Time#0:dump_compat.c:965:Oj:{:   dump Time#0:dump_compat.c:965:Oj:{: dump HashJSON.dump({created_at:Time.now.utc})=>{"created_at":"2022-01-11T12:27:16.966Z"}

As you can see in the trace,JSON.dump({created_at: Time.now.utc}) was running the code through bothdump_compat.candrails.c and returning the Time in the ActiveSupport format when it was supposed to return the same format that the JSON standard library gem would.

This was fixed inOj 3.10.1 as you can see in the below trace:

# Oj version 3.10.1# JSON.dump#0:dump_compat.c:941:Oj:}: dump Hash#0:dump_compat.c:941:Oj:}:   dump Time#0:dump_compat.c:123:Oj:>: to_json Time#0:dump_compat.c:131:Oj:<: to_json Time#0:dump_compat.c:966:Oj:{:   dump Time#0:dump_compat.c:966:Oj:{: dump HashJSON.dump({created_at:Time.now.utc})=>{"created_at":"2022-01-11 12:34:36 UTC"}

JSON.dump({created_at: Time.now.utc}) now exclusively uses thedump_compat.c file which was the intended behavior. Unfortunately, we had some code that relied on the time format produced by the buggy version of JSON.dump and that broke some things when we upgraded Oj.

Because Oj has to mimic the JSON standard library gem time format and, separately, mimic the ActiveSupport time format (both of which Oj has no control over, it just needs to adapt) we might write a test that catches whenever one the formats change.

You must be logged in to vote
0 replies
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Category
General
Labels
None yet
3 participants
@ohler55@HeyNonster@RamilGN

[8]ページ先頭

©2009-2025 Movatter.jp