Managed to consistently reproduce this on:
Fun fact: Ruby 2.7.7 - fixes the issue.
As well does upgrading to Rails 6.1+. So appears strictly with such set of versions.
Let's get straight to business.
To consistently reproduce and understand that you have the problem, open Rails console and test the next:
[User.first, User.last].to_json
=>
"[\"#<User:0x00007fbb497fad30>\",\"#<User:0x00007fbb5001df20>\"]"
{ test: User.limit(2).to_json }.to_json
=>
"{\"test\":\"#<User::ActiveRecord_Relation:0x00007fc0228b7d08>\"}"
If you see such output - unluckily you have this problem, but that's not a tragedy ;)
Issues that I met in field-tested conditions, and somebody could find them typical for their project & useful for reproducing/debugging/testing process:
if you have any API endpoints with render json: { user: user }
syntax
jbuilder views, which use the next definition json.(@user, :id, :profile)
or some non-serialized ActiveRecord object e.g. json.profile @user.profile
all scenarios, when you try to explicitly convert to json any Object inside Enumerable classes (you can grep-search all .to_json usages)
payload = [
<ActionController::Parameters {"user"=>{"profile"=>1}} permitted: false>
1,
2
].to_json
JSON.parse(payload)
=>
[
String (instead of Hash),
1,
2
]
Solution:
# config/initializers/monkey_patches.rb
# TODO: Remove after upgrade to Rails 6.1+. JSON serialization of Objects works fine there
# Source: https://stackoverflow.com/questions/66871265/to-json-on-activerecord-object-ruby-3-0
module ActiveSupport
module FixBrokenJsonSerialization
def to_json(options = nil)
return ::ActiveSupport::JSON.encode(self) if options.is_a?(::JSON::Ext::Generator::State)
super(options)
end
end
end
Object.prepend(ActiveSupport::FixBrokenJsonSerialization)
NB. It's not a silver bullet, it's a monkey-patch, what is always risky and bad.
Better solution would be to migrate to Rails 6.1 or degrade to Ruby 2.7.7 (the last one is actually pretty annoying).
In case you need exactly these versions - Please, also, make sure that you don't have any libraries with heavy JSON logic or relying in any way to JSON::Ext::Generator::State
.
Other than that fact - should help to repair most of places at once