tson-rails

tson-rails renders Rails responses in the text format of TSON (Typed Schema Object Notation). It implements the schemaless data layer of the TSON 2026 revision 32 Text Data Format that is needed for Rails data output.

Installation

# Gemfile
gem "tson-rails"

After restarting the application, the gem registers application/tson and the .tn1 extension, and render tson: becomes available.

Rendering TSON from Rails

class UsersController < ApplicationController
  def index
    render tson: User.order(:id), pretty: true
  end
end

Example output:

[
  {
    id: 1
    name: Ada
    created_at: !datetime "2026-08-09T12:34:56.000000000+09:00"
  }
]

The renderer accepts the same Active Model serialization options as render json:.

render tson: @user, only: %i[id name], pretty: true

It also supports respond_to and MIME negotiation.

respond_to do |format|
  format.tson { render tson: User.all }
  format.json { render json: User.all }
end

The response Content-Type is application/tson; charset=utf-8.

Ruby API

The encoder can also be used without Rails.

require "tson_rails"

TsonRails.encode(
  id: 1,
  name: "Ada",
  active: true,
  tags: ["ruby", "rails"]
)
# => "{id:1,name:Ada,active:true,tags:[ruby,rails]}"

Encoding rules:

  • Hashes with String or Symbol keys are emitted as TSON records ({ key: value }).
  • Hashes with other key types are emitted as TSON maps ({ key => value }).
  • Arrays are emitted as TSON arrays ([value value]); compact output uses commas between values.
  • nil becomes null, Ruby dates and times become !date or !datetime, and BigDecimal values remain numeric.
  • TsonRails.absent becomes the TSON absent sentinel _, which is distinct from nil.
  • Objects that provide serializable_hash (including Active Record and Active Model objects) are materialized and encoded recursively.
TsonRails.encode({ id: 1, note: TsonRails.absent })
# => "{id:1,note:_}"

TsonRails.encode({ id: 1, note: TsonRails.absent }, omit_absent: true)
# => "{id:1}"

Output is compact by default. Pass pretty: true to enable newlines and indentation. To explicitly encode hashes as maps, pass hash_mode: :map.

Scope

This initial release is a TSON schemaless data-format encoder. It does not yet include TSON schema document loading, schema hash verification, automatic schema generation from type definitions, or a TSON parser. The specification is still a working draft, so compatibility should be reviewed when it is finalized as version 1.

Development

bundle install
bundle exec rake test

The implementation and tests are released under the MIT License.