<- Back to blog

Rails adds support for typed json columns using has_json

Rails now supports typed schemas for json columns with has_json and has_delegated_json.

Vivek Patel

Vivek Patel

Rails adds support for typed json columns using has_json

We all use JSON columns in Rails. They are great for storing extra data like user preferences or vendor specific configuration that does not need its own column.

The downside is that JSON columns have no enforced schema and no types. You are responsible for casting values from forms, validating keys, and keeping the structure consistent. Until now, a JSON column was just a hash. If a form submits the string "true" for a boolean preference, Rails will happily store it without complaint.

A recent PR (#56258) introduced a new feature that helps to fix this using has_json and has_delegated_json.

Before

If you had a preferences JSON column, you usually treated it like a simple Ruby hash.

# Old way
user.preferences = { "theme" => "dark", "notifications" => "true", "language" => "en" }

This caused a few problems:

After

The new has_json allows you to define a schema for your JSON columns directly in your model, and Rails will handle defaults and type casting for you.

class User < ApplicationRecord
  has_json :preferences,
    theme: "light",       # Infers string, sets default to "light"
    notifications: true,  # Infers boolean, sets default to true
    language: :string     # Explicit type, no default
end

Now, interacting with this column is much simpler:

user = User.new

# Default values
user.preferences.theme           # => "light"
user.preferences.notifications?  # => true
user.preferences.language        # => nil

# Automatic casting
user.preferences.notifications = "false"
user.preferences.notifications?  # => false

# Bulk assignment
user.preferences = { "theme" => "dark", "notifications" => "true", "language" => "fr" }
user.preferences.theme           # => "dark"
user.preferences.notifications?  # => true
user.preferences.language        # => "fr"

If you don't want to type user.preferences.theme every time, you can use has_delegated_json instead.

Supported types and limitations

Currently, the feature supports three basic types:

As of the initial merge, nested structures are not supported. This feature is designed for flat key-value pairs within a JSON.

Resources:

Have a project that needs help? Get in touch with us today!

Schedule a free consultation with our experts. Let's build, scale, and optimize your web application to achieve your business goals.