Rails 3.1 has a serialize function that can take a custom column coder. A custom coder needs to have dump and load methods set, or else it will be recognized as a required type for the built-in YAML coder called YAMLColumn.

While the JSON class has the two required methods, it doesn’t allow specifying a default. So I created a custom coder. I don’t know where the best file and module locations to put the class in are, so I won’t include them here. This is the class, though:

class JSONColumn
  def initialize(default={})
    @default = default

  # this might be the database default and we should plan for empty strings or nils
  def load(s)
    s.present? ? JSON.load(s) : @default.clone

  # this should only be nil or an object that serializes to JSON (like a hash or array)
  def dump(o)
    JSON.dump(o || @default)

Since load and dump are instance methods, an instance of JSONColumn needs to be passed rather than the class. Here’s an example that works for me inside of the rails console:

class Person < ActiveRecord::Base
  validate :name, :pets, :presence => true
  serialize :pets, JSONColumn.new([])

Update: Added .clone to the load method. HT @miyagawa.