yajl-ruby-1.4.3/ 0000755 0000041 0000041 00000000000 14246427314 013474 5 ustar www-data www-data yajl-ruby-1.4.3/.rspec 0000644 0000041 0000041 00000000040 14246427314 014603 0 ustar www-data www-data --format documentation
--colour
yajl-ruby-1.4.3/README.md 0000644 0000041 0000041 00000030241 14246427314 014753 0 ustar www-data www-data # YAJL C Bindings for Ruby
This gem is a C binding to the excellent YAJL JSON parsing and generation library.
You can read more info at the project's website http://lloyd.github.com/yajl or check out its code at http://github.com/lloyd/yajl.
## Features
* JSON parsing and encoding directly to and from an IO stream (file, socket, etc) or String. Compressed stream parsing and encoding supported for Bzip2, Gzip and Deflate.
* Parse and encode *multiple* JSON objects to and from streams or strings continuously.
* JSON gem compatibility API - allows yajl-ruby to be used as a drop-in replacement for the JSON gem
* Basic HTTP client (only GET requests supported for now) which parses JSON directly off the response body *as it's being received*
* ~3.5x faster than JSON.generate
* ~1.9x faster than JSON.parse
* ~4.5x faster than YAML.load
* ~377.5x faster than YAML.dump
* ~1.5x faster than Marshal.load
* ~2x faster than Marshal.dump
## How to install
Go ahead and install it as usual:
```
gem install yajl-ruby
```
Or use your Gemfile:
``` ruby
gem 'yajl-ruby', require: 'yajl'
```
## Example of use
NOTE: I'm building up a collection of small examples in the examples (http://github.com/brianmario/yajl-ruby/tree/master/examples) folder.
First, you're probably gonna want to require it:
``` ruby
require 'yajl'
```
### Parsing
Then maybe parse some JSON from:
a File IO
``` ruby
json = File.new('test.json', 'r')
parser = Yajl::Parser.new
hash = parser.parse(json)
```
or maybe a StringIO
``` ruby
json = StringIO.new("...some JSON...")
parser = Yajl::Parser.new
hash = parser.parse(json)
```
or maybe STDIN
```
cat someJsonFile.json | ruby -ryajl -e "puts Yajl::Parser.parse(STDIN).inspect"
```
Or lets say you didn't have access to the IO object that contained JSON data, but instead
only had access to chunks of it at a time. No problem!
(Assume we're in an EventMachine::Connection instance)
``` ruby
def post_init
@parser = Yajl::Parser.new(:symbolize_keys => true)
end
def object_parsed(obj)
puts "Sometimes one pays most for the things one gets for nothing. - Albert Einstein"
puts obj.inspect
end
def connection_completed
# once a full JSON object has been parsed from the stream
# object_parsed will be called, and passed the constructed object
@parser.on_parse_complete = method(:object_parsed)
end
def receive_data(data)
# continue passing chunks
@parser << data
end
```
Or if you don't need to stream it, it'll just return the built object from the parse when it's done.
NOTE: if there are going to be multiple JSON strings in the input, you *must* specify a block or callback as this
is how yajl-ruby will hand you (the caller) each object as it's parsed off the input.
``` ruby
obj = Yajl::Parser.parse(str_or_io)
```
Or how about a JSON API HTTP request?
This actually makes a request using a raw TCPSocket, then parses the JSON body right off the socket. While it's being received over the wire!
``` ruby
require 'uri'
require 'yajl/http_stream'
url = URI.parse("http://search.twitter.com/search.json?q=engineyard")
results = Yajl::HttpStream.get(url)
```
Or do the same request, with Gzip and Deflate output compression support (also supports Bzip2, if loaded):
(this does the same raw socket Request, but transparently parses the compressed response body)
``` ruby
require 'uri'
require 'yajl/gzip'
require 'yajl/deflate'
require 'yajl/http_stream'
url = URI.parse("http://search.twitter.com/search.json?q=engineyard")
results = Yajl::HttpStream.get(url)
```
Since yajl-ruby parses JSON as a stream, supporting APIs like Twitter's Streaming API are a piece-of-cake.
You can simply supply a block to `Yajl::HttpStream.get`, which is used as the callback for when a JSON object has been
unserialized off the stream. For the case of this Twitter Streaming API call, the callback gets fired a few times a second (depending on your connection speed).
The code below is all that's needed to make the request and stream unserialized Ruby hashes off the response, continuously.
You'll note that I've enabled the :symbolize_keys parser option as well. Doing so is much more efficient for parsing JSON streams with
lots of repetitive keys - for things like result sets or multiple API requests - than the same parse with string keys.
This is because Ruby will reuse (and never GC) its symbol table. Be that as it may, if you want to parse JSON strings with random key names
it's much better to leave string keys enabled (the default), so they can get GC'd later.
``` ruby
require 'uri'
require 'yajl/http_stream'
uri = URI.parse("http://#{username}:#{password}@stream.twitter.com/spritzer.json")
Yajl::HttpStream.get(uri, :symbolize_keys => true) do |hash|
puts hash.inspect
end
```
Or how about parsing directly from a compressed file?
``` ruby
require 'yajl/bzip2'
file = File.new('some.json.bz2', 'r')
result = Yajl::Bzip2::StreamReader.parse(file)
```
### Encoding
Since yajl-ruby does everything using streams, you simply need to pass the object to encode, and the IO to write the stream to (this happens in chunks).
This allows you to encode JSON as a stream, writing directly to a socket
``` ruby
socket = TCPSocket.new('192.168.1.101', 9000)
hash = {:foo => 12425125, :bar => "some string", ... }
Yajl::Encoder.encode(hash, socket)
```
Or what if you wanted to compress the stream over the wire?
``` ruby
require 'yajl/gzip'
socket = TCPSocket.new('192.168.1.101', 9000)
hash = {:foo => 12425125, :bar => "some string", ... }
Yajl::Gzip::StreamWriter.encode(hash, socket)
```
Or what about encoding multiple objects to JSON over the same stream?
This example will encode and send 50 JSON objects over the same stream, continuously.
``` ruby
socket = TCPSocket.new('192.168.1.101', 9000)
encoder = Yajl::Encoder.new
50.times do
hash = {:current_time => Time.now.to_f, :foo => 12425125}
encoder.encode(hash, socket)
end
```
Using `EventMachine` and you want to encode and send in chunks?
(Assume we're in an `EventMachine::Connection` instance)
``` ruby
def post_init
# Passing a :terminator character will let us determine when the encoder
# is done encoding the current object
@encoder = Yajl::Encoder.new
motd_contents = File.read("/path/to/motd.txt")
status = File.read("/path/to/huge/status_file.txt")
@motd = {:motd => motd_contents, :system_status => status}
end
def connection_completed
# The encoder will do its best to hand you data in chunks that
# are around 8kb (but you may see some that are larger)
#
# It should be noted that you could have also assigned the _on_progress_ callback
# much like you can assign the _on_parse_complete_ callback with the parser class.
# Passing a block (like below) essentially tells the encoder to use that block
# as the callback normally assigned to _on_progress_.
#
# Send our MOTD and status
@encoder.encode(@motd) do |chunk|
if chunk.nil? # got our terminator, encoding is done
close_connection_after_writing
else
send_data(chunk)
end
end
end
```
But to make things simple, you might just want to let yajl-ruby do all the hard work for you and just hand back
a string when it's finished. In that case, just don't provide and IO or block (or assign the on_progress callback).
``` ruby
str = Yajl::Encoder.encode(obj)
```
You can also use `Yajl::Bzip2::StreamWriter` and `Yajl::Deflate::StreamWriter`. So you can pick whichever fits your CPU/bandwidth sweet-spot.
### HTML Safety
If you plan on embedding the output from the encoder in the DOM, you'll want to make sure you use the html_safe option on the encoder. This will escape all '/' characters to ensure no closing tags can be injected, preventing XSS.
Meaning the following should be perfectly safe:
``` html
", :html_safe => true) %>;
```
## JSON gem Compatibility API
The JSON gem compatibility API isn't enabled by default. You have to explicitly require it like so:
``` ruby
require 'yajl/json_gem'
```
That's right, you can just replace `"require 'json'"` with the line above and you're done!
This will require yajl-ruby itself, as well as enable its JSON gem compatibility API.
This includes the following API:
JSON.parse, JSON.generate, JSON.pretty_generate, JSON.load, JSON.dump
and all of the #to_json instance method overrides for Ruby's primitive objects
Once the compatibility API is enabled, your existing or new project should work as if the JSON gem itself were being used. Only you'll be using Yajl ;)
There are a lot more possibilities that I'd love to see other gems/plugins for someday.
Some ideas:
* parsing logs in JSON format
* a Rails plugin - DONE! (http://github.com/technoweenie/yajl-rails)
* official support in Rails 3 - DONE (http://github.com/rails/rails/commit/a96bf4ab5e73fccdafb78b99e8a122cc2172b505)
* and is the default (if installed) - http://github.com/rails/rails/commit/63bb955a99eb46e257655c93dd64e86ebbf05651
* Rack middleware (ideally the JSON body could be handed to the parser while it's still being received, this is apparently possible with Unicorn)
* JSON API clients (http://github.com/brianmario/freckle-api)
## Benchmarks
After I finished implementation - this library performs close to the same as the current JSON.parse (C gem) does on small/medium files.
But on larger files, and higher amounts of iteration, this library was around 2x faster than JSON.parse.
The main benefit of this library is in its memory usage.
Since it's able to parse the stream in chunks, its memory requirements are very, very low.
Here's what parsing a 2.43MB JSON file off the filesystem 20 times looks like:
### Memory Usage
#### Average
* Yajl::Parser#parse: 32MB
* JSON.parse: 54MB
* ActiveSupport::JSON.decode: 63MB
#### Peak
* Yajl::Parser#parse: 32MB
* JSON.parse: 57MB
* ActiveSupport::JSON.decode: 67MB
### Parse Time
* Yajl::Parser#parse: 4.54s
* JSON.parse: 5.47s
* ActiveSupport::JSON.decode: 64.42s
### Encode Time
* Yajl::Encoder#encode: 3.59s
* JSON#to_json: 6.2s
* ActiveSupport::JSON.encode: 45.58s
### Compared to YAML
NOTE: I converted the 2.4MB JSON file to YAML for this test.
#### Parse Time (from their respective formats)
* Yajl::Parser#parse: 4.33s
* JSON.parse: 5.37s
* YAML.load: 19.47s
#### Encode Time (to their respective formats)
* Yajl::Encoder#encode: 3.47s
* JSON#to_json: 6.6s
* YAML.dump(obj, io): 1309.93s
### Compared to Marshal.load/Marshal.dump
NOTE: I converted the 2.4MB JSON file to a Hash and a dump file from Marshal.dump for this test.
#### Parse Time (from their respective formats)
* Yajl::Parser#parse: 4.54s
* JSON.parse: 7.40s
* Marshal.load: 7s
#### Encode Time (to their respective formats)
* Yajl::Encoder#encode: 2.39s
* JSON#to_json: 8.37s
* Marshal.dump: 4.66s
## Third Party Sources Bundled
This project includes code from the BSD licensed yajl project, copyright 2007-2009 Lloyd Hilaiel
## Special Thanks & Contributors
For those of you using yajl-ruby out in the wild, please hit me up on Twitter (brianmario) or send me a message here on the Githubs describing the site and how you're using it. I'd love to get a list going!
I've had a lot of inspiration, and a lot of help. Thanks to everyone who's been a part of this and those to come!
* Lloyd Hilaiel - http://github.com/lloyd - for writing Yajl!!
* Josh Ferguson - http://github.com/besquared - for peer-pressuring me into getting back into C; it worked ;) Also tons of support over IM
* Jonathan Novak - http://github.com/cypriss - pointer-hacking help
* Tom Smith - http://github.com/rtomsmith - pointer-hacking help
* Rick Olson - http://github.com/technoweenie - for making an ActiveSupport patch with support for this library and teasing me that it might go into Rails 3. You sure lit a fire under my ass and I got a ton of work done because of it! :)
* The entire Github Crew - http://github.com/ - my inspiration, time spent writing this, finding Yajl, So many-MANY other things wouldn't have been possible without this awesome service. I owe you guys some whiskey at Kilowatt.
* Ben Burkert - http://github.com/benburkert
* Aman Gupta - http://github.com/tmm1 - tons of suggestions and inspiration for the most recent features, and hopefully more to come ;)
* Filipe Giusti
* Jonathan George
* Luke Redpath
* Neil Berkman
* Pavel Valodzka
* Rob Sharp
yajl-ruby-1.4.3/tasks/ 0000755 0000041 0000041 00000000000 14246427314 014621 5 ustar www-data www-data yajl-ruby-1.4.3/tasks/compile.rake 0000644 0000041 0000041 00000001640 14246427314 017116 0 ustar www-data www-data require 'rake/extensiontask'
def gemspec
@clean_gemspec ||= eval(File.read(File.expand_path('../../yajl-ruby.gemspec', __FILE__)))
end
Rake::ExtensionTask.new('yajl', gemspec) do |ext|
# automatically add build options to avoid need of manual input
ext.cross_compile = true
ext.cross_platform = ['x86-mingw32', 'x86-mswin32-60']
# inject 1.8/1.9 pure-ruby entry point when cross compiling only
ext.cross_compiling do |spec|
spec.files << 'lib/yajl/yajl.rb'
end
ext.lib_dir = File.join 'lib', 'yajl'
# clean compiled extension
CLEAN.include "#{ext.lib_dir}/*.#{RbConfig::CONFIG['DLEXT']}"
end
Rake::Task[:spec].prerequisites << :compile
file 'lib/yajl/yajl.rb' do |t|
File.open(t.name, 'wb') do |f|
f.write <<-eoruby
RUBY_VERSION =~ /(\\d+.\\d+)/
require "yajl/\#{$1}/yajl"
eoruby
end
end
if Rake::Task.task_defined?(:cross)
Rake::Task[:cross].prerequisites << 'lib/yajl/yajl.rb'
end
yajl-ruby-1.4.3/tasks/rspec.rake 0000644 0000041 0000041 00000000601 14246427314 016576 0 ustar www-data www-data begin
require 'rspec'
require 'rspec/core/rake_task'
desc "Run all examples with RCov"
RSpec::Core::RakeTask.new('spec:rcov') do |t|
t.rcov = true
end
RSpec::Core::RakeTask.new('spec') do |t|
t.verbose = true
end
task :default => :spec
rescue LoadError
puts "rspec, or one of its dependencies, is not available. Install it with: sudo gem install rspec"
end
yajl-ruby-1.4.3/spec/ 0000755 0000041 0000041 00000000000 14246427314 014426 5 ustar www-data www-data yajl-ruby-1.4.3/spec/json_gem_compatibility/ 0000755 0000041 0000041 00000000000 14246427314 021160 5 ustar www-data www-data yajl-ruby-1.4.3/spec/json_gem_compatibility/compatibility_spec.rb 0000644 0000041 0000041 00000015626 14246427314 025402 0 ustar www-data www-data # encoding: UTF-8
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
class Dummy; end
describe "JSON Gem compatability API" do
it "shoud not mixin #to_json on base objects until compatability has been enabled" do
d = Dummy.new
expect(d.respond_to?(:to_json)).not_to be_truthy
expect("".respond_to?(:to_json)).not_to be_truthy
expect(1.respond_to?(:to_json)).not_to be_truthy
expect("1.5".to_f.respond_to?(:to_json)).not_to be_truthy
expect([].respond_to?(:to_json)).not_to be_truthy
expect({:foo => "bar"}.respond_to?(:to_json)).not_to be_truthy
expect(true.respond_to?(:to_json)).not_to be_truthy
expect(false.respond_to?(:to_json)).not_to be_truthy
expect(nil.respond_to?(:to_json)).not_to be_truthy
end
it "should mixin #to_json on base objects after compatability has been enabled" do
require 'yajl/json_gem'
d = Dummy.new
expect(d.respond_to?(:to_json)).to be_truthy
expect("".respond_to?(:to_json)).to be_truthy
expect(1.respond_to?(:to_json)).to be_truthy
expect("1.5".to_f.respond_to?(:to_json)).to be_truthy
expect([].respond_to?(:to_json)).to be_truthy
expect({:foo => "bar"}.respond_to?(:to_json)).to be_truthy
expect(true.respond_to?(:to_json)).to be_truthy
expect(false.respond_to?(:to_json)).to be_truthy
expect(nil.respond_to?(:to_json)).to be_truthy
end
it "should require yajl/json_gem to enable the compatability API" do
expect(defined?(JSON)).to be_truthy
expect(JSON.respond_to?(:parse)).to be_truthy
expect(JSON.respond_to?(:generate)).to be_truthy
expect(JSON.respond_to?(:pretty_generate)).to be_truthy
expect(JSON.respond_to?(:load)).to be_truthy
expect(JSON.respond_to?(:dump)).to be_truthy
end
it "should allow default parsing options be set with JSON.default_options" do
default = JSON.default_options[:symbolize_keys]
expect(JSON.parse('{"foo": 1234}')).to be === {"foo" => 1234}
JSON.default_options[:symbolize_keys] = true
expect(JSON.parse('{"foo": 1234}')).to be === {:foo => 1234}
JSON.default_options[:symbolize_keys] = default # ensure the rest of the test cases expect the default
end
it "should also allow the json gem's symbolize_names key" do
expect(JSON.parse('{"foo": 1234}', :symbolize_names => true)).to be === {:foo => 1234}
end
it "should encode arbitrary classes via their default to_json method" do
d = Dummy.new
expect(d.to_json).to eq("\"#{d.to_s}\"")
t = Time.now
expect(t.to_json).to eq("\"#{t.to_s}\"")
da = Date.today
expect(da.to_json).to eq("\"#{da.to_s}\"")
dt = DateTime.new
expect(dt.to_json).to eq("\"#{dt.to_s}\"")
end
it "should have the standard parsing and encoding exceptions mapped" do
expect(JSON::JSONError.new.is_a?(StandardError)).to be_truthy
expect(JSON::ParserError.new.is_a?(JSON::JSONError)).to be_truthy
expect(JSON::GeneratorError.new.is_a?(JSON::JSONError)).to be_truthy
expect {
JSON.parse("blah")
}.to raise_error(JSON::ParserError)
expect {
JSON.generate(0.0/0.0)
}.to raise_error(JSON::GeneratorError)
end
context "ported tests for Unicode" do
it "should be able to encode and parse unicode" do
expect('""').to eql(''.to_json)
expect('"\\b"').to eql("\b".to_json)
expect('"\u0001"').to eql(0x1.chr.to_json)
expect('"\u001F"').to eql(0x1f.chr.to_json)
expect('" "').to eql(' '.to_json)
expect("\"#{0x7f.chr}\"").to eql(0x7f.chr.to_json)
utf8 = [ "© ≠ €! \01" ]
json = "[\"© ≠ €! \\u0001\"]"
expect(json).to eql(utf8.to_json)
expect(utf8).to eql(JSON.parse(json))
utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
json = "[\"あいうえお\"]"
expect(json).to eql(utf8.to_json)
expect(utf8).to eql(JSON.parse(json))
utf8 = ['საქართველო']
json = "[\"საქართველო\"]"
expect(json).to eql(utf8.to_json)
expect(utf8).to eql(JSON.parse(json))
expect('["Ã"]').to eql(JSON.generate(["Ã"]))
expect(["€"]).to eql(JSON.parse('["\u20ac"]'))
utf8_str = "\xf0\xa0\x80\x81"
utf8 = [utf8_str]
json = "[\"#{utf8_str}\"]"
expect(json).to eql(JSON.generate(utf8))
expect(utf8).to eql(JSON.parse(json))
end
end
context "ported tests for generation" do
before(:all) do
@hash = {
'a' => 2,
'b' => 3.141,
'c' => 'c',
'd' => [ 1, "b", 3.14 ],
'e' => { 'foo' => 'bar' },
'g' => "blah",
'h' => 1000.0,
'i' => 0.001
}
@json2 = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},"g":"blah","h":1000.0,"i":0.001}'
@json3 = %{
{
"a": 2,
"b": 3.141,
"c": "c",
"d": [1, "b", 3.14],
"e": {"foo": "bar"},
"g": "blah",
"h": 1000.0,
"i": 0.001
}
}.chomp
end
it "should be able to unparse" do
json = JSON.generate(@hash)
expect(JSON.parse(@json2)).to eq(JSON.parse(json))
parsed_json = JSON.parse(json)
expect(@hash).to eq(parsed_json)
json = JSON.generate({1=>2})
expect('{"1":2}').to eql(json)
parsed_json = JSON.parse(json)
expect({"1"=>2}).to eq(parsed_json)
end
it "should be able to unparse pretty" do
json = JSON.pretty_generate(@hash)
expect(JSON.parse(@json3)).to eq(JSON.parse(json))
parsed_json = JSON.parse(json)
expect(@hash).to eq(parsed_json)
json = JSON.pretty_generate({1=>2})
test = "{\n \"1\": 2\n}".chomp
expect(test).to eq(json)
parsed_json = JSON.parse(json)
expect({"1"=>2}).to eq(parsed_json)
end
end
context "ported fixture tests" do
fixtures = File.join(File.dirname(__FILE__), '../parsing/fixtures/*.json')
passed, failed = Dir[fixtures].partition { |f| f['pass'] }
JSON_PASSED = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
JSON_FAILED = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
JSON_FAILED.each do |name, source|
it "should not be able to parse #{File.basename(name)} as an IO" do
expect {
JSON.parse(StringIO.new(source))
}.to raise_error(JSON::ParserError)
end
end
JSON_FAILED.each do |name, source|
it "should not be able to parse #{File.basename(name)} as a string" do
expect {
JSON.parse(source)
}.to raise_error(JSON::ParserError)
end
end
JSON_PASSED.each do |name, source|
it "should be able to parse #{File.basename(name)} as an IO" do
expect {
JSON.parse(StringIO.new(source))
}.not_to raise_error
end
end
JSON_PASSED.each do |name, source|
it "should be able to parse #{File.basename(name)} as a string" do
expect {
JSON.parse(source)
}.not_to raise_error
end
end
end
end
yajl-ruby-1.4.3/spec/projection/ 0000755 0000041 0000041 00000000000 14246427314 016602 5 ustar www-data www-data yajl-ruby-1.4.3/spec/projection/projection.rb 0000644 0000041 0000041 00000027353 14246427314 021315 0 ustar www-data www-data require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
require 'stringio'
require 'json'
describe "projection" do
it "should work" do
stream = StringIO.new('{"name": "keith", "age": 27}')
projector = Yajl::Projector.new(stream)
projection = projector.project({"name" => nil})
expect(projection['name']).to eql("keith")
end
it "should filter" do
stream = StringIO.new('{"name": "keith", "age": 27}')
projector = Yajl::Projector.new(stream)
projection = projector.project({"name" => nil})
expect(projection['age']).to eql(nil)
end
it "should raise an exception and not leak memory" do
stream = StringIO.new('foo')
projector = Yajl::Projector.new(stream)
expect {
projector.project({"name" => nil})
}.to raise_error(Yajl::ParseError)
end
it "should raise an exception and not segv" do
stream = StringIO.new('[,,,,]')
projector = Yajl::Projector.new(stream)
expect {
projector.project({"name" => nil})
}.to raise_error(Yajl::ParseError)
end
it "should raise an exception and not segv on colons" do
stream = StringIO.new('[::::]')
projector = Yajl::Projector.new(stream)
expect {
projector.project({"name" => nil})
}.to raise_error(Yajl::ParseError)
end
it "should behave the same way as the regular parser on bad tokens like comma" do
bad_json = '{"name": "keith", "age":, 27}'
stream = StringIO.new(bad_json)
projector = Yajl::Projector.new(stream)
expect {
projector.project({"name" => nil})
}.to raise_error(capture_exception_for(bad_json).class)
end
it "should behave the same way as the regular parser on bad tokens like colon" do
bad_json = '{"name": "keith", "age":: 27}'
stream = StringIO.new(bad_json)
projector = Yajl::Projector.new(stream)
expect {
projector.project({"name" => nil})
}.to raise_error(capture_exception_for(bad_json).class)
end
it "should behave the same way as the regular parser on not enough json" do
bad_json = '{"name": "keith", "age":'
stream = StringIO.new(bad_json)
projector = Yajl::Projector.new(stream)
expect {
projector.project({"name" => nil})
}.to raise_error(capture_exception_for(bad_json).class)
end
def capture_exception_for(bad_json)
Yajl::Parser.new.parse(bad_json)
rescue Exception => e
e
end
def project(schema, over: "", json: nil, stream: nil)
if stream.nil?
if json.nil?
json = over.to_json
end
stream = StringIO.new(json)
end
Yajl::Projector.new(stream).project(schema)
end
it "filters arrays" do
json = {
"users" => [
{
"name" => "keith",
"company" => "internet plumbing inc",
"department" => "janitorial",
},
{
"name" => "justin",
"company" => "big blue",
"department" => "programming?",
},
{
"name" => "alan",
"company" => "different colour of blue",
"department" => "drop bear containment",
}
]
}.to_json
puts json
schema = {
# /users is an array of objects, each having many keys we only want name
"users" => {
"name" => nil,
}
}
expect(project(schema, json: json)).to eql({
"users" => [
{ "name" => "keith" },
{ "name" => "justin" },
{ "name" => "alan" }
]
})
end
it "filters top level arrays" do
json = [
{
"name" => "keith",
"personal detail" => "thing",
},
{
"name" => "cory",
"phone number" => "unknown",
}
]
schema = {
"name" => nil,
}
expect(project(schema, over: json)).to eql([
{ "name" => "keith" },
{ "name" => "cory" },
])
end
it "filters nested schemas" do
json = {
"foo" => 42,
"bar" => {
"name" => "keith",
"occupation" => "professional computering",
"age" => 26,
"hobbies" => [
"not computering",
]
},
"qux" => {
"quux" => [
{
"name" => "Reactive X",
"members" => "many",
},
{
"name" => "lstoll",
"members" => "such",
},
{
"name" => "github",
"members" => "very",
},
{
"name" => "theleague",
"members" => "numerous",
}
],
"corge" => {
"name" => "Brighton",
"address" =>"Buckingham Road",
},
},
"grault" => nil,
"waldo" => true,
}
schema = {
# include the /foo subtree (is a single number)
"foo" => nil,
# ignore the bar subtree (is an object)
# "bar" => ???
# include some of the /qux subtree (is an object)
"qux" => {
# include the whole /qux/quux subtree (is an array of objects)
"quux" => nil,
# include some of the /qux/corge subtree (is another object)
"corge" => {
# include name (is a string)
"name" => nil,
# include age (is missing from source doc)
"age" => nil,
# ignore address
# "address" => ???
},
},
# include the /grault subtree (is a null literal)
"grault" => nil,
# include the /waldo subtree (is a boolean literal)
"waldo" => nil,
}
expect(project(schema, over: json)).to eql({
"foo" => 42,
"qux" => {
"quux" => [
{
"name" => "Reactive X",
"members" => "many",
},
{
"name" => "lstoll",
"members" => "such",
},
{
"name" => "github",
"members" => "very",
},
{
"name" => "theleague",
"members" => "numerous",
}
],
"corge" => {
"name" => "Brighton",
},
},
"grault" => nil,
"waldo" => true,
})
end
it "supports incompatible schemas" do
json = {
# surprise! the json doesn't include an object under the foo key
"foo" => 42,
}
schema = {
# include some of the /foo subtree
"foo" => {
# include the whole /foo/baz subtree
"baz" => nil,
}
}
# expect the 42 to be pulled out
expect(project(schema, over: json)).to eql({
"foo" => 42
})
end
it "supports nil schema" do
json = {
"foo" => "bar",
}
expect(project(nil, over: json)).to eql({
"foo" => "bar"
})
end
it "supports empty schema" do
json = {
"foo" => "bar",
}
expect(project({}, over: json)).to eql({})
end
it "supports object projection" do
json = {
"foo" => "bar",
"qux" => "quux",
}
schema = {
"foo" => nil,
}
expect(project(schema, over: json)).to eql({
"foo" => "bar"
})
end
it "projects the readme example" do
json = <<-EOJ
[
{
"user": {
"name": "keith",
"age": 26,
"jobs": [
{
"title": "director of overworking",
"company": "south coast software",
"department": "most"
},
{
"title": "some kind of computering",
"company": "github the website dot com",
"department": true
}
]
},
"another key": {
},
"woah this document is huge": {
},
"many megabytes": {
},
"etc": {
}
}
]
EOJ
schema = {
"user" => {
"name" => nil,
"jobs" => {
"title" => nil,
},
},
}
expect(project(schema, json: json)).to eql([{
"user" => {
"name" => "keith",
"jobs" => [
{ "title" => "director of overworking" },
{ "title" => "some kind of computering" },
]
}
}])
end
it "errors with invalid json" do
expect {
project({"b" => nil}, json: '{"a":, "b": 2}')
}.to raise_error(StandardError)
end
it "errors with ignored unbalanced object syntax" do
expect {
project({"b" => nil}, json: '{"a": {{, "b": 2}')
}.to raise_error(StandardError)
end
it "errors with accepted unbalanced object tokens" do
expect {
project({"a" => nil}, json: '{"a": {"b": 2}')
}.to raise_error(Yajl::ParseError)
end
it "errors when projecting if an object comma is missing" do
expect {
project({"a" => nil}, json: '{"a": 1 "b": 2}')
}.to raise_error(Yajl::ParseError)
end
it "errors when building if an object comma is missing" do
expect {
project(nil, json: '{"a": {"b": 2 "c": 3}}')
}.to raise_error(Yajl::ParseError)
end
it "errors when eof instead of simple value" do
expect {
project(nil, json: '[')
}.to raise_error(Yajl::ParseError)
end
it "errors when arrays don't have a comma between elements" do
expect {
project(nil, json: '[1 2]')
}.to raise_error(Yajl::ParseError)
end
it "supports parsing empty array" do
expect(project(nil, json: '[]')).to eql([])
end
it "supports parsing empty object" do
expect(project(nil, json: '{}')).to eql({})
end
it "reads a full buffer" do
json = "[" + "1,"*2046 + "1 ]"
expect(json.size).to eql(4096)
expect(project(nil, json: json)).to eql(Array.new(2047, 1))
end
it "reads into a second buffer" do
json = "[" + "1,"*2047 + "1 ]"
expect(json.size).to eql(4098)
expect(JSON.parse(json)).to eql(Array.new(2048, 1))
expect(project(nil, json: json)).to eql(Array.new(2048, 1))
end
it "supports parsing big strings" do
json = [
"a",
"b"*10_000,
"c",
]
expect(project(nil, over: json)).to eql(json)
end
it "supports bigger read buffers" do
json = {
"a"*10_000 => "b"*10_000
}.to_json
stream = StringIO.new(json)
expect(Yajl::Projector.new(stream, 8192).project(nil)).to have_key("a"*10_000)
end
it "errors if starting with closing object" do
expect {
project(nil, json: '}')
}.to raise_error(Yajl::ParseError)
end
it "handles objects with utf16 escape sequences as keys" do
projection = project(nil, json: '{"\ud83d\ude00": "grinning face"}')
literal = {"😀" => "grinning face"}
expect(projection).to eql(literal)
end
it "handles objects with non-ascii utf8 bytes as keys" do
expect(project(nil, json: '{"😀": "grinning face"}')).to eql({"😀" => "grinning face"})
end
it "handles strings with utf16 escape sequences as object values" do
expect(project(nil, json: '{"grinning face": "\ud83d\ude00"}')).to eql({"grinning face" => "😀"})
end
it "handles strings with utf16 escape sequences as array values" do
projection = project(nil, json: '["\ud83d\ude00"]')
puts projection.first.inspect
puts projection.first.bytes
literal = ["😀"]
puts literal.first.inspect
puts literal.first.bytes
expect(projection).to eql(literal)
end
it "handles strings with non-ascii utf8 bytes as array values" do
projection = project(nil, json: '["😀"]')
puts projection.first.inspect
puts projection.first.bytes
literal = ["😀"]
puts literal.first.inspect
puts literal.first.bytes
expect(projection).to eql(literal)
end
it "ignores strings with utf16 escape sequences" do
expect(project({"grinning face with open mouth" => nil}, json: '{"grinning face": "\ud83d\ude00", "grinning face with open mouth": "\ud83d\ude03"}')).to eql({"grinning face with open mouth" => "😃"})
end
it "handles objects whose second key has escape sequences" do
expect(project(nil, json: '{"foo": "bar", "\ud83d\ude00": "grinning face"}')).to eql({"foo" => "bar", "😀" => "grinning face"})
end
end
yajl-ruby-1.4.3/spec/projection/project_file.rb 0000644 0000041 0000041 00000001553 14246427314 021600 0 ustar www-data www-data require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
require 'benchmark'
require 'benchmark/memory'
describe "file projection" do
it "projects file streams" do
schema = {
"forced" => nil,
"created" => nil,
"pusher" => {
"name" => nil,
},
"repository" => {
"name" => nil,
"full_name" => nil,
},
"ref" => nil,
"compare" => nil,
"commits" => {
"distinct" => nil,
"message" => nil,
"url" => nil,
"id" => nil,
"author" => {
"username" => nil,
}
}
}
file_path = ENV['JSON_FILE']
if file_path.nil? || file_path.empty?
return
end
Benchmark.memory { |x|
x.report("project (yajl)") { Yajl::Projector.new(File.open(file_path, 'r')).project(schema) }
x.compare!
}
end
end
yajl-ruby-1.4.3/spec/http/ 0000755 0000041 0000041 00000000000 14246427314 015405 5 ustar www-data www-data yajl-ruby-1.4.3/spec/http/http_get_spec.rb 0000644 0000041 0000041 00000007700 14246427314 020566 0 ustar www-data www-data require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
begin
require 'yajl/bzip2'
rescue
warn "Couldn't load yajl/bzip2, maybe you don't have bzip2-ruby installed? Continuing without running bzip2 specs."
end
require 'yajl/gzip'
require 'yajl/deflate'
require 'yajl/http_stream'
def parse_off_headers(io)
io.each_line do |line|
if line == "\r\n" # end of the headers
break
end
end
end
describe "Yajl HTTP GET request" do
before(:all) do
raw = File.new(File.expand_path(File.dirname(__FILE__) + '/fixtures/http.raw.dump'), 'r')
parse_off_headers(raw)
@template_hash = Yajl::Parser.parse(raw)
raw.rewind
parse_off_headers(raw)
@template_hash_symbolized = Yajl::Parser.parse(raw, :symbolize_keys => true)
@deflate = File.new(File.expand_path(File.dirname(__FILE__) + '/fixtures/http.deflate.dump'), 'r')
@gzip = File.new(File.expand_path(File.dirname(__FILE__) + '/fixtures/http.gzip.dump'), 'r')
@chunked_body = {"item"=>{"price"=>1.99, "updated_by_id"=>nil, "cached_tag_list"=>"", "name"=>"generated", "created_at"=>"2009-03-24T05:25:09Z", "cost"=>0.597, "delta"=>false, "created_by_id"=>nil, "updated_at"=>"2009-03-24T05:25:09Z", "import_tag"=>nil, "account_id"=>16, "id"=>1, "taxable"=>true, "unit"=>nil, "sku"=>"06317-0306", "company_id"=>0, "description"=>nil, "active"=>true}}
end
after(:each) do
@file_path = nil
end
def prepare_mock_request_dump(format=:raw)
@request = File.new(File.expand_path(File.dirname(__FILE__) + "/fixtures/http.#{format}.dump"), 'r')
@uri = 'file://'+File.expand_path(File.dirname(__FILE__) + "/fixtures/http/http.#{format}.dump")
expect(TCPSocket).to receive(:new).and_return(@request)
expect(@request).to receive(:write)
end
it "should parse a raw response" do
prepare_mock_request_dump :raw
expect(@template_hash).to eq(Yajl::HttpStream.get(@uri))
end
it "should parse a raw response and symbolize keys" do
prepare_mock_request_dump :raw
expect(@template_hash_symbolized).to eq(Yajl::HttpStream.get(@uri, :symbolize_keys => true))
end
it "should parse a raw response using instance method" do
prepare_mock_request_dump :raw
expect(@uri).to receive(:host)
expect(@uri).to receive(:port)
stream = Yajl::HttpStream.new
expect(@template_hash).to eq(stream.get(@uri))
end
it "should parse a chunked response using instance method" do
prepare_mock_request_dump :chunked
expect(@uri).to receive(:host)
expect(@uri).to receive(:port)
stream = Yajl::HttpStream.new
stream.get(@uri) do |obj|
expect(obj).to eql(@chunked_body)
end
end
if defined?(Yajl::Bzip2::StreamReader)
it "should parse a bzip2 compressed response" do
prepare_mock_request_dump :bzip2
expect(@template_hash).to eq(Yajl::HttpStream.get(@uri))
end
it "should parse a bzip2 compressed response and symbolize keys" do
prepare_mock_request_dump :bzip2
expect(@template_hash_symbolized).to eq(Yajl::HttpStream.get(@uri, :symbolize_keys => true))
end
end
it "should parse a deflate compressed response" do
prepare_mock_request_dump :deflate
expect(@template_hash).to eq(Yajl::HttpStream.get(@uri))
end
it "should parse a deflate compressed response and symbolize keys" do
prepare_mock_request_dump :deflate
expect(@template_hash_symbolized).to eq(Yajl::HttpStream.get(@uri, :symbolize_keys => true))
end
it "should parse a gzip compressed response" do
prepare_mock_request_dump :gzip
expect(@template_hash).to eq(Yajl::HttpStream.get(@uri))
end
it "should parse a gzip compressed response and symbolize keys" do
prepare_mock_request_dump :gzip
expect(@template_hash_symbolized).to eq(Yajl::HttpStream.get(@uri, :symbolize_keys => true))
end
it "should raise when an HTTP code that isn't 200 is returned" do
prepare_mock_request_dump :error
expect { Yajl::HttpStream.get(@uri) }.to raise_exception(Yajl::HttpStream::HttpError)
end
end
yajl-ruby-1.4.3/spec/http/fixtures/ 0000755 0000041 0000041 00000000000 14246427314 017256 5 ustar www-data www-data yajl-ruby-1.4.3/spec/http/fixtures/http.html.dump 0000644 0000041 0000041 00000101737 14246427314 022100 0 ustar www-data www-data HTTP/1.1 200 Not Acceptable
Content-Type: text/html; charset=iso-8859-1
Server: Jetty(6.1.17)
{
"command": {
"ps": "ps -ef"
},
"kernel": {
"modules": {
"org.virtualbox.kext.VBoxDrv": {
"size": 118784,
"version": "2.2.0",
"index": "114",
"refcount": "3"
},
"com.cisco.nke.ipsec": {
"size": 454656,
"version": "2.0.1",
"index": "111",
"refcount": "0"
},
"com.apple.driver.AppleAPIC": {
"size": 12288,
"version": "1.4",
"index": "26",
"refcount": "0"
},
"com.apple.driver.AirPort.Atheros": {
"size": 593920,
"version": "318.8.3",
"index": "88",
"refcount": "0"
},
"com.apple.driver.AppleIntelCPUPowerManagement": {
"size": 102400,
"version": "59.0.1",
"index": "22",
"refcount": "0"
},
"com.apple.iokit.IOStorageFamily": {
"size": 98304,
"version": "1.5.5",
"index": "44",
"refcount": "9"
},
"com.apple.iokit.IOATAPIProtocolTransport": {
"size": 16384,
"version": "1.5.2",
"index": "52",
"refcount": "0"
},
"com.apple.iokit.IOPCIFamily": {
"size": 65536,
"version": "2.5",
"index": "17",
"refcount": "18"
},
"com.apple.driver.AppleHPET": {
"size": 12288,
"version": "1.3",
"index": "33",
"refcount": "0"
},
"com.apple.driver.AppleUSBHub": {
"size": 49152,
"version": "3.2.7",
"index": "47",
"refcount": "0"
},
"com.apple.iokit.IOFireWireFamily": {
"size": 258048,
"version": "3.4.6",
"index": "49",
"refcount": "2"
},
"com.apple.driver.AppleUSBComposite": {
"size": 16384,
"version": "3.2.0",
"index": "60",
"refcount": "1"
},
"com.apple.driver.AppleIntelPIIXATA": {
"size": 36864,
"version": "2.0.0",
"index": "41",
"refcount": "0"
},
"com.apple.driver.AppleSmartBatteryManager": {
"size": 28672,
"version": "158.6.0",
"index": "32",
"refcount": "0"
},
"com.apple.filesystems.udf": {
"size": 233472,
"version": "2.0.2",
"index": "119",
"refcount": "0"
},
"com.apple.iokit.IOSMBusFamily": {
"size": 12288,
"version": "1.1",
"index": "27",
"refcount": "2"
},
"com.apple.iokit.IOACPIFamily": {
"size": 16384,
"version": "1.2.0",
"index": "18",
"refcount": "10"
},
"foo.tap": {
"size": 24576,
"version": "1.0",
"index": "113",
"refcount": "0"
},
"com.vmware.kext.vmx86": {
"size": 864256,
"version": "2.0.4",
"index": "104",
"refcount": "0"
},
"com.apple.iokit.CHUDUtils": {
"size": 28672,
"version": "200",
"index": "98",
"refcount": "0"
},
"org.virtualbox.kext.VBoxNetAdp": {
"size": 8192,
"version": "2.2.0",
"index": "117",
"refcount": "0"
},
"com.apple.filesystems.autofs": {
"size": 45056,
"version": "2.0.1",
"index": "109",
"refcount": "0"
},
"com.vmware.kext.vmnet": {
"size": 36864,
"version": "2.0.4",
"index": "108",
"refcount": "0"
},
"com.apple.driver.AppleACPIButtons": {
"size": 16384,
"version": "1.2.4",
"index": "30",
"refcount": "0"
},
"com.apple.driver.AppleFWOHCI": {
"size": 139264,
"version": "3.7.2",
"index": "50",
"refcount": "0"
},
"com.apple.iokit.IOSCSIArchitectureModelFamily": {
"size": 102400,
"version": "2.0.5",
"index": "51",
"refcount": "4"
},
"com.apple.iokit.IOSCSIBlockCommandsDevice": {
"size": 90112,
"version": "2.0.5",
"index": "57",
"refcount": "1"
},
"com.apple.driver.AppleACPIPCI": {
"size": 12288,
"version": "1.2.4",
"index": "31",
"refcount": "0"
},
"com.apple.security.seatbelt": {
"size": 98304,
"version": "107.10",
"index": "25",
"refcount": "0"
},
"com.apple.driver.AppleUpstreamUserClient": {
"size": 16384,
"version": "2.7.2",
"index": "100",
"refcount": "0"
},
"com.apple.kext.OSvKernDSPLib": {
"size": 12288,
"version": "1.1",
"index": "79",
"refcount": "1"
},
"com.apple.iokit.IOBDStorageFamily": {
"size": 20480,
"version": "1.5",
"index": "58",
"refcount": "1"
},
"com.apple.iokit.IOGraphicsFamily": {
"size": 118784,
"version": "1.7.1",
"index": "70",
"refcount": "5"
},
"com.apple.iokit.IONetworkingFamily": {
"size": 90112,
"version": "1.6.1",
"index": "82",
"refcount": "4"
},
"com.apple.iokit.IOATAFamily": {
"size": 53248,
"version": "2.0.0",
"index": "40",
"refcount": "2"
},
"com.apple.iokit.IOUSBHIDDriver": {
"size": 20480,
"version": "3.2.2",
"index": "63",
"refcount": "2"
},
"org.virtualbox.kext.VBoxUSB": {
"size": 28672,
"version": "2.2.0",
"index": "115",
"refcount": "0"
},
"com.vmware.kext.vmioplug": {
"size": 24576,
"version": "2.0.4",
"index": "107",
"refcount": "0"
},
"com.apple.security.TMSafetyNet": {
"size": 12288,
"version": "3",
"index": "23",
"refcount": "0"
},
"com.apple.iokit.IONDRVSupport": {
"size": 57344,
"version": "1.7.1",
"index": "71",
"refcount": "3"
},
"com.apple.BootCache": {
"size": 20480,
"version": "30.3",
"index": "20",
"refcount": "0"
},
"com.apple.iokit.IOUSBUserClient": {
"size": 8192,
"version": "3.2.4",
"index": "46",
"refcount": "1"
},
"com.apple.iokit.IOSCSIMultimediaCommandsDevice": {
"size": 90112,
"version": "2.0.5",
"index": "59",
"refcount": "0"
},
"com.apple.driver.AppleIRController": {
"size": 20480,
"version": "110",
"index": "78",
"refcount": "0"
},
"com.apple.driver.AudioIPCDriver": {
"size": 16384,
"version": "1.0.5",
"index": "81",
"refcount": "0"
},
"org.virtualbox.kext.VBoxNetFlt": {
"size": 16384,
"version": "2.2.0",
"index": "116",
"refcount": "0"
},
"com.apple.driver.AppleLPC": {
"size": 12288,
"version": "1.2.11",
"index": "73",
"refcount": "0"
},
"com.apple.iokit.CHUDKernLib": {
"size": 20480,
"version": "196",
"index": "93",
"refcount": "2"
},
"com.apple.iokit.CHUDProf": {
"size": 49152,
"version": "207",
"index": "97",
"refcount": "0"
},
"com.apple.NVDAResman": {
"size": 2478080,
"version": "5.3.6",
"index": "90",
"refcount": "2"
},
"com.apple.driver.AppleACPIEC": {
"size": 20480,
"version": "1.2.4",
"index": "28",
"refcount": "0"
},
"foo.tun": {
"size": 24576,
"version": "1.0",
"index": "118",
"refcount": "0"
},
"com.apple.iokit.IOSerialFamily": {
"size": 36864,
"version": "9.3",
"index": "102",
"refcount": "1"
},
"com.apple.GeForce": {
"size": 622592,
"version": "5.3.6",
"index": "96",
"refcount": "0"
},
"com.apple.iokit.IOCDStorageFamily": {
"size": 32768,
"version": "1.5",
"index": "55",
"refcount": "3"
},
"com.apple.driver.AppleUSBEHCI": {
"size": 73728,
"version": "3.2.5",
"index": "39",
"refcount": "0"
},
"com.apple.nvidia.nv50hal": {
"size": 2445312,
"version": "5.3.6",
"index": "91",
"refcount": "0"
},
"com.apple.driver.AppleSMBIOS": {
"size": 16384,
"version": "1.1.1",
"index": "29",
"refcount": "0"
},
"com.apple.driver.AppleBacklight": {
"size": 16384,
"version": "1.4.4",
"index": "72",
"refcount": "0"
},
"com.apple.driver.AppleACPIPlatform": {
"size": 253952,
"version": "1.2.4",
"index": "19",
"refcount": "3"
},
"com.apple.iokit.SCSITaskUserClient": {
"size": 24576,
"version": "2.0.5",
"index": "54",
"refcount": "0"
},
"com.apple.iokit.IOHIDFamily": {
"size": 233472,
"version": "1.5.3",
"index": "21",
"refcount": "7"
},
"com.apple.driver.DiskImages": {
"size": 65536,
"version": "195.2.2",
"index": "101",
"refcount": "0"
},
"com.apple.iokit.IODVDStorageFamily": {
"size": 24576,
"version": "1.5",
"index": "56",
"refcount": "2"
},
"com.apple.driver.XsanFilter": {
"size": 20480,
"version": "2.7.91",
"index": "53",
"refcount": "0"
},
"com.apple.driver.AppleEFIRuntime": {
"size": 12288,
"version": "1.2.0",
"index": "35",
"refcount": "1"
},
"com.apple.driver.AppleRTC": {
"size": 20480,
"version": "1.2.3",
"index": "34",
"refcount": "0"
},
"com.apple.iokit.IOFireWireIP": {
"size": 36864,
"version": "1.7.6",
"index": "83",
"refcount": "0"
},
"com.vmware.kext.vmci": {
"size": 45056,
"version": "2.0.4",
"index": "106",
"refcount": "0"
},
"com.apple.iokit.IO80211Family": {
"size": 126976,
"version": "215.1",
"index": "87",
"refcount": "1"
},
"com.apple.nke.applicationfirewall": {
"size": 32768,
"version": "1.0.77",
"index": "24",
"refcount": "0"
},
"com.apple.iokit.IOAHCIBlockStorage": {
"size": 69632,
"version": "1.2.0",
"index": "48",
"refcount": "0"
},
"com.apple.driver.AppleUSBUHCI": {
"size": 57344,
"version": "3.2.5",
"index": "38",
"refcount": "0"
},
"com.apple.iokit.IOAHCIFamily": {
"size": 24576,
"version": "1.5.0",
"index": "42",
"refcount": "2"
},
"com.apple.driver.AppleAHCIPort": {
"size": 53248,
"version": "1.5.2",
"index": "43",
"refcount": "0"
},
"com.apple.driver.AppleEFINVRAM": {
"size": 24576,
"version": "1.2.0",
"index": "36",
"refcount": "0"
},
"com.apple.iokit.IOUSBFamily": {
"size": 167936,
"version": "3.2.7",
"index": "37",
"refcount": "13"
},
"com.apple.driver.AppleUSBMergeNub": {
"size": 12288,
"version": "3.2.4",
"index": "61",
"refcount": "0"
}
},
"machine": "i386",
"name": "Darwin",
"os": "Darwin",
"version": "Darwin Kernel Version 9.6.0: Mon Nov 24 17:37:00 PST 2008; root:xnu-1228.9.59~1\/RELEASE_I386",
"release": "9.6.0"
},
"platform_version": "10.5.6",
"platform": "mac_os_x",
"ipaddress": "192.168.88.1",
"keys": {
"ssh": {
"host_dsa_public": "private",
"host_rsa_public": "private"
}
},
"network": {
"settings": {
"net.inet6.ip6.forwarding": "0",
"net.inet.ip.dummynet.debug": "0",
"net.inet.ip.rtexpire": "10",
"net.inet6.ipsec6.esp_trans_deflev": "1",
"net.inet.tcp.tcbhashsize": "4096",
"net.key.esp_auth": "0",
"net.inet6.ip6.hlim": "64",
"net.inet.ip.fw.dyn_fin_lifetime": "1",
"net.inet.ip.fw.dyn_udp_lifetime": "10",
"net.inet.icmp.bmcastecho": "1",
"net.athforceBias": "2 2",
"net.athbgscan": "1 1",
"net.inet.tcp.reass.maxsegments": "2048",
"net.inet6.ip6.auto_flowlabel": "1",
"net.inet6.ip6.rtmaxcache": "128",
"net.inet.tcp.sendspace": "131072",
"net.inet.tcp.keepinit": "75000",
"net.inet.ip.dummynet.max_chain_len": "16",
"net.inet.tcp.rfc1644": "0",
"net.inet.ip.fw.curr_dyn_buckets": "256",
"net.inet.ip.dummynet.ready_heap": "0",
"net.inet.ip.portrange.first": "49152",
"net.inet.tcp.background_io_trigger": "5",
"net.link.ether.inet.host_down_time": "20",
"net.inet6.ipsec6.def_policy": "1",
"net.inet6.ipsec6.ecn": "0",
"net.inet.ip.fastforwarding": "0",
"net.athaddbaignore": "0 0",
"net.inet6.ip6.v6only": "0",
"net.inet.tcp.sack": "1",
"net.inet6.ip6.rtexpire": "3600",
"net.link.ether.inet.proxyall": "0",
"net.inet6.ip6.keepfaith": "0",
"net.key.spi_trycnt": "1000",
"net.link.ether.inet.prune_intvl": "300",
"net.inet.tcp.ecn_initiate_out": "0",
"net.inet.ip.fw.dyn_rst_lifetime": "1",
"net.local.stream.sendspace": "8192",
"net.inet.tcp.socket_unlocked_on_output": "1",
"net.inet.ip.fw.verbose_limit": "0",
"net.local.dgram.recvspace": "4096",
"net.inet.ipsec.debug": "0",
"net.link.ether.inet.log_arp_warnings": "0",
"net.inet.tcp.ecn_negotiate_in": "0",
"net.inet.tcp.rfc3465": "1",
"net.inet.tcp.icmp_may_rst": "1",
"net.link.ether.inet.sendllconflict": "0",
"net.inet.ipsec.ah_offsetmask": "0",
"net.key.blockacq_count": "10",
"net.inet.tcp.delayed_ack": "3",
"net.inet.ip.fw.verbose": "2",
"net.inet.ip.fw.dyn_count": "0",
"net.inet.tcp.slowlink_wsize": "8192",
"net.inet6.ip6.fw.enable": "1",
"net.inet.ip.portrange.hilast": "65535",
"net.inet.icmp.maskrepl": "0",
"net.link.ether.inet.apple_hwcksum_rx": "1",
"net.inet.tcp.drop_synfin": "1",
"net.key.spi_maxval": "268435455",
"net.inet.ipsec.ecn": "0",
"net.inet.ip.fw.dyn_keepalive": "1",
"net.key.int_random": "60",
"net.key.debug": "0",
"net.inet.ip.dummynet.curr_time": "0",
"net.inet.udp.blackhole": "0",
"net.athaggrqmin": "1 1",
"net.athppmenable": "1 1",
"net.inet.ip.fw.dyn_syn_lifetime": "20",
"net.inet.tcp.keepidle": "7200000",
"net.inet6.ip6.tempvltime": "604800",
"net.inet.tcp.recvspace": "358400",
"net.inet.tcp.keepintvl": "75000",
"net.inet.udp.maxdgram": "9216",
"net.inet.ip.maxchainsent": "0",
"net.inet.ipsec.esp_net_deflev": "1",
"net.inet6.icmp6.nd6_useloopback": "1",
"net.inet.tcp.slowstart_flightsize": "1",
"net.inet.ip.fw.debug": "0",
"net.inet.ip.linklocal.in.allowbadttl": "1",
"net.key.spi_minval": "256",
"net.inet.ip.forwarding": "0",
"net.inet.tcp.v6mssdflt": "1024",
"net.key.larval_lifetime": "30",
"net.inet6.ip6.fw.verbose_limit": "0",
"net.inet.ip.dummynet.red_lookup_depth": "256",
"net.inet.tcp.pcbcount": "36",
"net.inet.ip.fw.dyn_ack_lifetime": "300",
"net.inet.ip.portrange.lowlast": "600",
"net.athCCAThreshold": "28 28",
"net.link.ether.inet.useloopback": "1",
"net.athqdepth": "0 0",
"net.inet.ip.ttl": "64",
"net.inet.ip.rtmaxcache": "128",
"net.inet.ipsec.bypass": "0",
"net.inet6.icmp6.nd6_debug": "0",
"net.inet.ip.use_route_genid": "1",
"net.inet6.icmp6.rediraccept": "1",
"net.inet.ip.fw.static_count": "1",
"net.inet6.ip6.fw.debug": "0",
"net.inet.udp.pcbcount": "104",
"net.inet.ipsec.esp_randpad": "-1",
"net.inet6.icmp6.nd6_maxnudhint": "0",
"net.inet.tcp.always_keepalive": "0",
"net.inet.udp.checksum": "1",
"net.link.ether.inet.keep_announcements": "1",
"net.athfixedDropThresh": "150 150",
"net.inet6.ip6.kame_version": "20010528\/apple-darwin",
"net.inet.ip.fw.dyn_max": "4096",
"net.inet.udp.log_in_vain": "0",
"net.inet6.icmp6.nd6_mmaxtries": "3",
"net.inet.ip.rtminexpire": "10",
"net.inet.ip.fw.dyn_buckets": "256",
"net.inet6.ip6.accept_rtadv": "0",
"net.inet6.ip6.rr_prune": "5",
"net.key.ah_keymin": "128",
"net.inet.ip.redirect": "1",
"net.inet.tcp.sack_globalmaxholes": "65536",
"net.inet.ip.keepfaith": "0",
"net.inet.ip.dummynet.expire": "1",
"net.inet.ip.gifttl": "30",
"net.inet.ip.portrange.last": "65535",
"net.inet.ipsec.ah_net_deflev": "1",
"net.inet6.icmp6.nd6_delay": "5",
"net.inet.tcp.packetchain": "50",
"net.inet6.ip6.hdrnestlimit": "50",
"net.inet.tcp.newreno": "0",
"net.inet6.ip6.dad_count": "1",
"net.inet6.ip6.auto_linklocal": "1",
"net.inet6.ip6.temppltime": "86400",
"net.inet.tcp.strict_rfc1948": "0",
"net.athdupie": "1 1",
"net.inet.ip.dummynet.red_max_pkt_size": "1500",
"net.inet.ip.maxfrags": "2048",
"net.inet.tcp.log_in_vain": "0",
"net.inet.tcp.rfc1323": "1",
"net.inet.ip.subnets_are_local": "0",
"net.inet.ip.dummynet.search_steps": "0",
"net.inet.icmp.icmplim": "250",
"net.link.ether.inet.apple_hwcksum_tx": "1",
"net.inet6.icmp6.redirtimeout": "600",
"net.inet.ipsec.ah_cleartos": "1",
"net.inet6.ip6.log_interval": "5",
"net.link.ether.inet.max_age": "1200",
"net.inet.ip.fw.enable": "1",
"net.inet6.ip6.redirect": "1",
"net.athaggrfmax": "28 28",
"net.inet.ip.maxfragsperpacket": "128",
"net.inet6.ip6.use_deprecated": "1",
"net.link.generic.system.dlil_input_sanity_check": "0",
"net.inet.tcp.sack_globalholes": "0",
"net.inet.tcp.reass.cursegments": "0",
"net.inet6.icmp6.nodeinfo": "3",
"net.local.inflight": "0",
"net.inet.ip.dummynet.hash_size": "64",
"net.inet.ip.dummynet.red_avg_pkt_size": "512",
"net.inet.ipsec.dfbit": "0",
"net.inet.tcp.reass.overflows": "0",
"net.inet.tcp.rexmt_thresh": "2",
"net.inet6.ip6.maxfrags": "8192",
"net.inet6.ip6.rtminexpire": "10",
"net.inet6.ipsec6.esp_net_deflev": "1",
"net.inet.tcp.blackhole": "0",
"net.key.esp_keymin": "256",
"net.inet.ip.check_interface": "0",
"net.inet.tcp.minmssoverload": "0",
"net.link.ether.inet.maxtries": "5",
"net.inet.tcp.do_tcpdrain": "0",
"net.inet.ipsec.esp_port": "4500",
"net.inet6.ipsec6.ah_net_deflev": "1",
"net.inet.ip.dummynet.extract_heap": "0",
"net.inet.tcp.path_mtu_discovery": "1",
"net.inet.ip.intr_queue_maxlen": "50",
"net.inet.ipsec.def_policy": "1",
"net.inet.ip.fw.autoinc_step": "100",
"net.inet.ip.accept_sourceroute": "0",
"net.inet.raw.maxdgram": "8192",
"net.inet.ip.maxfragpackets": "1024",
"net.inet.ip.fw.one_pass": "0",
"net.appletalk.routermix": "2000",
"net.inet.tcp.tcp_lq_overflow": "1",
"net.link.generic.system.ifcount": "9",
"net.link.ether.inet.send_conflicting_probes": "1",
"net.inet.tcp.background_io_enabled": "1",
"net.inet6.ipsec6.debug": "0",
"net.inet.tcp.win_scale_factor": "3",
"net.key.natt_keepalive_interval": "20",
"net.inet.tcp.msl": "15000",
"net.inet.ip.portrange.hifirst": "49152",
"net.inet.ipsec.ah_trans_deflev": "1",
"net.inet.tcp.rtt_min": "1",
"net.inet6.ip6.defmcasthlim": "1",
"net.inet6.icmp6.nd6_prune": "1",
"net.inet6.ip6.fw.verbose": "0",
"net.inet.ip.portrange.lowfirst": "1023",
"net.inet.tcp.maxseg_unacked": "8",
"net.local.dgram.maxdgram": "2048",
"net.key.blockacq_lifetime": "20",
"net.inet.tcp.sack_maxholes": "128",
"net.inet6.ip6.maxfragpackets": "1024",
"net.inet6.ip6.use_tempaddr": "0",
"net.athpowermode": "0 0",
"net.inet.udp.recvspace": "73728",
"net.inet.tcp.isn_reseed_interval": "0",
"net.inet.tcp.local_slowstart_flightsize": "8",
"net.inet.ip.dummynet.searches": "0",
"net.inet.ip.intr_queue_drops": "0",
"net.link.generic.system.multi_threaded_input": "1",
"net.inet.raw.recvspace": "8192",
"net.inet.ipsec.esp_trans_deflev": "1",
"net.key.prefered_oldsa": "0",
"net.local.stream.recvspace": "8192",
"net.inet.tcp.sockthreshold": "64",
"net.inet6.icmp6.nd6_umaxtries": "3",
"net.pstimeout": "20 20",
"net.inet.ip.sourceroute": "0",
"net.inet.ip.fw.dyn_short_lifetime": "5",
"net.inet.tcp.minmss": "216",
"net.inet6.ip6.gifhlim": "0",
"net.athvendorie": "1 1",
"net.inet.ip.check_route_selfref": "1",
"net.inet6.icmp6.errppslimit": "100",
"net.inet.tcp.mssdflt": "512",
"net.inet.icmp.log_redirect": "0",
"net.inet6.ipsec6.ah_trans_deflev": "1",
"net.inet6.ipsec6.esp_randpad": "-1",
"net.inet.icmp.drop_redirect": "0",
"net.inet.icmp.timestamp": "0",
"net.inet.ip.random_id": "1"
},
"interfaces": {
"vmnet1": {
"flags": [
"UP",
"BROADCAST",
"SMART",
"RUNNING",
"SIMPLEX",
"MULTICAST"
],
"addresses": [
{
"broadcast": "192.168.88.255",
"netmask": "255.255.255.0",
"family": "inet",
"address": "192.168.88.1"
},
{
"family": "lladdr",
"address": "private"
}
],
"number": "1",
"mtu": "1500",
"type": "vmnet",
"encapsulation": "Ethernet"
},
"stf0": {
"flags": [
],
"number": "0",
"mtu": "1280",
"type": "stf",
"encapsulation": "6to4"
},
"vboxnet0": {
"flags": [
"BROADCAST",
"RUNNING",
"SIMPLEX",
"MULTICAST"
],
"addresses": [
{
"family": "lladdr",
"address": "private"
}
],
"number": "0",
"mtu": "1500",
"type": "vboxnet",
"encapsulation": "Ethernet"
},
"lo0": {
"flags": [
"UP",
"LOOPBACK",
"RUNNING",
"MULTICAST"
],
"addresses": [
{
"scope": "Link",
"prefixlen": "64",
"family": "inet6",
"address": "fe80::1"
},
{
"netmask": "255.0.0.0",
"family": "inet",
"address": "127.0.0.1"
},
{
"scope": "Node",
"prefixlen": "128",
"family": "inet6",
"address": "::1"
},
{
"scope": "Node",
"prefixlen": "128",
"family": "inet6",
"address": "private"
}
],
"number": "0",
"mtu": "16384",
"type": "lo",
"encapsulation": "Loopback"
},
"vboxn": {
"counters": {
"tx": {
"bytes": "0",
"packets": "0",
"collisions": "0",
"compressed": 0,
"carrier": 0,
"drop": 0,
"errors": "0",
"overrun": 0
},
"rx": {
"bytes": "0",
"packets": "0",
"compressed": 0,
"drop": 0,
"errors": "0",
"overrun": 0,
"frame": 0,
"multicast": 0
}
}
},
"gif0": {
"flags": [
"POINTOPOINT",
"MULTICAST"
],
"number": "0",
"mtu": "1280",
"type": "gif",
"encapsulation": "IPIP"
},
"vmnet": {
"counters": {
"tx": {
"bytes": "0",
"packets": "0",
"collisions": "0",
"compressed": 0,
"carrier": 0,
"drop": 0,
"errors": "0",
"overrun": 0
},
"rx": {
"bytes": "0",
"packets": "0",
"compressed": 0,
"drop": 0,
"errors": "0",
"overrun": 0,
"frame": 0,
"multicast": 0
}
}
},
"vmnet8": {
"flags": [
"UP",
"BROADCAST",
"SMART",
"RUNNING",
"SIMPLEX",
"MULTICAST"
],
"addresses": [
{
"broadcast": "192.168.237.255",
"netmask": "255.255.255.0",
"family": "inet",
"address": "192.168.237.1"
},
{
"family": "lladdr",
"address": "private"
}
],
"number": "8",
"mtu": "1500",
"type": "vmnet",
"encapsulation": "Ethernet"
},
"en0": {
"status": "inactive",
"flags": [
"UP",
"BROADCAST",
"SMART",
"RUNNING",
"SIMPLEX",
"MULTICAST"
],
"addresses": [
{
"family": "lladdr",
"address": "private"
}
],
"number": "0",
"mtu": "1500",
"media": {
"supported": [
{
"autoselect": {
"options": [
]
}
},
{
"10baseT\/UTP": {
"options": [
"half-duplex"
]
}
},
{
"10baseT\/UTP": {
"options": [
"full-duplex"
]
}
},
{
"10baseT\/UTP": {
"options": [
"full-duplex",
"hw-loopback"
]
}
},
{
"10baseT\/UTP": {
"options": [
"full-duplex",
"flow-control"
]
}
},
{
"100baseTX": {
"options": [
"half-duplex"
]
}
},
{
"100baseTX": {
"options": [
"full-duplex"
]
}
},
{
"100baseTX": {
"options": [
"full-duplex",
"hw-loopback"
]
}
},
{
"100baseTX": {
"options": [
"full-duplex",
"flow-control"
]
}
},
{
"1000baseT": {
"options": [
"full-duplex"
]
}
},
{
"1000baseT": {
"options": [
"full-duplex",
"hw-loopback"
]
}
},
{
"1000baseT": {
"options": [
"full-duplex",
"flow-control"
]
}
},
{
"none": {
"options": [
]
}
}
],
"selected": [
{
"autoselect": {
"options": [
]
}
}
]
},
"type": "en",
"counters": {
"tx": {
"bytes": "342",
"packets": "0",
"collisions": "0",
"compressed": 0,
"carrier": 0,
"drop": 0,
"errors": "0",
"overrun": 0
},
"rx": {
"bytes": "0",
"packets": "0",
"compressed": 0,
"drop": 0,
"errors": "0",
"overrun": 0,
"frame": 0,
"multicast": 0
}
},
"encapsulation": "Ethernet"
},
"en1": {
"status": "active",
"flags": [
"UP",
"BROADCAST",
"SMART",
"RUNNING",
"SIMPLEX",
"MULTICAST"
],
"addresses": [
{
"scope": "Link",
"prefixlen": "64",
"family": "inet6",
"address": "private"
},
{
"broadcast": "192.168.1.255",
"netmask": "255.255.255.0",
"family": "inet",
"address": "192.168.1.4"
},
{
"family": "lladdr",
"address": "private"
}
],
"number": "1",
"mtu": "1500",
"media": {
"supported": [
{
"autoselect": {
"options": [
]
}
}
],
"selected": [
{
"autoselect": {
"options": [
]
}
}
]
},
"type": "en",
"counters": {
"tx": {
"bytes": "449206298",
"packets": "7041789",
"collisions": "0",
"compressed": 0,
"carrier": 0,
"drop": 0,
"errors": "95",
"overrun": 0
},
"rx": {
"bytes": "13673879120",
"packets": "19966002",
"compressed": 0,
"drop": 0,
"errors": "1655893",
"overrun": 0,
"frame": 0,
"multicast": 0
}
},
"arp": {
"192.168.1.7": "private"
},
"encapsulation": "Ethernet"
},
"fw0": {
"status": "inactive",
"flags": [
"UP",
"BROADCAST",
"SMART",
"RUNNING",
"SIMPLEX",
"MULTICAST"
],
"addresses": [
{
"family": "lladdr",
"address": "private"
}
],
"number": "0",
"mtu": "4078",
"media": {
"supported": [
{
"autoselect": {
"options": [
"full-duplex"
]
}
}
],
"selected": [
{
"autoselect": {
"options": [
"full-duplex"
]
}
}
]
},
"type": "fw",
"counters": {
"tx": {
"bytes": "346",
"packets": "0",
"collisions": "0",
"compressed": 0,
"carrier": 0,
"drop": 0,
"errors": "0",
"overrun": 0
},
"rx": {
"bytes": "0",
"packets": "0",
"compressed": 0,
"drop": 0,
"errors": "0",
"overrun": 0,
"frame": 0,
"multicast": 0
}
},
"encapsulation": "1394"
}
}
},
"fqdn": "local.local",
"ohai_time": 1240624355.08575,
"domain": "local",
"os": "darwin",
"platform_build": "9G55",
"os_version": "9.6.0",
"hostname": "local",
"macaddress": "private",
"languages": {
"ruby": {
"target_os": "darwin9.0",
"platform": "universal-darwin9.0",
"host_vendor": "apple",
"target_vendor": "apple",
"target_cpu": "i686",
"host_os": "darwin9.0",
"host_cpu": "i686",
"version": "1.8.6",
"host": "i686-apple-darwin9.0",
"target": "i686-apple-darwin9.0",
"release_date": "2008-03-03"
}
}
}
yajl-ruby-1.4.3/spec/http/fixtures/http.error.dump 0000644 0000041 0000041 00000000500 14246427314 022247 0 ustar www-data www-data HTTP/1.1 404 NOT FOUND
Vary: Accept-Encoding
Content-Type: text/html
Accept-Ranges: bytes
ETag: "-1274243775"
Last-Modified: Thu, 30 Apr 2009 04:36:11 GMT
Content-Length: 32444
Date: Wed, 24 Jun 2009 06:02:18 GMT
Server: lighttpd/1.4.22
Transfer-Encoding: chunked
THIS PAGE COULD NOT BE FOUND!
yajl-ruby-1.4.3/spec/http/fixtures/http.chunked.dump 0000644 0000041 0000041 00000000730 14246427314 022544 0 ustar www-data www-data HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
12f
{"item": {"name": "generated", "cached_tag_list": "", "updated_at": "2009-03-24T05:25:09Z", "updated_by_id": null, "price": 1.99, "delta": false, "cost": 0.597, "account_id": 16, "unit": null, "import_tag": null, "taxable": true, "id": 1, "created_by_id": null, "description": null, "company_id": 0, "sk
48
u": "06317-0306", "created_at": "2009-03-24T05:25:09Z", "active": true}}
0 yajl-ruby-1.4.3/spec/http/fixtures/http.gzip.dump 0000644 0000041 0000041 00000012633 14246427314 022101 0 ustar www-data www-data HTTP/1.1 200 OK
Vary: Accept-Encoding
Content-Encoding: gzip
Last-Modified: Thu, 30 Apr 2009 04:36:11 GMT
ETag: "-551242966"
Content-Type: application/json
Content-Length: 5283
Date: Wed, 24 Jun 2009 06:02:54 GMT
Server: lighttpd/1.4.22
*I ]m_1 qyIv63qe&9[u%lSoKKnjgbFZO??_l&i4z}'|y+//y;Rl[Jh 24cVV$g},Ogo5EX?/)+,号
0G{qG~Dz.¬JK~4
0.H
ݱz,a!X,Z 5"C)r:m )..7e@d'OJc"o*?E[0,̒[F"YVs0J6;(s]uK &jkjwMٯ\
\S˵-
UNS6f71(Z)&γuqIq
:^5Q)
MDfMXyFʒ' L=7A,r}C$tE(0hqƘH\ej,vCИ"7>aQlKE%ճ4v'[(3Q9ֱ<5L4 `0~XƉOi6ʙC0N~MH=_5E}
'Ej-] rn]#J$
4fC`gUYfZK~A#r_/"A)1&w L?d.Nr`>Jw/Hb4%TUN$ȗ/*CB(lh{?
&Zu0۫5·4.؇\6>wME2w4!Ek)Y$\yMeǭ>8(/uЛs*)5baeN
y,K1BĢH7i,IR"dOKp