# class JSON::PullParser

- JSON::PullParser
- Reference
- Object

##
Overview

This class allows you to consume JSON on demand, token by token.

Each read_* method consumes the next token. Sometimes it consumes only one token (like `#read_begin_array`), sometimes it consumes a full valid value (like `#read_array`).

You must be careful when calling those methods, as they move forward into the JSON input you are pulling. Calling `#read_string` twice will return the next two strings (if possible), not twice the same.

If you try to read a token which is not the one currently under the cursor location, an exception `ParseException` will be raised.

Example:

    input = %(
      {
        "type": "event",
        "values": [1, 4, "three", 10]
      }
    )
    pull = JSON::PullParser.new(input)
    pull.read_begin_object
    pull.read_object_key # => "type"
    pull.read_string     # => "event"
    # Actually you can also use `read_string` to read a key
    pull.read_string # => "values"
    pull.read_begin_array
    pull.read_int    # => 1
    pull.read_int    # => 4
    pull.read_string # => "three"
    pull.read_int    # => 10
    pull.read_end_array
    pull.read_end_object

Another example reading the same object:

    pull = JSON::PullParser.new(input)
    pull.read_object do |key|
      case key
      when "type"
        pull.read_string # => "event"
      when "values"
        pull.read_array do
          if v = pull.read?(Int8)
            v
          else
            pull.read_string
          end
        end
      end
    end

This example fails:

    pull = JSON::PullParser.new(input)
    pull.read_begin_object
    pull.read_object_key # => "type"
    pull.read_string     # => "event"
    pull.read_end_object # => raise an exception. The current token is a string ("values"), not the end of an object.

##
Defined in:

json/pull_parser.cr

##
Constructors

- .new(input)

  Creates a PullParser which will consume the JSON input.

##
Instance Method Summary

- #bool_value : Bool
- #column_number

  Returns the current column number.

- #float_value : Float64
- #int_value : Int64
- #kind : Kind
- #line_number

  Returns the current line number.

- #location : Tuple(Int32, Int32)

  Returns the current location.

- #max_nesting : Int32
- #max_nesting=(max_nesting : Int32)
- #on_key(key, & : self -> _)

  Reads an object keys and yield when key is found.

- #on_key!(key, & : self -> _)

  Reads an object keys and yield when key is found.

- #raise(message : String) : NoReturn

  Raises `ParseException` with message at current location.

- #raw_value : String
- #read?(klass : Bool.class) : Bool | Nil

  Reads a `Bool` value and returns it.

- #read?(klass : Int128.class) : Int128 | Nil

  Reads an `Int128` value and returns it.

- #read?(klass : Int16.class) : Int16 | Nil

  Reads an `Int16` value and returns it.

- #read?(klass : Int32.class) : Int32 | Nil

  Reads an `Int32` value and returns it.

- #read?(klass : Int64.class) : Int64 | Nil

  Reads an `Int64` value and returns it.

- #read?(klass : Int8.class) : Int8 | Nil

  Reads an `Int8` value and returns it.

- #read?(klass : UInt128.class) : UInt128 | Nil

  Reads an `UInt128` value and returns it.

- #read?(klass : UInt16.class) : UInt16 | Nil

  Reads an `UInt16` value and returns it.

- #read?(klass : UInt32.class) : UInt32 | Nil

  Reads an `UInt32` value and returns it.

- #read?(klass : UInt64.class) : UInt64 | Nil

  Reads an `UInt64` value and returns it.

- #read?(klass : UInt8.class) : UInt8 | Nil

  Reads an `UInt8` value and returns it.

- #read?(klass : Float32.class) : Float32 | Nil

  Reads an `Float32` value and returns it.

- #read?(klass : Float64.class) : Float64 | Nil

  Reads an `Float64` value and returns it.

- #read?(klass : String.class) : String | Nil

  Reads a `String` value and returns it.

- #read_array(&)

  Reads a whole array.

- #read_array_or_null(&)

  Reads an array or a null value, and returns it.

- #read_begin_array

  Reads the beginning of an array.

- #read_begin_object

  Reads the beginning of an object.

- #read_bool : Bool

  Reads a `Bool` value.

- #read_bool_or_null : Bool | Nil

  Reads a `Bool` or a null value, and returns it.

- #read_end_array

  Reads the end of an array.

- #read_end_object

  Reads the end of an object.

- #read_float : Float64

  Reads a float value.

- #read_float_or_null : Float64 | Nil

  Reads a float or a null value, and returns it.

- #read_int : Int64

  Reads an integer value.

- #read_int_or_null : Int64 | Nil

  Reads an integer or a null value, and returns it.

- #read_next : Kind

  Reads the next lexer's token.

- #read_null : Nil

  Reads a null value and returns it.

- #read_null? : Bool

  Reads the current token if its value is null.

- #read_null_or(&)

  Reads a null value and returns it, or executes the given block if the value is not null.

- #read_object(&)

  Reads a whole object.

- #read_object_key : String

  Reads an object's key and returns it.

- #read_object_or_null(&)

  Reads an object or a null value, and returns it.

- #read_raw(json) : Nil

  Reads the new value and fill the a JSON builder with it.

- #read_raw : String

  Read the next value and returns it.

- #read_string : String

  Reads a string and returns it.

- #read_string_or_null : String | Nil

  Reads a string or a null value, and returns it.

- #skip : Nil

  Skips the next value.

- #string_value : String

### Instance methods inherited from class `Reference`

==(other : self)
==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil) same?, to_s(io : IO) : Nil to_s

### Constructor methods inherited from class `Reference`

new new, unsafe_construct(address : Pointer, *args, **opts) : self unsafe_construct

### Class methods inherited from class `Reference`

pre_initialize(address : Pointer) pre_initialize

### Instance methods inherited from class `Object`

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

### Class methods inherited from class `Object`

from_json(string_or_io, root : String)
from_json(string_or_io) from_json, from_yaml(string_or_io : String | IO) from_yaml

### Macros inherited from class `Object`

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

##
Constructor Detail

def self.new(input) #

Creates a PullParser which will consume the JSON input.

input must be a `String` or an `IO`.

##
Instance Method Detail

def bool_value : Bool #
def column_number #

Returns the current column number.

def float_value : Float64 #
def int_value : Int64 #
def kind : Kind #
def line_number #

Returns the current line number.

def location : Tuple(Int32, Int32) #

Returns the current location.

The location is a tuple `{line number, column number}`.

def max_nesting : Int32 #
def max_nesting=(max_nesting : Int32) #
def on_key(key, & : self -> _) #

Reads an object keys and yield when key is found.

All the other object keys are skipped.

Returns the return value of the block or `Nil` if the key was not read.

def on_key!(key, & : self -> _) #

Reads an object keys and yield when key is found. If not found, raise an `Exception`.

All the other object keys are skipped.

Returns the return value of the block.

def raise(message : String) : NoReturn #

Raises `ParseException` with message at current location.

def raw_value : String #
def read?(klass : Bool.class) : Bool | Nil #

Reads a `Bool` value and returns it.

If the value is not a `Bool`, returns `nil`.

def read?(klass : Int128.class) : Int128 | Nil #

Reads an `Int128` value and returns it.

If the value is not an integer or does not fit in an `Int128`, it returns `nil`.

def read?(klass : Int16.class) : Int16 | Nil #

Reads an `Int16` value and returns it.

If the value is not an integer or does not fit in an `Int16`, it returns `nil`.

def read?(klass : Int32.class) : Int32 | Nil #

Reads an `Int32` value and returns it.

If the value is not an integer or does not fit in an `Int32`, it returns `nil`.

def read?(klass : Int64.class) : Int64 | Nil #

Reads an `Int64` value and returns it.

If the value is not an integer or does not fit in an `Int64`, it returns `nil`.

def read?(klass : Int8.class) : Int8 | Nil #

Reads an `Int8` value and returns it.

If the value is not an integer or does not fit in an `Int8`, it returns `nil`.

def read?(klass : UInt128.class) : UInt128 | Nil #

Reads an `UInt128` value and returns it.

If the value is not an integer or does not fit in an `UInt128`, it returns `nil`.

def read?(klass : UInt16.class) : UInt16 | Nil #

Reads an `UInt16` value and returns it.

If the value is not an integer or does not fit in an `UInt16`, it returns `nil`.

def read?(klass : UInt32.class) : UInt32 | Nil #

Reads an `UInt32` value and returns it.

If the value is not an integer or does not fit in an `UInt32`, it returns `nil`.

def read?(klass : UInt64.class) : UInt64 | Nil #

Reads an `UInt64` value and returns it.

If the value is not an integer or does not fit in an `UInt64`, it returns `nil`.

def read?(klass : UInt8.class) : UInt8 | Nil #

Reads an `UInt8` value and returns it.

If the value is not an integer or does not fit in an `UInt8`, it returns `nil`.

def read?(klass : Float32.class) : Float32 | Nil #

Reads an `Float32` value and returns it.

If the value is not an integer or does not fit in an `Float32`, it returns `nil`. If the value was actually an integer, it is converted to a float.

def read?(klass : Float64.class) : Float64 | Nil #

Reads an `Float64` value and returns it.

If the value is not an integer or does not fit in a `Float64` variable, it returns `nil`. If the value was actually an integer, it is converted to a float.

def read?(klass : String.class) : String | Nil #

Reads a `String` value and returns it.

If the value is not a `String`, returns `nil`.

def read_array(&) #

Reads a whole array.

It reads the beginning of the array, yield each value of the array, and reads the end of the array. You have to consumes the values, if any, so the pull parser does not fail when reading the end of the array.

If the array is empty, it does not yield.

def read_array_or_null(&) #

Reads an array or a null value, and returns it.

def read_begin_array #

Reads the beginning of an array.

def read_begin_object #

Reads the beginning of an object.

def read_bool : Bool #

Reads a `Bool` value.

def read_bool_or_null : Bool | Nil #

Reads a `Bool` or a null value, and returns it.

def read_end_array #

Reads the end of an array.

def read_end_object #

Reads the end of an object.

def read_float : Float64 #

Reads a float value.

If the value is actually an integer, it is converted to float.

def read_float_or_null : Float64 | Nil #

Reads a float or a null value, and returns it.

def read_int : Int64 #

Reads an integer value.

def read_int_or_null : Int64 | Nil #

Reads an integer or a null value, and returns it.

def read_next : Kind #

Reads the next lexer's token.

Contrary to `#read_raw`, it does not read a full value. For example if the next token is the beginning of an array, it will stop there, while `#read_raw` would have read the whole array.

def read_null : Nil #

Reads a null value and returns it.

def read_null? : Bool #

Reads the current token if its value is null.

Returns `true` if the token was read.

def read_null_or(&) #

Reads a null value and returns it, or executes the given block if the value is not null.

def read_object(&) #

Reads a whole object.

It reads the beginning of the object, yield each key and key location, and reads the end of the object. You have to consumes the values, if any, so the pull parser does not fail when reading the end of the object.

If the object is empty, it does not yield.

def read_object_key : String #

Reads an object's key and returns it.

def read_object_or_null(&) #

Reads an object or a null value, and returns it.

def read_raw(json) : Nil #

Reads the new value and fill the a JSON builder with it.

Use this method with a `JSON::Builder` to read a JSON while building another one.

def read_raw : String #

Read the next value and returns it.

The value is returned as a json string. If the value is an array or an object, it returns a string representing the full value. If the value in unknown, it raises a `ParseException`.

    pull = JSON::PullParser.new %([null, true, 1, "foo", [1, "two"], {"foo": "bar"}])
    pull.read_begin_array
    pull.read_raw # => "null"
    pull.read_raw # => "true"
    pull.read_raw # => "1"
    pull.read_raw # => "\"foo\""
    pull.read_raw # => "[1,\"two\"]"
    pull.read_raw # => "{\"foo\":\"bar\"}"
    pull.read_end_array

def read_string : String #

Reads a string and returns it.

def read_string_or_null : String | Nil #

Reads a string or a null value, and returns it.

def skip : Nil #

Skips the next value.

It skips the whole value, not only the next lexer's token. For example if the next value is an array, the whole array will be skipped.

def string_value : String #