123456789_123456789_123456789_123456789_123456789_

Module: Puma::JSON

Relationships & Source Files
Namespace Children
Exceptions:
Defined in: lib/puma/json.rb

Overview

::Puma deliberately avoids the use of the json gem and instead performs JSON serialization without any external dependencies. In a puma cluster, loading any gem into the puma master process means that operators cannot use a phased restart to upgrade their application if the new version of that application uses a different version of that gem. The json gem in particular is additionally problematic because it leverages native extensions. If the puma master process relies on a gem with native extensions and operators remove gems from disk related to old releases, subsequent phased restarts can fail.

The implementation of JSON serialization in this module is not designed to be particularly full-featured or fast. It just has to handle the few places where ::Puma relies on JSON serialization internally.

Constant Summary

Class Method Summary

Class Method Details

.generate(value)

[ GitHub ]

  
# File 'lib/puma/json.rb', line 29

def generate(value)
  StringIO.open do |io|
    serialize_value io, value
    io.string
  end
end

.serialize_object_key(output, value) (private)

[ GitHub ]

  
# File 'lib/puma/json.rb', line 86

def serialize_object_key(output, value)
  case value
  when Symbol, String
    serialize_string output, value.to_s
  else
    raise SerializationError, "Could not serialize object of type #{value.class} as object key"
  end
end

.serialize_string(output, value) (private)

[ GitHub ]

  
# File 'lib/puma/json.rb', line 71

def serialize_string(output, value)
  output << '"'
  output << value.gsub(CHAR_TO_ESCAPE) do |character|
    case character
    when BACKSLASH
      '\\\\'
    when QUOTE
      '\\"'
    when CONTROL_CHAR_TO_ESCAPE
      '\u%.4X' % character.ord
    end
  end
  output << '"'
end

.serialize_value(output, value) (private)

[ GitHub ]

  
# File 'lib/puma/json.rb', line 38

def serialize_value(output, value)
  case value
  when Hash
    output << '{'
    value.each_with_index do |(k, v), index|
      output << ',' if index != 0
      serialize_object_key output, k
      output << ':'
      serialize_value output, v
    end
    output << '}'
  when Array
    output << '['
    value.each_with_index do |member, index|
      output << ',' if index != 0
      serialize_value output, member
    end
    output << ']'
  when Integer, Float
    output << value.to_s
  when String
    serialize_string output, value
  when true
    output << 'true'
  when false
    output << 'false'
  when nil
    output << 'null'
  else
    raise SerializationError, "Unexpected value of type #{value.class}"
  end
end