JSON implementation for Ruby ↑

Description ↑

This is an implementation of the JSON specification according to RFC 7159 www.ietf.org/rfc/rfc7159.txt .

The JSON generator generate UTF-8 character sequences by default. If an :ascii_only option with a true value is given, they escape all non-ASCII and control characters with uXXXX escape sequences, and support UTF-16 surrogate pairs in order to be able to generate the whole range of unicode code points.

All strings, that are to be encoded as JSON strings, should be UTF-8 byte sequences on the Ruby side.

Installation ↑

Install the gem and add to the application’s Gemfile by executing:

$ bundle add json

If bundler is not being used to manage dependencies, install the gem by executing:

$ gem install json

Basic Usage ↑

To use JSON you can

require 'json'

Now you can parse a JSON document into a ruby data structure by calling

JSON.parse(document)

If you want to generate a JSON document from a ruby data structure call

JSON.generate(data)

You can also use the pretty_generate method (which formats the output more verbosely and nicely).

Casting non native types ↑

JSON documents can only support Hashes, Arrays, Strings, Integers and Floats.

By default if you attempt to serialize something else, JSON.generate will search for a to_json method on that object:

Position = Struct.new(:latitude, :longitude) do
  def to_json(state = nil, *)
    JSON::State.from_state(state).generate({
      latitude: latitude,
      longitude: longitude,
    })
  end
end

JSON.generate([
  Position.new(12323.234, 435345.233),
  Position.new(23434.676, 159435.324),
]) # => [{"latitude":12323.234,"longitude":435345.233},{"latitude":23434.676,"longitude":159435.324}]

If a to_json method isn’t defined on the object, JSON.generate will fallback to call to_s:

JSON.generate(Object.new) # => "#<Object:0x000000011e768b98>"

Both of these behavior can be disabled using the strict: true option:

JSON.generate(Object.new, strict: true) # => Object not allowed in JSON (JSON::GeneratorError)
JSON.generate(Position.new(1, 2), strict: true) # => Position not allowed in JSON (JSON::GeneratorError)

JSON::Coder ↑

Since to_json methods are global, it can sometimes be problematic if you need a given type to be serialized in different ways in different locations.

Instead it is recommended to use the newer JSON::Coder API:

module MyApp
  API_JSON_CODER = JSON::Coder.new do |object, is_object_key|
    case object
    when Time
      object.iso8601(3)
    else
      object
    end
  end
end

puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"

The provided block is called for all objects that don’t have a native JSON equivalent, and must return a Ruby object that has a native JSON equivalent.

It is also called for objects that do have a JSON equivalent, but are used as Hash keys, for instance { 1 => 2}, as well as for strings that aren’t valid UTF-8:

coder = JSON::Coder.new do |object, is_object_key|
  case object
  when String
    if !object.valid_encoding? || object.encoding != Encoding::UTF_8
      Base64.encode64(object)
    else
      object
    end
  else
    object
  end
end

Combining JSON fragments ↑

To combine JSON fragments into a bigger JSON document, you can use JSON::Fragment:

posts_json = cache.fetch_multi(post_ids) do |post_id|
  JSON.generate(Post.find(post_id))
end
posts_json.map! { |post_json| JSON::Fragment.new(post_json) }
JSON.generate({ posts: posts_json, count: posts_json.count })

Pretty Printing ↑

JSON.generate always creates the shortest possible string representation of a ruby data structure in one line. This is good for data storage or network protocols, but not so good for humans to read. Fortunately there’s also JSON.pretty_generate that creates a more readable output:

puts JSON.pretty_generate([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
 [
   1,
   2,
   {
     "a": 3.141
   },
   false,
   true,
   null,
   {
     "json_class": "Range",
     "data": [
       4,
       10,
       false
     ]
   }
 ]

Security ↑

When parsing or serializing untrusted input, parser and generator options should never be user controlled.

# Dangerous, DO NOT DO THIS.
JSON.generate(params[:data], params[:options])

Security vulnerability reports relying on attacker controlled parsing or generator options will be handled as regular bug fixes.

Development ↑

Prerequisites ↑

  1. Clone the repository

  2. Install dependencies with bundle install

Testing ↑

The full test suite can be run with:

bundle exec rake test

Release ↑

Update the lib/json/version.rb file.

rbenv shell 2.6.5
rake build
gem push pkg/json-2.3.0.gem

rbenv shell jruby-9.2.9.0
rake build
gem push pkg/json-2.3.0-java.gem

Author ↑

Florian Frank flori@ping.de

License ↑

Ruby License, see www.ruby-lang.org/en/about/license.txt.

Download ↑

The latest version of this library can be downloaded at

Online Documentation should be located at