yajl-ruby 0.5.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of yajl-ruby might be problematic. Click here for more details.

Files changed (129) hide show
  1. data/.gitignore +5 -0
  2. data/CHANGELOG.md +164 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +264 -0
  5. data/Rakefile +29 -0
  6. data/VERSION.yml +4 -0
  7. data/benchmark/encode.rb +46 -0
  8. data/benchmark/encode_json_and_marshal.rb +35 -0
  9. data/benchmark/encode_json_and_yaml.rb +47 -0
  10. data/benchmark/http.rb +30 -0
  11. data/benchmark/parse.rb +49 -0
  12. data/benchmark/parse_json_and_marshal.rb +47 -0
  13. data/benchmark/parse_json_and_yaml.rb +56 -0
  14. data/benchmark/parse_stream.rb +48 -0
  15. data/benchmark/subjects/contacts.json +1 -0
  16. data/benchmark/subjects/contacts.marshal_dump +0 -0
  17. data/benchmark/subjects/contacts.yml +114685 -0
  18. data/benchmark/subjects/item.json +1 -0
  19. data/benchmark/subjects/ohai.json +1216 -0
  20. data/benchmark/subjects/twitter_search.json +1 -0
  21. data/benchmark/subjects/twitter_stream.json +430 -0
  22. data/benchmark/subjects/unicode.json +1 -0
  23. data/examples/http/twitter_search_api.rb +15 -0
  24. data/examples/http/twitter_stream_api.rb +25 -0
  25. data/examples/parsing/from_file.rb +14 -0
  26. data/examples/parsing/from_stdin.rb +9 -0
  27. data/examples/parsing/from_string.rb +15 -0
  28. data/ext/api/yajl_common.h +85 -0
  29. data/ext/api/yajl_gen.h +123 -0
  30. data/ext/api/yajl_parse.h +182 -0
  31. data/ext/extconf.rb +8 -0
  32. data/ext/yajl.c +157 -0
  33. data/ext/yajl_alloc.c +65 -0
  34. data/ext/yajl_alloc.h +50 -0
  35. data/ext/yajl_buf.c +119 -0
  36. data/ext/yajl_buf.h +73 -0
  37. data/ext/yajl_bytestack.h +85 -0
  38. data/ext/yajl_encode.c +179 -0
  39. data/ext/yajl_encode.h +44 -0
  40. data/ext/yajl_ext.c +774 -0
  41. data/ext/yajl_ext.h +74 -0
  42. data/ext/yajl_gen.c +290 -0
  43. data/ext/yajl_lex.c +744 -0
  44. data/ext/yajl_lex.h +135 -0
  45. data/ext/yajl_parser.c +447 -0
  46. data/ext/yajl_parser.h +79 -0
  47. data/lib/yajl.rb +80 -0
  48. data/lib/yajl/bzip2.rb +11 -0
  49. data/lib/yajl/bzip2/stream_reader.rb +29 -0
  50. data/lib/yajl/bzip2/stream_writer.rb +15 -0
  51. data/lib/yajl/deflate.rb +6 -0
  52. data/lib/yajl/deflate/stream_reader.rb +37 -0
  53. data/lib/yajl/deflate/stream_writer.rb +21 -0
  54. data/lib/yajl/gzip.rb +6 -0
  55. data/lib/yajl/gzip/stream_reader.rb +28 -0
  56. data/lib/yajl/gzip/stream_writer.rb +14 -0
  57. data/lib/yajl/http_stream.rb +101 -0
  58. data/lib/yajl/json_gem.rb +69 -0
  59. data/spec/encoding/encoding_spec.rb +186 -0
  60. data/spec/http/fixtures/http.bzip2.dump +0 -0
  61. data/spec/http/fixtures/http.deflate.dump +0 -0
  62. data/spec/http/fixtures/http.gzip.dump +0 -0
  63. data/spec/http/fixtures/http.raw.dump +12 -0
  64. data/spec/http/http_spec.rb +94 -0
  65. data/spec/json_gem_compatibility/compatibility_spec.rb +170 -0
  66. data/spec/parsing/active_support_spec.rb +68 -0
  67. data/spec/parsing/chunked_spec.rb +98 -0
  68. data/spec/parsing/fixtures/fail.15.json +1 -0
  69. data/spec/parsing/fixtures/fail.16.json +1 -0
  70. data/spec/parsing/fixtures/fail.17.json +1 -0
  71. data/spec/parsing/fixtures/fail.26.json +1 -0
  72. data/spec/parsing/fixtures/fail11.json +1 -0
  73. data/spec/parsing/fixtures/fail12.json +1 -0
  74. data/spec/parsing/fixtures/fail13.json +1 -0
  75. data/spec/parsing/fixtures/fail14.json +1 -0
  76. data/spec/parsing/fixtures/fail19.json +1 -0
  77. data/spec/parsing/fixtures/fail20.json +1 -0
  78. data/spec/parsing/fixtures/fail21.json +1 -0
  79. data/spec/parsing/fixtures/fail22.json +1 -0
  80. data/spec/parsing/fixtures/fail23.json +1 -0
  81. data/spec/parsing/fixtures/fail24.json +1 -0
  82. data/spec/parsing/fixtures/fail25.json +1 -0
  83. data/spec/parsing/fixtures/fail27.json +2 -0
  84. data/spec/parsing/fixtures/fail28.json +2 -0
  85. data/spec/parsing/fixtures/fail3.json +1 -0
  86. data/spec/parsing/fixtures/fail4.json +1 -0
  87. data/spec/parsing/fixtures/fail5.json +1 -0
  88. data/spec/parsing/fixtures/fail6.json +1 -0
  89. data/spec/parsing/fixtures/fail9.json +1 -0
  90. data/spec/parsing/fixtures/pass.array.json +6 -0
  91. data/spec/parsing/fixtures/pass.codepoints_from_unicode_org.json +1 -0
  92. data/spec/parsing/fixtures/pass.contacts.json +1 -0
  93. data/spec/parsing/fixtures/pass.db100.xml.json +1 -0
  94. data/spec/parsing/fixtures/pass.db1000.xml.json +1 -0
  95. data/spec/parsing/fixtures/pass.dc_simple_with_comments.json +11 -0
  96. data/spec/parsing/fixtures/pass.deep_arrays.json +1 -0
  97. data/spec/parsing/fixtures/pass.difficult_json_c_test_case.json +1 -0
  98. data/spec/parsing/fixtures/pass.difficult_json_c_test_case_with_comments.json +1 -0
  99. data/spec/parsing/fixtures/pass.doubles.json +1 -0
  100. data/spec/parsing/fixtures/pass.empty_array.json +1 -0
  101. data/spec/parsing/fixtures/pass.empty_string.json +1 -0
  102. data/spec/parsing/fixtures/pass.escaped_bulgarian.json +4 -0
  103. data/spec/parsing/fixtures/pass.escaped_foobar.json +1 -0
  104. data/spec/parsing/fixtures/pass.item.json +1 -0
  105. data/spec/parsing/fixtures/pass.json-org-sample1.json +23 -0
  106. data/spec/parsing/fixtures/pass.json-org-sample2.json +11 -0
  107. data/spec/parsing/fixtures/pass.json-org-sample3.json +26 -0
  108. data/spec/parsing/fixtures/pass.json-org-sample4-nows.json +88 -0
  109. data/spec/parsing/fixtures/pass.json-org-sample4.json +89 -0
  110. data/spec/parsing/fixtures/pass.json-org-sample5.json +27 -0
  111. data/spec/parsing/fixtures/pass.map-spain.xml.json +1 -0
  112. data/spec/parsing/fixtures/pass.ns-invoice100.xml.json +1 -0
  113. data/spec/parsing/fixtures/pass.ns-soap.xml.json +1 -0
  114. data/spec/parsing/fixtures/pass.numbers-fp-4k.json +6 -0
  115. data/spec/parsing/fixtures/pass.numbers-fp-64k.json +61 -0
  116. data/spec/parsing/fixtures/pass.numbers-int-4k.json +11 -0
  117. data/spec/parsing/fixtures/pass.numbers-int-64k.json +154 -0
  118. data/spec/parsing/fixtures/pass.twitter-search.json +1 -0
  119. data/spec/parsing/fixtures/pass.twitter-search2.json +1 -0
  120. data/spec/parsing/fixtures/pass.unicode.json +3315 -0
  121. data/spec/parsing/fixtures/pass.yelp.json +1 -0
  122. data/spec/parsing/fixtures/pass1.json +56 -0
  123. data/spec/parsing/fixtures/pass2.json +1 -0
  124. data/spec/parsing/fixtures/pass3.json +6 -0
  125. data/spec/parsing/fixtures_spec.rb +45 -0
  126. data/spec/parsing/one_off_spec.rb +58 -0
  127. data/spec/spec_helper.rb +11 -0
  128. data/yajl-ruby.gemspec +176 -0
  129. metadata +196 -0
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ Makefile
2
+ *.o
3
+ *.dylib
4
+ *.bundle
5
+ TODO.txt
data/CHANGELOG.md ADDED
@@ -0,0 +1,164 @@
1
+ # Changelog
2
+
3
+ ## 0.5.5 (June 17th, 2009)
4
+ * Introduction of the JSON gem API compatibility layer
5
+ ** NOTE: this isn't a 1:1 compatibility API, the goal was to be compatible with as many of the projects using the JSON gem as possible - not the JSON gem API itself
6
+ ** the compatibility API must be explicitly enabled by requiring 'yajl/json_gem' in your project
7
+ ** JSON.parse, JSON.generate, and the #to_json instance method extension to ruby's primitive classes are all included
8
+ * Fix Yajl::Encoder to ensure map keys are strings
9
+ * Encoding multiple JSON objects to a single stream doesn't separate by a newline character anymore
10
+ * Yajl::Encoder now checks for the existence of, and will call #to_json on any non-primitive object
11
+
12
+ ## 0.5.4 (June 16th, 2009)
13
+ * Yajl::Parser's :symbolize_keys option now defaults to false
14
+ * remove use of sprintf for a little speed improvement while parsing
15
+
16
+ ## 0.5.3 (June 7th, 2009)
17
+ * The IO parameter for Yajl::Encode#encode is now optional, and accepts a block
18
+ ** it will return the resulting JSON string if no IO is passed to stream to
19
+ ** if a block is passed, it will call and pass it the resulting JSON string
20
+ * Yajl::Parser#parse can now parse from a String as well as an IO
21
+ * Added and updated lot of in-code documentation.
22
+ ** all the C code exposed to Ruby should now have comments
23
+ * Added :symbolize_keys option to the Yajl::Parser class, which defaults to true.
24
+ ** Having this option enabled has shown around an 18% speedup in parsing time according to my benchmarks
25
+
26
+ ## 0.5.2 (May 30th, 2009)
27
+ * Added class helper methods Yajl::Encoder.encode(obj, io) and Yajl::Parser.parse(io)
28
+ * added tests for the above
29
+ * Updated Twitter streaming example to have a less verbose output
30
+ * Patch Yajl so encoding can continue as a stream
31
+ * IE: multiple objects encoded onto the same IO
32
+ * added a test for the above
33
+ * Set the internal read buffer size back down to 8kb by default
34
+ * Added an internal write buffer size (set to 8kb by default) which is used to throttle writes to the output stream
35
+ * This is to fix a major performance bug/issue with the IO#write C method in ruby 1.9.x (I've opened a bug with them about it)
36
+ * Fixed a typo in a one-off parsing spec test
37
+ * Updated benchmarks to work properly in 1.9 (required removal ActiveSupport benchmarking for now)
38
+ * Updated spec tests to respect ridiculous differences in hash key ordering between 1.8 and 1.9
39
+
40
+
41
+ ## 0.5.1 (May 25th, 2009)
42
+ * added some more tests for the new API
43
+ * inlined a couple of hot functions used in parsing for a little speedup
44
+ * updates to readme, reflecting changes in API
45
+ * version bump to push another gem build
46
+
47
+ ## 0.5.0 (May 25th, 2009)
48
+ * Refactored internal API so the caller can specify initialization options for the Parser and Encoder respectively. Two new classes were introduced as a result - Yajl::Parser and Yajl::Encoder. The newly refactored codebase is cleaner, thread-safe and removed all of the hack-code that was trickled around to make things work in the previous implementation. She's much more seaworthy now cap'n!
49
+ * Yajl::Parser.new accepts two options, :allow_comments and :check_utf8 which both default to true
50
+ * Yajl::Encoder.new accepts two options, :pretty and :indent which default to false and " " respectively
51
+ * cleaned up a lot of state code, that to my knowledge prevented yajl-ruby from being used in a thread-safe environment.
52
+ * added deprecated messaging to Yajl::Stream.parse and Yajl::Stream.encode - these will likely go away before 0.6.0
53
+ * fixed a bug in the chunked http response parser regarding partially received chunks
54
+ * added a Twitter Search API example showing off the HttpStream API
55
+
56
+ ## 0.4.9 (May 20th, 2009)
57
+ * fixed some parser state bugs surfaced by edge cases
58
+ * added support for Chunked HTTP response bodies in Yajl::HttpStream
59
+ * added support for passing a block to Yajl::HttpStream.get that will be used as a callback whenever a JSON object is parsed off the stream (even if there is more than one!)
60
+ * added an examples folder, and put an example using the Twitter Streaming API in there to start
61
+ * added some more spec tests, this time around Chunked parsing and continuously parsing multiple JSON strings
62
+
63
+ ## 0.4.8 (May 18th, 2009)
64
+ * fixed a totally bone-head compilation problem, I created for myself ;)
65
+
66
+ ## 0.4.7 (May 18th, 2009)
67
+ * Bundling Yajl sources to remove the need to install them (and CMake) separately (Thank you Lloyd!!!) This means you can now simply install the gem and be off and running
68
+ * Added some spec tests for Yajl::HttpStream
69
+ * Added some spec tests for Yajl::Stream.encode
70
+ * added some more thank you's, where credit's due - in the readme
71
+ * updated the unicode.json file to reflect a "real-life" JSON response
72
+ * reorganized spec tests into their functional areas
73
+ * added an rcov rake task to generate code coverage output
74
+
75
+ ## 0.4.6 (May 17th, 2009)
76
+ * Applied a patch from benburkert (http://github.com/benburkert) to fix HTTP Basic Auth in Yajl::HttpStream.get
77
+
78
+ ## 0.4.5 (May 17th, 2009)
79
+ * added Yajl::Stream.encode(hash, io)
80
+ * generates a JSON string stream, and writes to IO
81
+ * compressed StreamWriter helpers added as well
82
+ * fixed a pretty lame segfault in (x86_64 only?) ubuntu/linux
83
+ * changed the compiled extension to have a more specific name (yajl_ext) for easier loading
84
+ * removed forced-load of .bundle file, for the rest of the planet aside from OSX users
85
+ * added some more benchmarks to compare to other forms of serialization in Ruby
86
+ * various readme updates
87
+
88
+ ## 0.4.4 (May 12th, 2009)
89
+ * NOTE: Breaking API change:
90
+ * renamed Yajl::GzipStreamReader to Yajl::Gzip::StreamReader
91
+ * added Yajl::Bzip2::StreamReader
92
+ * depends on the bzip2-ruby gem if you want to use it, if not Yajl::Bzip2 won't be loaded
93
+ * added Yajl::Deflate::StreamReader
94
+ * actually uses Zlib::Inflate for stream decompression
95
+ * added parse(io) class methods to Yajl::Gzip::StreamReader and Yajl::Bzip2::StreamReader as a helper for parsing compressed streams.
96
+ * updated Yajl::HttpStream to request responses compressed as deflate and bzip2 in addition to gzip
97
+ * fixed a bug regarding parsing Integers as Floats (so 123456 would have be parsed and returned as 123456.0)
98
+ * fixed a bug which caused a segfault in ruby's GC during string replacement in Yajl::Gzip and Yajl::Bzip2's StreamReader#read methods
99
+ * added support for user-specified User-Agent strings in Yajl::HttpStream
100
+
101
+ ## 0.4.3 (May 2nd, 2009)
102
+ * adding text/plain as an allowed mime-type for Yajl::HttpStream for webservers that respond with it instead of application/json (ahem...Yelp...)
103
+ * renamed specs folder to spec for no reason at all
104
+
105
+ ## 0.4.2 (April 30th, 2009)
106
+ * Yajl::HttpStream is now sending "proper" http request headers
107
+ * Yajl::HttpStream will request HTTP-Basic auth if credentials are provided in the passed URI
108
+ * cleanup requires
109
+
110
+ ## 0.4.1 (April 30th, 2009)
111
+ * fixed a typo in the stream.rb benchmark file
112
+ * fixed a bug in Yajl::Stream.parse that was causing "strange" Ruby malloc errors on large files, with large strings
113
+ * added Yajl::GzipStreamReader as a wrapper around Zlib::GzipReader to allow for standard IO#read behavior
114
+ * this allows Yajl::Stream to read off of a Gzip stream directly
115
+
116
+ ## 0.4.0 (April 29th, 2009)
117
+ * NOTE: Breaking API change:
118
+ * refactored Stream parsing methods out of Yajl::Native into Yajl::Stream
119
+ * removed Yajl::Native namespace/module
120
+ * Addition of Yajl::HttpStream module
121
+ * This module is for streaming JSON HTTP responses directly into Yajl (as they're being received) for increased awesomeness
122
+ * it currently supports basic get requests with Yajl::HttpStream.get(uri)
123
+ * it also supports (and prefers) output compressed (gzip) responses
124
+ * Addition Yajl::Chunked module
125
+ * This module is for feeding Yajl JSON pieces at a time, instead of an entire IO object
126
+ * This works very well in environments like an EventMachine app where data is received in chunks by design
127
+ * decreased read buffer for Yajl::Stream from 8kb to 4kb
128
+
129
+ ## 0.3.4 (April 24th, 2009)
130
+ * turned Unicode checks back on in the Yajl parser now that it's fixed (thanks Lloyd!)
131
+ * this also bumps the yajl version dependency requirement to 1.0.4
132
+ * better guessing of Integer/Float from number found instead of just trying to create a BigNum no matter what
133
+ * changed extconf.rb to fail Makefile creation if yajl isn't found
134
+ * added a test to check for parsing Infinity due to a Float overflow
135
+
136
+ ## 0.3.3 (April 24th, 2009)
137
+ * 1.9 compatibility
138
+
139
+ ## 0.3.2 (April 24th, 2009)
140
+ * version bump: forgot to include yajl.c in the gem
141
+
142
+ ## 0.3.1 (April 23rd, 2009)
143
+ * fixed borked gemspec
144
+
145
+ ## 0.3.0 (April 23rd, 2009)
146
+ * slight refactor of ActiveSupport tests to better reflect how they actually exist in ActiveSupport
147
+ * typo correction in the changelog which had the years in 2008
148
+ * added some initial spec tests
149
+ * ported some from ActiveSupport to ensure proper compatibility
150
+ * included 57 JSON fixtures to test against, all of which pass
151
+ * changed parser config to not check for invalid unicode characters as Ruby is going to do this anyway (?). This resolves the remaining test failures around unicode.
152
+ * changed how the parser was dealing with numbers to prevent overflows
153
+ * added an exception class Yajl::ParseError which is now used in place of simply printing to STDERR upon a parsing error
154
+ * renamed a couple of JSON test files in the benchmark folder to better represent their contents
155
+ * misc README updates
156
+
157
+ ## 0.2.1 (April 23rd, 2009)
158
+ * fixed parsing bug - also fixed failing ActiveSupport test failures (except for the unicode one, which is an issue in Yajl itself)
159
+
160
+ ## 0.2.0 (April 22nd, 2009)
161
+ * updated gemspec and README
162
+
163
+ ## 0.1.0 (April 21st, 2009)
164
+ * initial release - gemified
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2009 Brian Lopez - http://github.com/brianmario
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,264 @@
1
+ = YAJL C Bindings for Ruby
2
+
3
+ This gem (although not in gem form just yet) is a C binding to the excellent YAJL JSON parsing and generation library.
4
+
5
+ You can read more info at the projects website http://lloydforge.org/projects/yajl or check out it's codes at http://github.com/lloyd/yajl.
6
+
7
+ == Features
8
+
9
+ * 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.
10
+ * Parse and encode *multiple* JSON objects to and from streams or strings continuously.
11
+ * JSON gem compatibility API - allows yajl-ruby to be used as a drop-in replacement for the JSON gem
12
+ * Basic HTTP client (only GET requests supported for now) which parses JSON directly off the response body *as it's being received*
13
+ * ~3.5x faster than JSON.generate
14
+ * ~1.9x faster than JSON.parse
15
+ * ~4.5x faster than YAML.load
16
+ * ~377.5x faster than YAML.dump
17
+ * ~1.5x faster than Marshal.load
18
+ * ~2x faster than Marshal.dump
19
+
20
+ == How to install
21
+
22
+ Install it like any other gem hosted at the Githubs like so:
23
+
24
+ (more instructions here: http://gems.github.com)
25
+
26
+ sudo gem install brianmario-yajl-ruby
27
+
28
+ == Example of use
29
+
30
+ First, you're probably gonna want to require it:
31
+
32
+ require 'yajl'
33
+
34
+ === Parsing
35
+
36
+ Then maybe parse some JSON from:
37
+
38
+ a File IO
39
+
40
+ json = File.new('test.json', 'r')
41
+ parser = Yajl::Parser.new
42
+ hash = parser.parse(json)
43
+
44
+ or maybe a StringIO
45
+
46
+ json = StringIO.new("...some JSON...")
47
+ parser = Yajl::Parser.new
48
+ hash = parser.parse(json)
49
+
50
+ or maybe STDIN
51
+
52
+ cat someJsonFile.json | ruby -ryajl -e "puts Yajl::Parser.new.parse(STDIN).inspect"
53
+
54
+
55
+ Or lets say you didn't have access to the IO object that contained JSON data, but instead
56
+ only had access to chunks of it at a time. No problem!
57
+
58
+ (Assume we're in an EventMachine::Connection instance)
59
+
60
+ def post_init
61
+ @parser = Yajl::Parser.new
62
+ end
63
+
64
+ def object_parsed(obj)
65
+ puts "Sometimes one pays most for the things one gets for nothing. - Albert Einstein"
66
+ puts obj.inspect
67
+ end
68
+
69
+ def connection_completed
70
+ # once a full JSON object has been parsed from the stream
71
+ # object_parsed will be called, and passed the constructed object
72
+ @parser.on_parse_complete = method(:object_parsed)
73
+ end
74
+
75
+ def receive_data(data)
76
+ # continue passing chunks
77
+ @parser << data
78
+ end
79
+
80
+
81
+ Or how about a JSON API HTTP request?
82
+ 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!
83
+
84
+ require 'uri'
85
+ require 'yajl/http_stream'
86
+
87
+ url = URI.parse("http://search.twitter.com/search.json?q=engineyard")
88
+ results = Yajl::HttpStream.get(url)
89
+
90
+ Or do the same request, with Gzip and Deflate output compression support (also supports Bzip2, if loaded):
91
+ (this does the same raw socket Request, but transparently parses the compressed response body)
92
+
93
+ require 'uri'
94
+ require 'yajl/gzip'
95
+ require 'yajl/deflate'
96
+ require 'yajl/http_stream'
97
+
98
+ url = URI.parse("http://search.twitter.com/search.json?q=engineyard")
99
+ results = Yajl::HttpStream.get(url)
100
+
101
+ Since yajl-ruby parses JSON as a stream, supporting API's like Twitter's Streaming API are a piece-of-cake.
102
+ You can simply supply a block to Yajl::HttpStream.get, which is used as the callback for when a JSON object has been
103
+ 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).
104
+ The code below is all that's needed to make the request and stream unserialized Ruby hashes off the response, continuously.
105
+
106
+ require 'uri'
107
+ require 'yajl/http_stream'
108
+
109
+ uri = URI.parse("http://#{username}:#{password}@stream.twitter.com/spritzer.json")
110
+ Yajl::HttpStream.get(uri) do |hash|
111
+ puts hash.inspect
112
+ end
113
+
114
+ Or how about parsing directly from a compressed file?
115
+
116
+ require 'yajl/bzip2'
117
+
118
+ file = File.new('some.json.bz2', 'r')
119
+ result = Yajl::Bzip2::StreamReader.parse(file)
120
+
121
+ === Encoding
122
+
123
+ 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).
124
+
125
+ This allows you to encode JSON as a stream, writing directly to a socket
126
+
127
+ socket = TCPSocket.new(192.168.1.101, 9000)
128
+ hash = {:foo => 12425125, :bar => "some string", ... }
129
+ encoder = Yajl::Encoder.new
130
+ Yajl::Encoder.encode(hash, socket)
131
+
132
+ Or what if you wanted to compress the stream over the wire?
133
+
134
+ require 'yajl/gzip'
135
+ socket = TCPSocket.new(192.168.1.101, 9000)
136
+ hash = {:foo => 12425125, :bar => "some string", ... }
137
+ Yajl::Gzip::StreamWriter.encode(hash, socket)
138
+
139
+ Or what about encoding multiple objects to JSON over the same stream?
140
+ This example will encode and send 50 JSON objects over the same stream, continuously.
141
+
142
+ socket = TCPSocket.new(192.168.1.101, 9000)
143
+ encoder = Yajl::Encoder.new
144
+ 50.times do
145
+ hash = {:current_time => Time.now.to_f, :foo => 12425125}
146
+ encoder.encode(hash, socket)
147
+ end
148
+
149
+ You can also use Yajl::Bzip2::StreamWriter and Yajl::Deflate::StreamWriter. So you can pick whichever fits your CPU/bandwidth sweet-spot.
150
+
151
+ == JSON gem Compatibility API
152
+
153
+ The JSON gem compatibility API isn't enabled by default. You have to explicitly require it like so:
154
+
155
+ require 'yajl/json_gem'
156
+
157
+ That's right, you can just replace "require 'json'" with the line above and you're done!
158
+
159
+ This will require yajl-ruby itself, as well as enable it's JSON gem compatibility API.
160
+
161
+ This includes the following API:
162
+
163
+ JSON.parse, JSON.generate, JSON.pretty_generate, JSON.load, JSON.dump
164
+ and all of the #to_json instance method overrides for Ruby's primitive objects
165
+
166
+ Once the compatibility API is enabled, you're existing or new project should work as if the JSON gem itself were being used. Only you'll be using Yajl ;)
167
+
168
+ There are a lot more possibilities that I'd love to see other gems/plugins for someday.
169
+
170
+ Some ideas are:
171
+ * parsing logs in JSON format
172
+ * a Rails plugin (http://github.com/technoweenie/yajl-rails)
173
+ * builtin Rails 3 support?
174
+ * Rack middleware (ideally the JSON body could be handed to the parser while it's still being received)
175
+ * use with ohai (http://github.com/brianmario/ohai)
176
+ * JSON API clients (http://github.com/brianmario/crack, http://github.com/brianmario/freckle-api)
177
+ * Patch Marshal#load and Marshal#dump to use JSON? ;)
178
+ * etc...
179
+
180
+ == Benchmarks
181
+
182
+ After I finished implementation - this library performs close to the same as the current JSON.parse (C gem) does on small/medium files.
183
+
184
+ But on larger files, and higher amounts of iteration, this library was around 2x faster than JSON.parse.
185
+
186
+ The main benefit of this library is in it's memory usage.
187
+ Since it's able to parse the stream in chunks, it's memory requirements are very, very low.
188
+
189
+ Here's what parsing a 2.43MB JSON file off the filesystem 20 times looks like:
190
+
191
+ === Memory Usage
192
+
193
+ ==== Average
194
+
195
+ * Yajl::Parser#parse: 32MB
196
+ * JSON.parse: 54MB
197
+ * ActiveSupport::JSON.decode: 63MB
198
+
199
+ ==== Peak
200
+
201
+ * Yajl::Parser#parse: 32MB
202
+ * JSON.parse: 57MB
203
+ * ActiveSupport::JSON.decode: 67MB
204
+
205
+ === Parse Time
206
+
207
+ * Yajl::Parser#parse: 4.54s
208
+ * JSON.parse: 5.47s
209
+ * ActiveSupport::JSON.decode: 64.42s
210
+
211
+ === Encode Time
212
+
213
+ * Yajl::Encoder#encode: 3.59s
214
+ * JSON#to_json: 6.2s
215
+ * ActiveSupport::JSON.encode: 45.58s
216
+
217
+ === Compared to YAML
218
+
219
+ NOTE: I converted the 2.4MB JSON file to YAML for this test.
220
+
221
+ ==== Parse Time (from their respective formats)
222
+
223
+ * Yajl::Parser#parse: 4.33s
224
+ * JSON.parse: 5.37s
225
+ * YAML.load: 19.47s
226
+
227
+ ==== Encode Time (to their respective formats)
228
+
229
+ * Yajl::Encoder#encode: 3.47s
230
+ * JSON#to_json: 6.6s
231
+ * YAML.dump(obj, io): 1309.93s
232
+
233
+ === Compared to Marshal.load/Marshal.dump
234
+
235
+ NOTE: I converted the 2.4MB JSON file to a Hash and a dump file from Marshal.dump for this test.
236
+
237
+ ==== Parse Time (from their respective formats)
238
+
239
+ * Yajl::Parser#parse: 4.54s
240
+ * JSON.parse: 7.40s
241
+ * Marshal.load: 7s
242
+
243
+ ==== Encode Time (to their respective formats)
244
+
245
+ * Yajl::Encoder#encode: 2.39s
246
+ * JSON#to_json: 8.37s
247
+ * Marshal.dump: 4.66s
248
+
249
+ == Third Party Sources Bundled
250
+
251
+ This project includes code from the BSD licensed yajl project, copyright 2007-2009 Lloyd Hilaiel
252
+
253
+ == Special Thanks
254
+
255
+ 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!
256
+
257
+ * Lloyd Hilaiel - http://github.com/lloyd - for writing Yajl!!
258
+ * Josh Ferguson - http://github.com/besquared - for peer-pressuring me into getting back into C; it worked ;) Also tons of support over IM
259
+ * Jonathan Novak - http://github.com/cypriss - pointer-hacking help
260
+ * Tom Smith - http://github.com/rtomsmith - pointer-hacking help
261
+ * Rick 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! :)
262
+ * 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.
263
+ * benburkert - http://github.com/benburkert
264
+ * Aman Gupta - http://github.com/tmm1 - tons of suggestions and inspiration for the most recent features, and hopefully more to come ;)