yajl-ruby 0.5.11 → 0.5.12
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.
- data/CHANGELOG.md +4 -0
- data/README.rdoc +45 -2
- data/VERSION.yml +2 -2
- data/ext/yajl_ext.c +36 -6
- data/ext/yajl_ext.h +3 -2
- data/lib/yajl.rb +1 -1
- data/spec/encoding/encoding_spec.rb +36 -0
- data/yajl-ruby.gemspec +3 -3
- metadata +4 -3
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.5.12 (July 31st, 2009)
|
4
|
+
* Add another option that can be passed to Yajl::Encoder's constructor (:terminator) to allow the caller some control over
|
5
|
+
when a full JSON string has been generated by the encoder. More information on it's use in the README
|
6
|
+
|
3
7
|
## 0.5.11 (July 14th, 2009)
|
4
8
|
* fixing a bug Aman found with to_json on non-primitive Ruby objects and double-quoting in the JSON compat API
|
5
9
|
|
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= YAJL C Bindings for Ruby
|
2
2
|
|
3
|
-
This gem
|
3
|
+
This gem is a C binding to the excellent YAJL JSON parsing and generation library.
|
4
4
|
|
5
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
6
|
|
@@ -27,6 +27,8 @@ Install it like any other gem hosted at the Githubs like so:
|
|
27
27
|
|
28
28
|
== Example of use
|
29
29
|
|
30
|
+
NOTE: I'm building up a collection of small examples in the examples (http://github.com/brianmario/yajl-ruby/tree/master/examples) folder.
|
31
|
+
|
30
32
|
First, you're probably gonna want to require it:
|
31
33
|
|
32
34
|
require 'yajl'
|
@@ -77,6 +79,11 @@ only had access to chunks of it at a time. No problem!
|
|
77
79
|
@parser << data
|
78
80
|
end
|
79
81
|
|
82
|
+
Or if you don't need to stream it, it'll just return the built object from the parse when it's done.
|
83
|
+
NOTE: if there are going to be multiple JSON strings in the input, you *must* specify a block or callback as this
|
84
|
+
is how yajl-ruby will hand you (the caller) each object as it's parsed off the input.
|
85
|
+
|
86
|
+
obj = Yajl::Parser.parse(str_or_io)
|
80
87
|
|
81
88
|
Or how about a JSON API HTTP request?
|
82
89
|
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!
|
@@ -150,6 +157,42 @@ This example will encode and send 50 JSON objects over the same stream, continuo
|
|
150
157
|
encoder.encode(hash, socket)
|
151
158
|
end
|
152
159
|
|
160
|
+
Using EventMachine and you want to encode and send in chunks?
|
161
|
+
(Assume we're in an EventMachine::Connection instance)
|
162
|
+
|
163
|
+
def post_init
|
164
|
+
# Passing a :terminator character will let us determine when the encoder
|
165
|
+
# is done encoding the current object
|
166
|
+
@encoder = Yajl::Encoder.new(:terminator => nil)
|
167
|
+
motd_contents = File.read("/path/to/motd.txt")
|
168
|
+
status = File.read("/path/to/huge/status_file.txt")
|
169
|
+
@motd = {:motd => motd_contents, :system_status => status}
|
170
|
+
end
|
171
|
+
|
172
|
+
def connection_completed
|
173
|
+
# The encoder will do it's best to hand you data in chunks that
|
174
|
+
# are around 8kb (but you may see some that are larger)
|
175
|
+
#
|
176
|
+
# It should be noted that you could have also assigned the _on_progress_ callback
|
177
|
+
# much like you can assign the _on_parse_complete_ callback with the parser class.
|
178
|
+
# Passing a block (like below) essentially tells the encoder to use that block
|
179
|
+
# as the callback normally assigned to _on_progress_.
|
180
|
+
#
|
181
|
+
# Send our MOTD and status
|
182
|
+
@encoder.encode(@motd) do |chunk|
|
183
|
+
if chunk.nil?
|
184
|
+
close_connection_after_writing
|
185
|
+
else
|
186
|
+
send_data(chunk)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
But to make things simple, you might just want to let yajl-ruby do all the hard work for you and just hand back
|
192
|
+
a string when it's finished. In that case, just don't provide and IO or block (or assign the on_progress callback).
|
193
|
+
|
194
|
+
str = Yajl::Encoder.encode(obj)
|
195
|
+
|
153
196
|
You can also use Yajl::Bzip2::StreamWriter and Yajl::Deflate::StreamWriter. So you can pick whichever fits your CPU/bandwidth sweet-spot.
|
154
197
|
|
155
198
|
== JSON gem Compatibility API
|
@@ -174,7 +217,7 @@ There are a lot more possibilities that I'd love to see other gems/plugins for s
|
|
174
217
|
Some ideas are:
|
175
218
|
* parsing logs in JSON format
|
176
219
|
* a Rails plugin (http://github.com/technoweenie/yajl-rails)
|
177
|
-
* builtin Rails 3
|
220
|
+
* builtin support in Rails 3?
|
178
221
|
* Rack middleware (ideally the JSON body could be handed to the parser while it's still being received)
|
179
222
|
* use with ohai (http://github.com/brianmario/ohai)
|
180
223
|
* JSON API clients (http://github.com/brianmario/crack, http://github.com/brianmario/freckle-api)
|
data/VERSION.yml
CHANGED
data/ext/yajl_ext.c
CHANGED
@@ -69,6 +69,7 @@ static void yajl_encoder_wrapper_free(void * wrapper) {
|
|
69
69
|
static void yajl_encoder_wrapper_mark(void * wrapper) {
|
70
70
|
struct yajl_encoder_wrapper * w = wrapper;
|
71
71
|
rb_gc_mark(w->on_progress_callback);
|
72
|
+
rb_gc_mark(w->terminator);
|
72
73
|
}
|
73
74
|
|
74
75
|
void yajl_encode_part(void * wrapper, VALUE obj, VALUE io) {
|
@@ -445,11 +446,17 @@ static VALUE rb_yajl_parser_set_complete_cb(VALUE self, VALUE callback) {
|
|
445
446
|
/*
|
446
447
|
* Document-method: new
|
447
448
|
*
|
448
|
-
* call-seq:
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
449
|
+
* call-seq: initialize([:pretty => false[, :indent => ' '][, :terminator => "\n"]])
|
450
|
+
*
|
451
|
+
* :pretty will enable/disable beautifying or "pretty priting" the output string.
|
452
|
+
*
|
453
|
+
* :indent is the character(s) used to indent the output string.
|
454
|
+
*
|
455
|
+
* :terminator allows you to specify a character to be used as the termination character after a full JSON string has been generated by
|
456
|
+
* the encoder. This would be especially useful when encoding in chunks (via a block or callback during the encode process), to be able to
|
457
|
+
* determine when the last chunk of the current encode is sent.
|
458
|
+
* If you specify this option to be nil, it will be ignored if encoding directly to an IO or simply returning a string. But if a block is used,
|
459
|
+
* the encoder will still pass it - I hope that makes sense ;).
|
453
460
|
*/
|
454
461
|
static VALUE rb_yajl_encoder_new(int argc, VALUE * argv, VALUE klass) {
|
455
462
|
struct yajl_encoder_wrapper * wrapper;
|
@@ -476,6 +483,11 @@ static VALUE rb_yajl_encoder_new(int argc, VALUE * argv, VALUE klass) {
|
|
476
483
|
obj = Data_Make_Struct(klass, struct yajl_encoder_wrapper, yajl_encoder_wrapper_mark, yajl_encoder_wrapper_free, wrapper);
|
477
484
|
wrapper->encoder = yajl_gen_alloc(&cfg, NULL);
|
478
485
|
wrapper->on_progress_callback = Qnil;
|
486
|
+
if (opts != Qnil && rb_funcall(opts, intern_has_key, 1, ID2SYM(sym_terminator)) == Qtrue) {
|
487
|
+
wrapper->terminator = rb_hash_aref(opts, ID2SYM(sym_terminator));
|
488
|
+
} else {
|
489
|
+
wrapper->terminator = 0;
|
490
|
+
}
|
479
491
|
rb_obj_call_init(obj, 0, 0);
|
480
492
|
return obj;
|
481
493
|
}
|
@@ -483,11 +495,17 @@ static VALUE rb_yajl_encoder_new(int argc, VALUE * argv, VALUE klass) {
|
|
483
495
|
/*
|
484
496
|
* Document-method: initialize
|
485
497
|
*
|
486
|
-
* call-seq: initialize([:pretty => false[, :indent => ' ']])
|
498
|
+
* call-seq: initialize([:pretty => false[, :indent => ' '][, :terminator => "\n"]])
|
487
499
|
*
|
488
500
|
* :pretty will enable/disable beautifying or "pretty priting" the output string.
|
489
501
|
*
|
490
502
|
* :indent is the character(s) used to indent the output string.
|
503
|
+
*
|
504
|
+
* :terminator allows you to specify a character to be used as the termination character after a full JSON string has been generated by
|
505
|
+
* the encoder. This would be especially useful when encoding in chunks (via a block or callback during the encode process), to be able to
|
506
|
+
* determine when the last chunk of the current encode is sent.
|
507
|
+
* If you specify this option to be nil, it will be ignored if encoding directly to an IO or simply returning a string. But if a block is used,
|
508
|
+
* the encoder will still pass it - I hope that makes sense ;).
|
491
509
|
*/
|
492
510
|
static VALUE rb_yajl_encoder_init(int argc, VALUE * argv, VALUE self) {
|
493
511
|
return self;
|
@@ -530,13 +548,23 @@ static VALUE rb_yajl_encoder_encode(int argc, VALUE * argv, VALUE self) {
|
|
530
548
|
yajl_gen_get_buf(wrapper->encoder, &buffer, &len);
|
531
549
|
outBuff = rb_str_new((const char *)buffer, len);
|
532
550
|
yajl_gen_clear(wrapper->encoder);
|
551
|
+
|
533
552
|
if (io != Qnil) {
|
534
553
|
rb_io_write(io, outBuff);
|
554
|
+
if (wrapper->terminator != 0 && wrapper->terminator != Qnil) {
|
555
|
+
rb_io_write(io, wrapper->terminator);
|
556
|
+
}
|
535
557
|
return Qnil;
|
536
558
|
} else if (blk != Qnil) {
|
537
559
|
rb_funcall(blk, intern_call, 1, outBuff);
|
560
|
+
if (wrapper->terminator != 0) {
|
561
|
+
rb_funcall(blk, intern_call, 1, wrapper->terminator);
|
562
|
+
}
|
538
563
|
return Qnil;
|
539
564
|
} else {
|
565
|
+
if (wrapper->terminator != 0 && wrapper->terminator != Qnil) {
|
566
|
+
rb_str_concat(outBuff, wrapper->terminator);
|
567
|
+
}
|
540
568
|
return outBuff;
|
541
569
|
}
|
542
570
|
return Qnil;
|
@@ -787,5 +815,7 @@ void Init_yajl_ext() {
|
|
787
815
|
sym_check_utf8 = rb_intern("check_utf8");
|
788
816
|
sym_pretty = rb_intern("pretty");
|
789
817
|
sym_indent = rb_intern("indent");
|
818
|
+
sym_terminator = rb_intern("terminator");
|
790
819
|
sym_symbolize_keys = rb_intern("symbolize_keys");
|
820
|
+
intern_has_key = rb_intern("has_key?");
|
791
821
|
}
|
data/ext/yajl_ext.h
CHANGED
@@ -6,8 +6,8 @@
|
|
6
6
|
#define WRITE_BUFSIZE 8092
|
7
7
|
|
8
8
|
static VALUE cParseError, cEncodeError, mYajl, cParser, cEncoder;
|
9
|
-
static ID intern_io_read, intern_eof, intern_call, intern_keys, intern_to_s, intern_to_json,
|
10
|
-
sym_allow_comments, sym_check_utf8, sym_pretty, sym_indent, sym_symbolize_keys;
|
9
|
+
static ID intern_io_read, intern_eof, intern_call, intern_keys, intern_to_s, intern_to_json, intern_has_key,
|
10
|
+
sym_allow_comments, sym_check_utf8, sym_pretty, sym_indent, sym_terminator, sym_symbolize_keys;
|
11
11
|
|
12
12
|
#define GetParser(obj, sval) (sval = (struct yajl_parser_wrapper*)DATA_PTR(obj));
|
13
13
|
#define GetEncoder(obj, sval) (sval = (struct yajl_encoder_wrapper*)DATA_PTR(obj));
|
@@ -53,6 +53,7 @@ struct yajl_parser_wrapper {
|
|
53
53
|
|
54
54
|
struct yajl_encoder_wrapper {
|
55
55
|
VALUE on_progress_callback;
|
56
|
+
VALUE terminator;
|
56
57
|
yajl_gen encoder;
|
57
58
|
};
|
58
59
|
|
data/lib/yajl.rb
CHANGED
@@ -187,4 +187,40 @@ describe "Yajl JSON encoder" do
|
|
187
187
|
it "should encode a hash where the key and value can be symbols" do
|
188
188
|
Yajl::Encoder.encode({:foo => :bar}).should eql('{"foo":"bar"}')
|
189
189
|
end
|
190
|
+
|
191
|
+
it "should encode using a newline or nil terminator" do
|
192
|
+
Yajl::Encoder.new(:terminator => "\n").encode({:foo => :bar}).should eql("{\"foo\":\"bar\"}\n")
|
193
|
+
Yajl::Encoder.new(:terminator => nil).encode({:foo => :bar}).should eql("{\"foo\":\"bar\"}")
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should encode using a newline or nil terminator, to an IO" do
|
197
|
+
s = StringIO.new
|
198
|
+
Yajl::Encoder.new(:terminator => "\n").encode({:foo => :bar}, s)
|
199
|
+
s.rewind
|
200
|
+
s.read.should eql("{\"foo\":\"bar\"}\n")
|
201
|
+
|
202
|
+
s = StringIO.new
|
203
|
+
Yajl::Encoder.new(:terminator => nil).encode({:foo => :bar}, s)
|
204
|
+
s.rewind
|
205
|
+
s.read.should eql("{\"foo\":\"bar\"}")
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should encode using a newline or nil terminator, using a block" do
|
209
|
+
s = StringIO.new
|
210
|
+
Yajl::Encoder.new(:terminator => "\n").encode({:foo => :bar}) do |chunk|
|
211
|
+
s << chunk
|
212
|
+
end
|
213
|
+
s.rewind
|
214
|
+
s.read.should eql("{\"foo\":\"bar\"}\n")
|
215
|
+
|
216
|
+
s = StringIO.new
|
217
|
+
nilpassed = false
|
218
|
+
Yajl::Encoder.new(:terminator => nil).encode({:foo => :bar}) do |chunk|
|
219
|
+
nilpassed = true if chunk.nil?
|
220
|
+
s << chunk
|
221
|
+
end
|
222
|
+
nilpassed.should be_true
|
223
|
+
s.rewind
|
224
|
+
s.read.should eql("{\"foo\":\"bar\"}")
|
225
|
+
end
|
190
226
|
end
|
data/yajl-ruby.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{yajl-ruby}
|
5
|
-
s.version = "0.5.
|
5
|
+
s.version = "0.5.12"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Brian Lopez", "Lloyd Hilaiel"]
|
9
|
-
s.date = %q{2009-07-
|
9
|
+
s.date = %q{2009-07-31}
|
10
10
|
s.email = %q{seniorlopez@gmail.com}
|
11
11
|
s.extensions = ["ext/extconf.rb"]
|
12
12
|
s.extra_rdoc_files = [
|
@@ -152,7 +152,7 @@ Gem::Specification.new do |s|
|
|
152
152
|
s.rdoc_options = ["--charset=UTF-8"]
|
153
153
|
s.require_paths = ["lib", "ext"]
|
154
154
|
s.rubyforge_project = %q{yajl-ruby}
|
155
|
-
s.rubygems_version = %q{1.3.
|
155
|
+
s.rubygems_version = %q{1.3.5}
|
156
156
|
s.summary = %q{Ruby C bindings to the excellent Yajl JSON stream-based parser library.}
|
157
157
|
s.test_files = [
|
158
158
|
"spec/encoding/encoding_spec.rb",
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yajl-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Lopez
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-07-
|
13
|
+
date: 2009-07-31 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -182,8 +182,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
182
182
|
requirements: []
|
183
183
|
|
184
184
|
rubyforge_project: yajl-ruby
|
185
|
-
rubygems_version: 1.3.
|
185
|
+
rubygems_version: 1.3.5
|
186
186
|
signing_key:
|
187
|
+
source:
|
187
188
|
specification_version: 3
|
188
189
|
summary: Ruby C bindings to the excellent Yajl JSON stream-based parser library.
|
189
190
|
test_files:
|