summaryrefslogtreecommitdiff
path: root/ext/json/lib
diff options
context:
space:
mode:
Diffstat (limited to 'ext/json/lib')
-rw-r--r--ext/json/lib/json.rb62
-rw-r--r--ext/json/lib/json/add/bigdecimal.rb28
-rw-r--r--ext/json/lib/json/add/complex.rb28
-rw-r--r--ext/json/lib/json/add/core.rb11
-rw-r--r--ext/json/lib/json/add/date.rb34
-rw-r--r--ext/json/lib/json/add/date_time.rb50
-rw-r--r--ext/json/lib/json/add/exception.rb31
-rw-r--r--ext/json/lib/json/add/ostruct.rb31
-rw-r--r--ext/json/lib/json/add/range.rb29
-rw-r--r--ext/json/lib/json/add/rational.rb27
-rw-r--r--ext/json/lib/json/add/regexp.rb30
-rw-r--r--ext/json/lib/json/add/struct.rb30
-rw-r--r--ext/json/lib/json/add/symbol.rb25
-rw-r--r--ext/json/lib/json/add/time.rb38
-rw-r--r--ext/json/lib/json/common.rb484
-rw-r--r--ext/json/lib/json/ext.rb21
-rw-r--r--ext/json/lib/json/generic_object.rb62
-rw-r--r--ext/json/lib/json/version.rb8
18 files changed, 1029 insertions, 0 deletions
diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb
new file mode 100644
index 0000000000..24aa385c91
--- /dev/null
+++ b/ext/json/lib/json.rb
@@ -0,0 +1,62 @@
+require 'json/common'
+
+##
+# = JavaScript Object Notation (JSON)
+#
+# JSON is a lightweight data-interchange format. It is easy for us
+# humans to read and write. Plus, equally simple for machines to generate or parse.
+# JSON is completely language agnostic, making it the ideal interchange format.
+#
+# Built on two universally available structures:
+# 1. A collection of name/value pairs. Often referred to as an _object_, hash table, record, struct, keyed list, or associative array.
+# 2. An ordered list of values. More commonly called an _array_, vector, sequence or list.
+#
+# To read more about JSON visit: http://json.org
+#
+# == Parsing JSON
+#
+# To parse a JSON string received by another application or generated within
+# your existing application:
+#
+# require 'json'
+#
+# my_hash = JSON.parse('{"hello": "goodbye"}')
+# puts my_hash["hello"] => "goodbye"
+#
+# Notice the extra quotes <tt>''</tt> around the hash notation. Ruby expects
+# the argument to be a string and can't convert objects like a hash or array.
+#
+# Ruby converts your string into a hash
+#
+# == Generating JSON
+#
+# Creating a JSON string for communication or serialization is
+# just as simple.
+#
+# require 'json'
+#
+# my_hash = {:hello => "goodbye"}
+# puts JSON.generate(my_hash) => "{\"hello\":\"goodbye\"}"
+#
+# Or an alternative way:
+#
+# require 'json'
+# puts {:hello => "goodbye"}.to_json => "{\"hello\":\"goodbye\"}"
+#
+# <tt>JSON.generate</tt> only allows objects or arrays to be converted
+# to JSON syntax. <tt>to_json</tt>, however, accepts many Ruby classes
+# even though it acts only as a method for serialization:
+#
+# require 'json'
+#
+# 1.to_json => "1"
+#
+module JSON
+ require 'json/version'
+
+ begin
+ require 'json/ext'
+ rescue LoadError
+ require 'json/pure'
+ end
+end
diff --git a/ext/json/lib/json/add/bigdecimal.rb b/ext/json/lib/json/add/bigdecimal.rb
new file mode 100644
index 0000000000..0ef69f12e0
--- /dev/null
+++ b/ext/json/lib/json/add/bigdecimal.rb
@@ -0,0 +1,28 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+defined?(::BigDecimal) or require 'bigdecimal'
+
+class BigDecimal
+ # Import a JSON Marshalled object.
+ #
+ # method used for JSON marshalling support.
+ def self.json_create(object)
+ BigDecimal._load object['b']
+ end
+
+ # Marshal the object to JSON.
+ #
+ # method used for JSON marshalling support.
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'b' => _dump,
+ }
+ end
+
+ # return the JSON value
+ def to_json(*)
+ as_json.to_json
+ end
+end
diff --git a/ext/json/lib/json/add/complex.rb b/ext/json/lib/json/add/complex.rb
new file mode 100644
index 0000000000..3d653bb50d
--- /dev/null
+++ b/ext/json/lib/json/add/complex.rb
@@ -0,0 +1,28 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+defined?(::Complex) or require 'complex'
+
+class Complex
+
+ # Deserializes JSON string by converting Real value <tt>r</tt>, imaginary
+ # value <tt>i</tt>, to a Complex object.
+ def self.json_create(object)
+ Complex(object['r'], object['i'])
+ end
+
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'r' => real,
+ 'i' => imag,
+ }
+ end
+
+ # Stores class name (Complex) along with real value <tt>r</tt> and imaginary value <tt>i</tt> as JSON string
+ def to_json(*)
+ as_json.to_json
+ end
+end
diff --git a/ext/json/lib/json/add/core.rb b/ext/json/lib/json/add/core.rb
new file mode 100644
index 0000000000..77d9dc0b20
--- /dev/null
+++ b/ext/json/lib/json/add/core.rb
@@ -0,0 +1,11 @@
+# This file requires the implementations of ruby core's custom objects for
+# serialisation/deserialisation.
+
+require 'json/add/date'
+require 'json/add/date_time'
+require 'json/add/exception'
+require 'json/add/range'
+require 'json/add/regexp'
+require 'json/add/struct'
+require 'json/add/symbol'
+require 'json/add/time'
diff --git a/ext/json/lib/json/add/date.rb b/ext/json/lib/json/add/date.rb
new file mode 100644
index 0000000000..4288237db1
--- /dev/null
+++ b/ext/json/lib/json/add/date.rb
@@ -0,0 +1,34 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+require 'date'
+
+# Date serialization/deserialization
+class Date
+
+ # Deserializes JSON string by converting Julian year <tt>y</tt>, month
+ # <tt>m</tt>, day <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> to Date.
+ def self.json_create(object)
+ civil(*object.values_at('y', 'm', 'd', 'sg'))
+ end
+
+ alias start sg unless method_defined?(:start)
+
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'y' => year,
+ 'm' => month,
+ 'd' => day,
+ 'sg' => start,
+ }
+ end
+
+ # Stores class name (Date) with Julian year <tt>y</tt>, month <tt>m</tt>, day
+ # <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/date_time.rb b/ext/json/lib/json/add/date_time.rb
new file mode 100644
index 0000000000..5ea42ea656
--- /dev/null
+++ b/ext/json/lib/json/add/date_time.rb
@@ -0,0 +1,50 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+require 'date'
+
+# DateTime serialization/deserialization
+class DateTime
+
+ # Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>,
+ # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
+ # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> to DateTime.
+ def self.json_create(object)
+ args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
+ of_a, of_b = object['of'].split('/')
+ if of_b and of_b != '0'
+ args << Rational(of_a.to_i, of_b.to_i)
+ else
+ args << of_a
+ end
+ args << object['sg']
+ civil(*args)
+ end
+
+ alias start sg unless method_defined?(:start)
+
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'y' => year,
+ 'm' => month,
+ 'd' => day,
+ 'H' => hour,
+ 'M' => min,
+ 'S' => sec,
+ 'of' => offset.to_s,
+ 'sg' => start,
+ }
+ end
+
+ # Stores class name (DateTime) with Julian year <tt>y</tt>, month <tt>m</tt>,
+ # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
+ # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
+
+
diff --git a/ext/json/lib/json/add/exception.rb b/ext/json/lib/json/add/exception.rb
new file mode 100644
index 0000000000..e6ad257abf
--- /dev/null
+++ b/ext/json/lib/json/add/exception.rb
@@ -0,0 +1,31 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+# Exception serialization/deserialization
+class Exception
+
+ # Deserializes JSON string by constructing new Exception object with message
+ # <tt>m</tt> and backtrace <tt>b</tt> serialized with <tt>to_json</tt>
+ def self.json_create(object)
+ result = new(object['m'])
+ result.set_backtrace object['b']
+ result
+ end
+
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'm' => message,
+ 'b' => backtrace,
+ }
+ end
+
+ # Stores class name (Exception) with message <tt>m</tt> and backtrace array
+ # <tt>b</tt> as JSON string
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/ostruct.rb b/ext/json/lib/json/add/ostruct.rb
new file mode 100644
index 0000000000..da81e107a7
--- /dev/null
+++ b/ext/json/lib/json/add/ostruct.rb
@@ -0,0 +1,31 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+require 'ostruct'
+
+# OpenStruct serialization/deserialization
+class OpenStruct
+
+ # Deserializes JSON string by constructing new Struct object with values
+ # <tt>v</tt> serialized by <tt>to_json</tt>.
+ def self.json_create(object)
+ new(object['t'] || object[:t])
+ end
+
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ klass = self.class.name
+ klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
+ {
+ JSON.create_id => klass,
+ 't' => table,
+ }
+ end
+
+ # Stores class name (OpenStruct) with this struct's values <tt>v</tt> as a
+ # JSON string.
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/range.rb b/ext/json/lib/json/add/range.rb
new file mode 100644
index 0000000000..e61e553cdb
--- /dev/null
+++ b/ext/json/lib/json/add/range.rb
@@ -0,0 +1,29 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+# Range serialization/deserialization
+class Range
+
+ # Deserializes JSON string by constructing new Range object with arguments
+ # <tt>a</tt> serialized by <tt>to_json</tt>.
+ def self.json_create(object)
+ new(*object['a'])
+ end
+
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'a' => [ first, last, exclude_end? ]
+ }
+ end
+
+ # Stores class name (Range) with JSON array of arguments <tt>a</tt> which
+ # include <tt>first</tt> (integer), <tt>last</tt> (integer), and
+ # <tt>exclude_end?</tt> (boolean) as JSON string.
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/rational.rb b/ext/json/lib/json/add/rational.rb
new file mode 100644
index 0000000000..ee39c20e8d
--- /dev/null
+++ b/ext/json/lib/json/add/rational.rb
@@ -0,0 +1,27 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+defined?(::Rational) or require 'rational'
+
+class Rational
+ # Deserializes JSON string by converting numerator value <tt>n</tt>,
+ # denominator value <tt>d</tt>, to a Rational object.
+ def self.json_create(object)
+ Rational(object['n'], object['d'])
+ end
+
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'n' => numerator,
+ 'd' => denominator,
+ }
+ end
+
+ # Stores class name (Rational) along with numerator value <tt>n</tt> and denominator value <tt>d</tt> as JSON string
+ def to_json(*)
+ as_json.to_json
+ end
+end
diff --git a/ext/json/lib/json/add/regexp.rb b/ext/json/lib/json/add/regexp.rb
new file mode 100644
index 0000000000..2fcbb6fb14
--- /dev/null
+++ b/ext/json/lib/json/add/regexp.rb
@@ -0,0 +1,30 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+# Regexp serialization/deserialization
+class Regexp
+
+ # Deserializes JSON string by constructing new Regexp object with source
+ # <tt>s</tt> (Regexp or String) and options <tt>o</tt> serialized by
+ # <tt>to_json</tt>
+ def self.json_create(object)
+ new(object['s'], object['o'])
+ end
+
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 'o' => options,
+ 's' => source,
+ }
+ end
+
+ # Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt>
+ # (Regexp or String) as JSON string
+ def to_json(*)
+ as_json.to_json
+ end
+end
diff --git a/ext/json/lib/json/add/struct.rb b/ext/json/lib/json/add/struct.rb
new file mode 100644
index 0000000000..6847cde99b
--- /dev/null
+++ b/ext/json/lib/json/add/struct.rb
@@ -0,0 +1,30 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+# Struct serialization/deserialization
+class Struct
+
+ # Deserializes JSON string by constructing new Struct object with values
+ # <tt>v</tt> serialized by <tt>to_json</tt>.
+ def self.json_create(object)
+ new(*object['v'])
+ end
+
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ klass = self.class.name
+ klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
+ {
+ JSON.create_id => klass,
+ 'v' => values,
+ }
+ end
+
+ # Stores class name (Struct) with Struct values <tt>v</tt> as a JSON string.
+ # Only named structs are supported.
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/add/symbol.rb b/ext/json/lib/json/add/symbol.rb
new file mode 100644
index 0000000000..03dc9a56a5
--- /dev/null
+++ b/ext/json/lib/json/add/symbol.rb
@@ -0,0 +1,25 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+# Symbol serialization/deserialization
+class Symbol
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ {
+ JSON.create_id => self.class.name,
+ 's' => to_s,
+ }
+ end
+
+ # Stores class name (Symbol) with String representation of Symbol as a JSON string.
+ def to_json(*a)
+ as_json.to_json(*a)
+ end
+
+ # Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol
+ def self.json_create(o)
+ o['s'].to_sym
+ end
+end
diff --git a/ext/json/lib/json/add/time.rb b/ext/json/lib/json/add/time.rb
new file mode 100644
index 0000000000..d9834677ac
--- /dev/null
+++ b/ext/json/lib/json/add/time.rb
@@ -0,0 +1,38 @@
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+# Time serialization/deserialization
+class Time
+
+ # Deserializes JSON string by converting time since epoch to Time
+ def self.json_create(object)
+ if usec = object.delete('u') # used to be tv_usec -> tv_nsec
+ object['n'] = usec * 1000
+ end
+ if method_defined?(:tv_nsec)
+ at(object['s'], Rational(object['n'], 1000))
+ else
+ at(object['s'], object['n'] / 1000)
+ end
+ end
+
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+ def as_json(*)
+ nanoseconds = [ tv_usec * 1000 ]
+ respond_to?(:tv_nsec) and nanoseconds << tv_nsec
+ nanoseconds = nanoseconds.max
+ {
+ JSON.create_id => self.class.name,
+ 's' => tv_sec,
+ 'n' => nanoseconds,
+ }
+ end
+
+ # Stores class name (Time) with number of seconds since epoch and number of
+ # microseconds for Time as JSON string
+ def to_json(*args)
+ as_json.to_json(*args)
+ end
+end
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
new file mode 100644
index 0000000000..f44184e138
--- /dev/null
+++ b/ext/json/lib/json/common.rb
@@ -0,0 +1,484 @@
+require 'json/version'
+require 'json/generic_object'
+
+module JSON
+ class << self
+ # If _object_ is string-like, parse the string and return the parsed result
+ # as a Ruby data structure. Otherwise generate a JSON text from the Ruby
+ # data structure object and return it.
+ #
+ # The _opts_ argument is passed through to generate/parse respectively. See
+ # generate and parse for their documentation.
+ def [](object, opts = {})
+ if object.respond_to? :to_str
+ JSON.parse(object.to_str, opts)
+ else
+ JSON.generate(object, opts)
+ end
+ end
+
+ # Returns the JSON parser class that is used by JSON. This is either
+ # JSON::Ext::Parser or JSON::Pure::Parser.
+ attr_reader :parser
+
+ # Set the JSON parser class _parser_ to be used by JSON.
+ def parser=(parser) # :nodoc:
+ @parser = parser
+ remove_const :Parser if JSON.const_defined_in?(self, :Parser)
+ const_set :Parser, parser
+ end
+
+ # Return the constant located at _path_. The format of _path_ has to be
+ # either ::A::B::C or A::B::C. In any case, A has to be located at the top
+ # level (absolute namespace path?). If there doesn't exist a constant at
+ # the given path, an ArgumentError is raised.
+ def deep_const_get(path) # :nodoc:
+ path.to_s.split(/::/).inject(Object) do |p, c|
+ case
+ when c.empty? then p
+ when JSON.const_defined_in?(p, c) then p.const_get(c)
+ else
+ begin
+ p.const_missing(c)
+ rescue NameError => e
+ raise ArgumentError, "can't get const #{path}: #{e}"
+ end
+ end
+ end
+ end
+
+ # Set the module _generator_ to be used by JSON.
+ def generator=(generator) # :nodoc:
+ old, $VERBOSE = $VERBOSE, nil
+ @generator = generator
+ generator_methods = generator::GeneratorMethods
+ for const in generator_methods.constants
+ klass = deep_const_get(const)
+ modul = generator_methods.const_get(const)
+ klass.class_eval do
+ instance_methods(false).each do |m|
+ m.to_s == 'to_json' and remove_method m
+ end
+ include modul
+ end
+ end
+ self.state = generator::State
+ const_set :State, self.state
+ const_set :SAFE_STATE_PROTOTYPE, State.new
+ const_set :FAST_STATE_PROTOTYPE, State.new(
+ :indent => '',
+ :space => '',
+ :object_nl => "",
+ :array_nl => "",
+ :max_nesting => false
+ )
+ const_set :PRETTY_STATE_PROTOTYPE, State.new(
+ :indent => ' ',
+ :space => ' ',
+ :object_nl => "\n",
+ :array_nl => "\n"
+ )
+ ensure
+ $VERBOSE = old
+ end
+
+ # Returns the JSON generator module that is used by JSON. This is
+ # either JSON::Ext::Generator or JSON::Pure::Generator.
+ attr_reader :generator
+
+ # Returns the JSON generator state class that is used by JSON. This is
+ # either JSON::Ext::Generator::State or JSON::Pure::Generator::State.
+ attr_accessor :state
+
+ # This is create identifier, which is used to decide if the _json_create_
+ # hook of a class should be called. It defaults to 'json_class'.
+ attr_accessor :create_id
+ end
+ self.create_id = 'json_class'
+
+ NaN = 0.0/0
+
+ Infinity = 1.0/0
+
+ MinusInfinity = -Infinity
+
+ # The base exception for JSON errors.
+ class JSONError < StandardError
+ def self.wrap(exception)
+ obj = new("Wrapped(#{exception.class}): #{exception.message.inspect}")
+ obj.set_backtrace exception.backtrace
+ obj
+ end
+ end
+
+ # This exception is raised if a parser error occurs.
+ class ParserError < JSONError; end
+
+ # This exception is raised if the nesting of parsed data structures is too
+ # deep.
+ class NestingError < ParserError; end
+
+ # :stopdoc:
+ class CircularDatastructure < NestingError; end
+ # :startdoc:
+
+ # This exception is raised if a generator or unparser error occurs.
+ class GeneratorError < JSONError; end
+ # For backwards compatibility
+ UnparserError = GeneratorError
+
+ # This exception is raised if the required unicode support is missing on the
+ # system. Usually this means that the iconv library is not installed.
+ class MissingUnicodeSupport < JSONError; end
+
+ module_function
+
+ # Parse the JSON document _source_ into a Ruby data structure and return it.
+ #
+ # _opts_ can have the following
+ # keys:
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
+ # structures. Disable depth checking with :max_nesting => false. It defaults
+ # to 100.
+ # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
+ # to false.
+ # * *symbolize_names*: If set to true, returns symbols for the names
+ # (keys) in a JSON object. Otherwise strings are returned. Strings are
+ # the default.
+ # * *create_additions*: If set to false, the Parser doesn't create
+ # additions even if a matching class and create_id was found. This option
+ # defaults to false.
+ # * *object_class*: Defaults to Hash
+ # * *array_class*: Defaults to Array
+ def parse(source, opts = {})
+ Parser.new(source, opts).parse
+ end
+
+ # Parse the JSON document _source_ into a Ruby data structure and return it.
+ # The bang version of the parse method defaults to the more dangerous values
+ # for the _opts_ hash, so be sure only to parse trusted _source_ documents.
+ #
+ # _opts_ can have the following keys:
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
+ # structures. Enable depth checking with :max_nesting => anInteger. The parse!
+ # methods defaults to not doing max depth checking: This can be dangerous
+ # if someone wants to fill up your stack.
+ # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
+ # defiance of RFC 4627 to be parsed by the Parser. This option defaults
+ # to true.
+ # * *create_additions*: If set to false, the Parser doesn't create
+ # additions even if a matching class and create_id was found. This option
+ # defaults to false.
+ def parse!(source, opts = {})
+ opts = {
+ :max_nesting => false,
+ :allow_nan => true
+ }.update(opts)
+ Parser.new(source, opts).parse
+ end
+
+ # Generate a JSON document from the Ruby data structure _obj_ and return
+ # it. _state_ is * a JSON::State object,
+ # * or a Hash like object (responding to to_hash),
+ # * an object convertible into a hash by a to_h method,
+ # that is used as or to configure a State object.
+ #
+ # It defaults to a state object, that creates the shortest possible JSON text
+ # in one line, checks for circular data structures and doesn't allow NaN,
+ # Infinity, and -Infinity.
+ #
+ # A _state_ hash can have the following keys:
+ # * *indent*: a string used to indent levels (default: ''),
+ # * *space*: a string that is put after, a : or , delimiter (default: ''),
+ # * *space_before*: a string that is put before a : pair delimiter (default: ''),
+ # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
+ # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
+ # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
+ # generated, otherwise an exception is thrown if these values are
+ # encountered. This options defaults to false.
+ # * *max_nesting*: The maximum depth of nesting allowed in the data
+ # structures from which JSON is to be generated. Disable depth checking
+ # with :max_nesting => false, it defaults to 100.
+ #
+ # See also the fast_generate for the fastest creation method with the least
+ # amount of sanity checks, and the pretty_generate method for some
+ # defaults for pretty output.
+ def generate(obj, opts = nil)
+ if State === opts
+ state, opts = opts, nil
+ else
+ state = SAFE_STATE_PROTOTYPE.dup
+ end
+ if opts
+ if opts.respond_to? :to_hash
+ opts = opts.to_hash
+ elsif opts.respond_to? :to_h
+ opts = opts.to_h
+ else
+ raise TypeError, "can't convert #{opts.class} into Hash"
+ end
+ state = state.configure(opts)
+ end
+ state.generate(obj)
+ end
+
+ # :stopdoc:
+ # I want to deprecate these later, so I'll first be silent about them, and
+ # later delete them.
+ alias unparse generate
+ module_function :unparse
+ # :startdoc:
+
+ # Generate a JSON document from the Ruby data structure _obj_ and return it.
+ # This method disables the checks for circles in Ruby objects.
+ #
+ # *WARNING*: Be careful not to pass any Ruby data structures with circles as
+ # _obj_ argument because this will cause JSON to go into an infinite loop.
+ def fast_generate(obj, opts = nil)
+ if State === opts
+ state, opts = opts, nil
+ else
+ state = FAST_STATE_PROTOTYPE.dup
+ end
+ if opts
+ if opts.respond_to? :to_hash
+ opts = opts.to_hash
+ elsif opts.respond_to? :to_h
+ opts = opts.to_h
+ else
+ raise TypeError, "can't convert #{opts.class} into Hash"
+ end
+ state.configure(opts)
+ end
+ state.generate(obj)
+ end
+
+ # :stopdoc:
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
+ alias fast_unparse fast_generate
+ module_function :fast_unparse
+ # :startdoc:
+
+ # Generate a JSON document from the Ruby data structure _obj_ and return it.
+ # The returned document is a prettier form of the document returned by
+ # #unparse.
+ #
+ # The _opts_ argument can be used to configure the generator. See the
+ # generate method for a more detailed explanation.
+ def pretty_generate(obj, opts = nil)
+ if State === opts
+ state, opts = opts, nil
+ else
+ state = PRETTY_STATE_PROTOTYPE.dup
+ end
+ if opts
+ if opts.respond_to? :to_hash
+ opts = opts.to_hash
+ elsif opts.respond_to? :to_h
+ opts = opts.to_h
+ else
+ raise TypeError, "can't convert #{opts.class} into Hash"
+ end
+ state.configure(opts)
+ end
+ state.generate(obj)
+ end
+
+ # :stopdoc:
+ # I want to deprecate these later, so I'll first be silent about them, and later delete them.
+ alias pretty_unparse pretty_generate
+ module_function :pretty_unparse
+ # :startdoc:
+
+ class << self
+ # The global default options for the JSON.load method:
+ # :max_nesting: false
+ # :allow_nan: true
+ # :quirks_mode: true
+ attr_accessor :load_default_options
+ end
+ self.load_default_options = {
+ :max_nesting => false,
+ :allow_nan => true,
+ :quirks_mode => true,
+ :create_additions => true,
+ }
+
+ # Load a ruby data structure from a JSON _source_ and return it. A source can
+ # either be a string-like object, an IO-like object, or an object responding
+ # to the read method. If _proc_ was given, it will be called with any nested
+ # Ruby object as an argument recursively in depth first order. To modify the
+ # default options pass in the optional _options_ argument as well.
+ #
+ # BEWARE: This method is meant to serialise data from trusted user input,
+ # like from your own database server or clients under your control, it could
+ # be dangerous to allow untrusted users to pass JSON sources into it. The
+ # default options for the parser can be changed via the load_default_options
+ # method.
+ #
+ # This method is part of the implementation of the load/dump interface of
+ # Marshal and YAML.
+ def load(source, proc = nil, options = {})
+ opts = load_default_options.merge options
+ if source.respond_to? :to_str
+ source = source.to_str
+ elsif source.respond_to? :to_io
+ source = source.to_io.read
+ elsif source.respond_to?(:read)
+ source = source.read
+ end
+ if opts[:quirks_mode] && (source.nil? || source.empty?)
+ source = 'null'
+ end
+ result = parse(source, opts)
+ recurse_proc(result, &proc) if proc
+ result
+ end
+
+ # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
+ def recurse_proc(result, &proc)
+ case result
+ when Array
+ result.each { |x| recurse_proc x, &proc }
+ proc.call result
+ when Hash
+ result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc }
+ proc.call result
+ else
+ proc.call result
+ end
+ end
+
+ alias restore load
+ module_function :restore
+
+ class << self
+ # The global default options for the JSON.dump method:
+ # :max_nesting: false
+ # :allow_nan: true
+ # :quirks_mode: true
+ attr_accessor :dump_default_options
+ end
+ self.dump_default_options = {
+ :max_nesting => false,
+ :allow_nan => true,
+ :quirks_mode => true,
+ }
+
+ # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
+ # the result.
+ #
+ # If anIO (an IO-like object or an object that responds to the write method)
+ # was given, the resulting JSON is written to it.
+ #
+ # If the number of nested arrays or objects exceeds _limit_, an ArgumentError
+ # exception is raised. This argument is similar (but not exactly the
+ # same!) to the _limit_ argument in Marshal.dump.
+ #
+ # The default options for the generator can be changed via the
+ # dump_default_options method.
+ #
+ # This method is part of the implementation of the load/dump interface of
+ # Marshal and YAML.
+ def dump(obj, anIO = nil, limit = nil)
+ if anIO and limit.nil?
+ anIO = anIO.to_io if anIO.respond_to?(:to_io)
+ unless anIO.respond_to?(:write)
+ limit = anIO
+ anIO = nil
+ end
+ end
+ opts = JSON.dump_default_options
+ opts = opts.merge(:max_nesting => limit) if limit
+ result = generate(obj, opts)
+ if anIO
+ anIO.write result
+ anIO
+ else
+ result
+ end
+ rescue JSON::NestingError
+ raise ArgumentError, "exceed depth limit"
+ end
+
+ # Swap consecutive bytes of _string_ in place.
+ def self.swap!(string) # :nodoc:
+ 0.upto(string.size / 2) do |i|
+ break unless string[2 * i + 1]
+ string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
+ end
+ string
+ end
+
+ # Shortcut for iconv.
+ if ::String.method_defined?(:encode)
+ # Encodes string using Ruby's _String.encode_
+ def self.iconv(to, from, string)
+ string.encode(to, from)
+ end
+ else
+ require 'iconv'
+ # Encodes string using _iconv_ library
+ def self.iconv(to, from, string)
+ Iconv.conv(to, from, string)
+ end
+ end
+
+ if ::Object.method(:const_defined?).arity == 1
+ def self.const_defined_in?(modul, constant)
+ modul.const_defined?(constant)
+ end
+ else
+ def self.const_defined_in?(modul, constant)
+ modul.const_defined?(constant, false)
+ end
+ end
+end
+
+module ::Kernel
+ private
+
+ # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
+ # one line.
+ def j(*objs)
+ objs.each do |obj|
+ puts JSON::generate(obj, :allow_nan => true, :max_nesting => false)
+ end
+ nil
+ end
+
+ # Outputs _objs_ to STDOUT as JSON strings in a pretty format, with
+ # indentation and over many lines.
+ def jj(*objs)
+ objs.each do |obj|
+ puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
+ end
+ nil
+ end
+
+ # If _object_ is string-like, parse the string and return the parsed result as
+ # a Ruby data structure. Otherwise, generate a JSON text from the Ruby data
+ # structure object and return it.
+ #
+ # The _opts_ argument is passed through to generate/parse respectively. See
+ # generate and parse for their documentation.
+ def JSON(object, *args)
+ if object.respond_to? :to_str
+ JSON.parse(object.to_str, args.first)
+ else
+ JSON.generate(object, args.first)
+ end
+ end
+end
+
+# Extends any Class to include _json_creatable?_ method.
+class ::Class
+ # Returns true if this class can be used to create an instance
+ # from a serialised JSON string. The class has to implement a class
+ # method _json_create_ that expects a hash as first parameter. The hash
+ # should include the required data.
+ def json_creatable?
+ respond_to?(:json_create)
+ end
+end
diff --git a/ext/json/lib/json/ext.rb b/ext/json/lib/json/ext.rb
new file mode 100644
index 0000000000..c5f813181d
--- /dev/null
+++ b/ext/json/lib/json/ext.rb
@@ -0,0 +1,21 @@
+if ENV['SIMPLECOV_COVERAGE'].to_i == 1
+ require 'simplecov'
+ SimpleCov.start do
+ add_filter "/tests/"
+ end
+end
+require 'json/common'
+
+module JSON
+ # This module holds all the modules/classes that implement JSON's
+ # functionality as C extensions.
+ module Ext
+ require 'json/ext/parser'
+ require 'json/ext/generator'
+ $DEBUG and warn "Using Ext extension for JSON."
+ JSON.parser = Parser
+ JSON.generator = Generator
+ end
+
+ JSON_LOADED = true unless defined?(::JSON::JSON_LOADED)
+end
diff --git a/ext/json/lib/json/generic_object.rb b/ext/json/lib/json/generic_object.rb
new file mode 100644
index 0000000000..3a14f0ea7d
--- /dev/null
+++ b/ext/json/lib/json/generic_object.rb
@@ -0,0 +1,62 @@
+require 'ostruct'
+
+module JSON
+ class GenericObject < OpenStruct
+ class << self
+ alias [] new
+
+ def json_creatable?
+ @json_creatable
+ end
+
+ attr_writer :json_creatable
+
+ def json_create(data)
+ data = data.dup
+ data.delete JSON.create_id
+ self[data]
+ end
+
+ def from_hash(object)
+ case
+ when object.respond_to?(:to_hash)
+ result = new
+ object.to_hash.each do |key, value|
+ result[key] = from_hash(value)
+ end
+ result
+ when object.respond_to?(:to_ary)
+ object.to_ary.map { |a| from_hash(a) }
+ else
+ object
+ end
+ end
+
+ def load(source, proc = nil, opts = {})
+ result = ::JSON.load(source, proc, opts.merge(:object_class => self))
+ result.nil? ? new : result
+ end
+
+ def dump(obj, *args)
+ ::JSON.dump(obj, *args)
+ end
+ end
+ self.json_creatable = false
+
+ def to_hash
+ table
+ end
+
+ def |(other)
+ self.class[other.to_hash.merge(to_hash)]
+ end
+
+ def as_json(*)
+ { JSON.create_id => self.class.name }.merge to_hash
+ end
+
+ def to_json(*a)
+ as_json.to_json(*a)
+ end
+ end
+end
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
new file mode 100644
index 0000000000..47cdcd607c
--- /dev/null
+++ b/ext/json/lib/json/version.rb
@@ -0,0 +1,8 @@
+module JSON
+ # JSON version
+ VERSION = '1.8.1'
+ VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
+ VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
+ VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
+ VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
+end