Project

wankel

0.0
Low commit activity in last 3 years
No release in over a year
A JSON parser that enables streaming parsing and encoding of JSON
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

Wankel

Wankel

Wankel is a Ruby gem that provides C bindings to the YAJL 2 C Library.

Wankel provides gerneral parsing and encoding to and from JSON, but also a streaming parser and encoder.

Features

  • Streaming JSON parsing and encoding
  • JSON parsing and encoding directly to and from an IO stream (file, socket, etc) or String.
  • Parse and encode multiple JSON objects to and from streams or strings continuously.
  • JSON gem compatibility API - allows wankel to be used as a drop-in replacement for the JSON gem

Dependencies

Wankel only dependency is YAJL version 2.

You can install it with homebrew via:

brew install yajl

Installation

Wankel is installed via Rubygems:

gem install wankel

Examples

Simple Usage

Wankel.parse('{"key": "value"}')
# => {"key" => "value"}

Wankel.encode({"key" => "value"})
# => '{"key":"value"}'

Streaming Parser Example

class SimpleParser < Wankel::StreamParser
  def on_array_start
    puts "Array start"
  end
  def on_string(string)
    puts string
  end
end

parser = SimpleParser.new
parser.parse('["string1", null, "string2"]')
# => "Array start"
# => "string1"
# => "string2"

Streaming Encoder Example

output = StringIO.new
encoder = Wankel::StreamEncoder.new(output)
encoder.map_open
encoder.string("key")
encoder.number(123)
encoder.string("type")
encoder.value("value-determined-by-method")
encoder.map_close
encoder.flush
output.string # => '{"key":123,"type":"value-determined-by-method"}'

Parsing Options

  • :symbolize_keys (Default: false)

    make Hash keys into Ruby symbols

    Wankel.parse('{"key": "value"}', :symbolize_keys => true)
    # => {:key => "value"}
  • :allow_comments (Default: false)

    Ignore javascript style comments in JSON input.

    Wankel.parse('{"key": /*comment*/ "value"}', :allow_comments => false)
    # => Wankel::ParseError
    
    Wankel.parse('{"key": /*comment*/ "value"}', :allow_comments => true)
    # => {"key" => "value"}
  • :validate_utf8 (Default: false)

    Verify that all strings in JSON input are valid UTF8 emit a parse error if this is not so. This option makes parsing slightly more expensive.

    Wankel.parse("[\"\x81\x83\"]", :validate_utf8 => false)
    # => ["\x81\x83"]
    
    Wankel.parse("[\"\x81\x83\"]", :validate_utf8 => true)
    # => Wankel::ParseError
  • :allow_trailing_garbage (Default: false)

    Ensure the entire input text was consumed and raise an error otherwise

    Wankel.parse('{"key": "value"}gar', :allow_trailing_garbage => false)
    # => Wankel::ParseError
    
    Wankel.parse('{"key": "value"}gar', :allow_trailing_garbage => true)
    # => {"key" => "value"}
  • :multiple_values (Default: false)

    Allow multiple values to be parsed by a single parser. The entire text must be valid JSON, and values can be seperated by any kind of whitespace

    Wankel.parse('{"abc": 123}{"def": 456}')
    # => Wankel::ParseError
    
    Wankel.parse('{"abc": 123}{"def": 456}', :multiple_values => true)
    # => [{"abc"=>123}, {"def"=>456}]
    
    Wankel.parse('{"abc": 123}{"def": 456}', :multiple_values => true) do |obj|
        puts obj
    end
    # => {"abc"=>123}
    # => {"def"=>456}
  • :allow_partial_values (Default: false)

    TODO

  • :read_buffer_size (Default: 8092)

    The read buffer size in bytes when reading from an IO Object.

Encoding Options

  • :beautify (Default: false)

    Generate indented (beautiful) output.

    Wankel.encode({"key" => "value"}, :beautify => true)
    # => "{\n    \"key\": \"value\"\n}\n"
  • :indent_string (Default: " ", four spaces)

    The indent string which is used when :beautify is enabled

    Wankel.encode({"key" => "value"}, :beautify => true, :indent_string => "\t")
    # => "{\n\t\"key\": \"value\"\n}\n"
  • :validate_utf8 (Default: false)

    Validate that the strings are valid UTF8.

    Wankel.encode(["#{"\201\203"}"], :validate_utf8 => false)
    # => "[\"#{"\201\203"}\"]"
    
    Wankel.encode(["#{"\201\203"}"], :validate_utf8 => true)
    # => Wankel::EncodeError
  • :escape_solidus (Default: false)

    The forward solidus (slash or '/' in human) is not required to be escaped in json text. By default, YAJL will not escape it in the iterest of saving bytes. Setting this flag will cause YAJL to always escape '/' in generated JSON strings.

    Wankel.encode("/", :escape_solidus => false)
    # => '"/"'
    
    Wankel.encode("/", :escape_solidus => true)
    # => '"\/"'
  • :write_buffer_size

    The write buffer size in bytes before writing to the IO object or String.

Performance Comparisons

TODO:

General Encoder

The test description (ie. Small: 100,000 parses of a 255 byte JSON):

Gem Parse Time Rate Ratio
Wankel N seconds N.NK parses/sec N.N
OJ N seconds N.NK parses/sec N.N
Yajl N seconds N.NK parses/sec N.N
JSON::Ext N seconds N.NK parses/sec N.N

General Decoder

Streaming Encoder

class Wankel::SaxEncoder

  def number
  end

  def string
  end

  def null
  end

  def bool
  end

  def map_open
  end

  def map_close
  end

  def array_open
  end

  def array_close
  end

  def value
  end

  def complete
  end

end

Streaming Decoder

class Wankel::SaxParser

  def on_map_start
    puts 'start map'
  end

  def on_map_end
    puts 'end map'
  end

  def on_map_key(key)
    puts 'key'
  end

  def on_null
    puts "null"
  end

  def on_boolean(value)
    puts value
  end

  def on_integer(i)
    puts "integer"
  end

  def on_double(d)
    puts "double"
  end

  def on_string(s)
    puts "string"
  end

  def on_array_start
    puts "start array"
  end

  def on_array_end
    puts "end array"
  end

end