Class: JSON::Pure::Parser

Inherits:
StringScanner
  • Object
show all
Defined in:
lib/json/pure/parser.rb

Overview

This class implements the JSON parser that is used to parse a JSON string into a Ruby data structure.

Constant Summary collapse

STRING =
/" ((?:[^\x0-\x1f"\\] |
     # escaped special characters:
    \\["\\\/bfnrt] |
    \\u[0-9a-fA-F]{4} |
     # match all but escaped special characters:
    \\[\x20-\x21\x23-\x2e\x30-\x5b\x5d-\x61\x63-\x65\x67-\x6d\x6f-\x71\x73\x75-\xff])*)
"/nx
INTEGER =
/(-?0|-?[1-9]\d*)/
FLOAT =
/(-?
(?:0|[1-9]\d*)
(?:
  \.\d+(?i:e[+-]?\d+) |
  \.\d+ |
  (?i:e[+-]?\d+)
)
)/x
NAN =
/NaN/
INFINITY =
/Infinity/
MINUS_INFINITY =
/-Infinity/
OBJECT_OPEN =
/\{/
OBJECT_CLOSE =
/\}/
ARRAY_OPEN =
/\[/
ARRAY_CLOSE =
/\]/
PAIR_DELIMITER =
/:/
COLLECTION_DELIMITER =
/,/
TRUE =
/true/
FALSE =
/false/
NULL =
/null/
IGNORE =
%r(
  (?:
   //[^\n\r]*[\n\r]| # line comments
   /\*               # c-style comments
   (?:
    [^*/]|        # normal chars
    /[^*]|        # slashes that do not start a nested comment
    \*[^/]|       # asterisks that do not end this comment
    /(?=\*/)      # single slash before this comment's end 
   )*
     \*/               # the End of this comment
     |[ \t\r\n]+       # whitespaces: space, horicontal tab, lf, cr
  )+
)mx
UNPARSED =
Object.new

Instance Method Summary collapse

Constructor Details

#initialize(source, opts = {}) ⇒ Parser

Creates a new JSON::Pure::Parser instance for the string source.

It will be configured by the opts hash. 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|nil|0, it defaults to 19.

  • 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, which is also the default.

  • create_additions: If set to false, the Parser doesn’t create additions even if a matchin class and create_id was found. This option defaults to true.

  • object_class: Defaults to Hash

  • array_class: Defaults to Array



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/json/pure/parser.rb', line 71

def initialize(source, opts = {})
  opts ||= {}
  if defined?(::Encoding)
    if source.encoding == ::Encoding::ASCII_8BIT
      b = source[0, 4].bytes.to_a
      source = case
               when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
                 source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
               when b.size >= 4 && b[0] == 0 && b[2] == 0
                 source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
               when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
                 source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)

               when b.size >= 4 && b[1] == 0 && b[3] == 0
                 source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
               else
                 source.dup
               end
    else
      source = source.encode(::Encoding::UTF_8)
    end
    source.force_encoding(::Encoding::ASCII_8BIT)
  else
    b = source
    source = case
             when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
               JSON.iconv('utf-8', 'utf-32be', b)
             when b.size >= 4 && b[0] == 0 && b[2] == 0
               JSON.iconv('utf-8', 'utf-16be', b)
             when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
               JSON.iconv('utf-8', 'utf-32le', b)
             when b.size >= 4 && b[1] == 0 && b[3] == 0
               JSON.iconv('utf-8', 'utf-16le', b)
             else
               b
             end
  end
  super source
  if !opts.key?(:max_nesting) # defaults to 19
    @max_nesting = 19
  elsif opts[:max_nesting]
    @max_nesting = opts[:max_nesting]
  else
    @max_nesting = 0
  end
  @allow_nan = !!opts[:allow_nan]
  @symbolize_names = !!opts[:symbolize_names]
  ca = true
  ca = opts[:create_additions] if opts.key?(:create_additions)
  @create_id = ca ? JSON.create_id : nil
  @object_class = opts[:object_class] || Hash
  @array_class = opts[:array_class] || Array
end

Instance Method Details

#parseObject

Parses the current JSON string source and returns the complete data structure as a result.



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/json/pure/parser.rb', line 129

def parse
  reset
  obj = nil
  until eos?
    case
    when scan(OBJECT_OPEN)
      obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
      @current_nesting = 1
      obj = parse_object
    when scan(ARRAY_OPEN)
      obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
      @current_nesting = 1
      obj = parse_array
    when skip(IGNORE)
      ;
    else
      raise ParserError, "source '#{peek(20)}' not in JSON!"
    end
  end
  obj or raise ParserError, "source did not contain any JSON!"
  obj
end