brianmario-yajl-ruby 0.5.4 → 0.5.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +9 -0
- data/README.rdoc +49 -3
- data/VERSION.yml +1 -1
- data/benchmark/encode_json_and_marshal.rb +2 -2
- data/benchmark/parse_json_and_marshal.rb +9 -5
- data/benchmark/subjects/contacts.marshal_dump +0 -0
- data/ext/yajl_ext.c +245 -20
- data/ext/yajl_ext.h +13 -2
- data/ext/yajl_gen.c +1 -3
- data/lib/yajl/http_stream.rb +1 -1
- data/lib/yajl/json_gem.rb +69 -0
- data/lib/yajl.rb +1 -1
- data/spec/encoding/encoding_spec.rb +31 -16
- data/spec/json_gem_compatibility/compatibility_spec.rb +170 -0
- data/yajl-ruby.gemspec +6 -2
- metadata +6 -2
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
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
|
+
|
3
12
|
## 0.5.4 (June 16th, 2009)
|
4
13
|
* Yajl::Parser's :symbolize_keys option now defaults to false
|
5
14
|
* remove use of sprintf for a little speed improvement while parsing
|
data/README.rdoc
CHANGED
@@ -4,6 +4,19 @@ This gem (although not in gem form just yet) is a C binding to the excellent YAJ
|
|
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
|
|
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
|
+
|
7
20
|
== How to install
|
8
21
|
|
9
22
|
Install it like any other gem hosted at the Githubs like so:
|
@@ -114,7 +127,7 @@ This allows you to encode JSON as a stream, writing directly to a socket
|
|
114
127
|
socket = TCPSocket.new(192.168.1.101, 9000)
|
115
128
|
hash = {:foo => 12425125, :bar => "some string", ... }
|
116
129
|
encoder = Yajl::Encoder.new
|
117
|
-
Yajl::
|
130
|
+
Yajl::Encoder.encode(hash, socket)
|
118
131
|
|
119
132
|
Or what if you wanted to compress the stream over the wire?
|
120
133
|
|
@@ -135,7 +148,24 @@ This example will encode and send 50 JSON objects over the same stream, continuo
|
|
135
148
|
|
136
149
|
You can also use Yajl::Bzip2::StreamWriter and Yajl::Deflate::StreamWriter. So you can pick whichever fits your CPU/bandwidth sweet-spot.
|
137
150
|
|
138
|
-
|
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.
|
139
169
|
|
140
170
|
Some ideas are:
|
141
171
|
* parsing logs in JSON format
|
@@ -192,7 +222,7 @@ NOTE: I converted the 2.4MB JSON file to YAML for this test.
|
|
192
222
|
|
193
223
|
* Yajl::Parser#parse: 4.33s
|
194
224
|
* JSON.parse: 5.37s
|
195
|
-
* YAML.
|
225
|
+
* YAML.load: 19.47s
|
196
226
|
|
197
227
|
==== Encode Time (to their respective formats)
|
198
228
|
|
@@ -200,6 +230,22 @@ NOTE: I converted the 2.4MB JSON file to YAML for this test.
|
|
200
230
|
* JSON#to_json: 6.6s
|
201
231
|
* YAML.dump(obj, io): 1309.93s
|
202
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
|
+
|
203
249
|
== Third Party Sources Bundled
|
204
250
|
|
205
251
|
This project includes code from the BSD licensed yajl project, copyright 2007-2009 Lloyd Hilaiel
|
data/VERSION.yml
CHANGED
@@ -5,12 +5,12 @@ require 'yajl_ext'
|
|
5
5
|
require 'stringio'
|
6
6
|
require 'json'
|
7
7
|
|
8
|
-
|
8
|
+
times = ARGV[0] ? ARGV[0].to_i : 1
|
9
|
+
filename = 'benchmark/subjects/contacts.json'
|
9
10
|
json = File.new(filename, 'r')
|
10
11
|
hash = Yajl::Parser.new.parse(json)
|
11
12
|
json.close
|
12
13
|
|
13
|
-
times = ARGV[1] ? ARGV[1].to_i : 1
|
14
14
|
puts "Starting benchmark encoding #{filename} #{times} times\n\n"
|
15
15
|
Benchmark.bm { |x|
|
16
16
|
encoder = Yajl::Encoder.new
|
@@ -6,23 +6,26 @@ require 'json'
|
|
6
6
|
|
7
7
|
# JSON section
|
8
8
|
filename = 'benchmark/subjects/contacts.json'
|
9
|
+
marshal_filename = 'benchmark/subjects/contacts.marshal_dump'
|
9
10
|
json = File.new(filename, 'r')
|
11
|
+
marshal_file = File.new(marshal_filename, 'r')
|
10
12
|
|
11
13
|
# warm up the filesystem
|
12
14
|
json.read
|
13
15
|
json.rewind
|
16
|
+
marshal_file.read
|
17
|
+
marshal_file.rewind
|
14
18
|
|
15
19
|
hash = {}
|
16
20
|
|
17
21
|
times = ARGV[0] ? ARGV[0].to_i : 1
|
18
22
|
puts "Starting benchmark parsing #{File.size(filename)} bytes of JSON data #{times} times\n\n"
|
19
23
|
Benchmark.bm { |x|
|
20
|
-
parser = Yajl::Parser.new
|
21
24
|
x.report {
|
22
25
|
puts "Yajl::Parser#parse"
|
23
26
|
times.times {
|
24
27
|
json.rewind
|
25
|
-
hash =
|
28
|
+
hash = Yajl::Parser.new.parse(json)
|
26
29
|
}
|
27
30
|
}
|
28
31
|
x.report {
|
@@ -32,12 +35,13 @@ Benchmark.bm { |x|
|
|
32
35
|
JSON.parse(json.read, :max_nesting => false)
|
33
36
|
}
|
34
37
|
}
|
35
|
-
data = Marshal.dump(hash)
|
36
38
|
x.report {
|
37
39
|
puts "Marshal.load"
|
38
40
|
times.times {
|
39
|
-
|
41
|
+
marshal_file.rewind
|
42
|
+
Marshal.load(marshal_file)
|
40
43
|
}
|
41
44
|
}
|
42
45
|
}
|
43
|
-
json.close
|
46
|
+
json.close
|
47
|
+
marshal_file.close
|
Binary file
|
data/ext/yajl_ext.c
CHANGED
@@ -62,13 +62,13 @@ inline void yajl_set_static_value(void * ctx, VALUE val) {
|
|
62
62
|
|
63
63
|
void yajl_encode_part(yajl_gen hand, VALUE obj, VALUE io) {
|
64
64
|
VALUE str, outBuff, otherObj;
|
65
|
-
|
65
|
+
yajl_gen_status status;
|
66
66
|
int idx = 0;
|
67
67
|
const unsigned char * buffer;
|
68
68
|
unsigned int len;
|
69
69
|
|
70
70
|
if (io != Qnil) {
|
71
|
-
yajl_gen_get_buf(hand, &buffer, &len);
|
71
|
+
status = yajl_gen_get_buf(hand, &buffer, &len);
|
72
72
|
if (len >= WRITE_BUFSIZE) {
|
73
73
|
outBuff = rb_str_new((const char *)buffer, len);
|
74
74
|
rb_io_write(io, outBuff);
|
@@ -78,49 +78,55 @@ void yajl_encode_part(yajl_gen hand, VALUE obj, VALUE io) {
|
|
78
78
|
|
79
79
|
switch (TYPE(obj)) {
|
80
80
|
case T_HASH:
|
81
|
-
yajl_gen_map_open(hand);
|
81
|
+
status = yajl_gen_map_open(hand);
|
82
82
|
|
83
83
|
// TODO: itterate through keys in the hash
|
84
84
|
VALUE keys = rb_funcall(obj, intern_keys, 0);
|
85
|
-
VALUE entry;
|
85
|
+
VALUE entry, keyStr;
|
86
86
|
for(idx=0; idx<RARRAY_LEN(keys); idx++) {
|
87
87
|
entry = rb_ary_entry(keys, idx);
|
88
|
+
keyStr = rb_funcall(entry, intern_to_s, 0); // key must be a string
|
88
89
|
// the key
|
89
|
-
yajl_encode_part(hand,
|
90
|
+
yajl_encode_part(hand, keyStr, io);
|
90
91
|
// the value
|
91
92
|
yajl_encode_part(hand, rb_hash_aref(obj, entry), io);
|
92
93
|
}
|
93
94
|
|
94
|
-
yajl_gen_map_close(hand);
|
95
|
+
status = yajl_gen_map_close(hand);
|
95
96
|
break;
|
96
97
|
case T_ARRAY:
|
97
|
-
yajl_gen_array_open(hand);
|
98
|
+
status = yajl_gen_array_open(hand);
|
98
99
|
for(idx=0; idx<RARRAY_LEN(obj); idx++) {
|
99
100
|
otherObj = rb_ary_entry(obj, idx);
|
100
101
|
yajl_encode_part(hand, otherObj, io);
|
101
102
|
}
|
102
|
-
yajl_gen_array_close(hand);
|
103
|
+
status = yajl_gen_array_close(hand);
|
103
104
|
break;
|
104
105
|
case T_NIL:
|
105
|
-
yajl_gen_null(hand);
|
106
|
+
status = yajl_gen_null(hand);
|
106
107
|
break;
|
107
108
|
case T_TRUE:
|
108
|
-
yajl_gen_bool(hand, 1);
|
109
|
+
status = yajl_gen_bool(hand, 1);
|
109
110
|
break;
|
110
111
|
case T_FALSE:
|
111
|
-
yajl_gen_bool(hand, 0);
|
112
|
+
status = yajl_gen_bool(hand, 0);
|
112
113
|
break;
|
113
114
|
case T_FIXNUM:
|
114
115
|
case T_FLOAT:
|
115
116
|
case T_BIGNUM:
|
116
117
|
str = rb_funcall(obj, intern_to_s, 0);
|
117
|
-
|
118
|
-
|
118
|
+
status = yajl_gen_number(hand, RSTRING_PTR(str), (unsigned int)RSTRING_LEN(str));
|
119
|
+
break;
|
120
|
+
case T_STRING:
|
121
|
+
status = yajl_gen_string(hand, (const unsigned char *)RSTRING_PTR(obj), (unsigned int)RSTRING_LEN(obj));
|
119
122
|
break;
|
120
123
|
default:
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
+
if (rb_respond_to(obj, intern_to_json)) {
|
125
|
+
str = rb_funcall(obj, intern_to_json, 0);
|
126
|
+
} else {
|
127
|
+
str = rb_funcall(obj, intern_to_s, 0);
|
128
|
+
}
|
129
|
+
status = yajl_gen_string(hand, (const unsigned char *)RSTRING_PTR(str), (unsigned int)RSTRING_LEN(str));
|
124
130
|
break;
|
125
131
|
}
|
126
132
|
}
|
@@ -515,13 +521,228 @@ static VALUE rb_yajl_encoder_encode(int argc, VALUE * argv, VALUE self) {
|
|
515
521
|
return Qnil;
|
516
522
|
}
|
517
523
|
|
524
|
+
|
525
|
+
// JSON Gem compatibility
|
526
|
+
|
527
|
+
/*
|
528
|
+
* Document-class: Object
|
529
|
+
*/
|
530
|
+
/*
|
531
|
+
* Document-method: to_json
|
532
|
+
*
|
533
|
+
* call-seq: to_json(encoder=Yajl::Encoder.new)
|
534
|
+
*
|
535
|
+
* +encoder+ is an existing Yajl::Encoder used to encode JSON
|
536
|
+
*
|
537
|
+
* Encodes an instance of Object to JSON
|
538
|
+
*/
|
539
|
+
static VALUE rb_yajl_json_ext_object_to_json(int argc, VALUE * argv, VALUE self) {
|
540
|
+
VALUE rb_encoder;
|
541
|
+
rb_scan_args(argc, argv, "01", &rb_encoder);
|
542
|
+
if (rb_encoder == Qnil) {
|
543
|
+
rb_encoder = rb_yajl_encoder_new(0, NULL, cEncoder);
|
544
|
+
}
|
545
|
+
return rb_yajl_encoder_encode(1, &self, rb_encoder);
|
546
|
+
}
|
547
|
+
|
548
|
+
/*
|
549
|
+
* Document-class: Hash
|
550
|
+
*/
|
551
|
+
/*
|
552
|
+
* Document-method: to_json
|
553
|
+
*
|
554
|
+
* call-seq: to_json(encoder=Yajl::Encoder.new)
|
555
|
+
*
|
556
|
+
* +encoder+ is an existing Yajl::Encoder used to encode JSON
|
557
|
+
*
|
558
|
+
* Encodes an instance of Hash to JSON
|
559
|
+
*/
|
560
|
+
static VALUE rb_yajl_json_ext_hash_to_json(int argc, VALUE * argv, VALUE self) {
|
561
|
+
VALUE rb_encoder;
|
562
|
+
rb_scan_args(argc, argv, "01", &rb_encoder);
|
563
|
+
if (rb_encoder == Qnil) {
|
564
|
+
rb_encoder = rb_yajl_encoder_new(0, NULL, cEncoder);
|
565
|
+
}
|
566
|
+
return rb_yajl_encoder_encode(1, &self, rb_encoder);
|
567
|
+
}
|
568
|
+
|
569
|
+
/*
|
570
|
+
* Document-class: Array
|
571
|
+
*/
|
572
|
+
/*
|
573
|
+
* Document-method: to_json
|
574
|
+
*
|
575
|
+
* call-seq: to_json(encoder=Yajl::Encoder.new)
|
576
|
+
*
|
577
|
+
* +encoder+ is an existing Yajl::Encoder used to encode JSON
|
578
|
+
*
|
579
|
+
* Encodes an instance of Array to JSON
|
580
|
+
*/
|
581
|
+
static VALUE rb_yajl_json_ext_array_to_json(int argc, VALUE * argv, VALUE self) {
|
582
|
+
VALUE rb_encoder;
|
583
|
+
rb_scan_args(argc, argv, "01", &rb_encoder);
|
584
|
+
if (rb_encoder == Qnil) {
|
585
|
+
rb_encoder = rb_yajl_encoder_new(0, NULL, cEncoder);
|
586
|
+
}
|
587
|
+
return rb_yajl_encoder_encode(1, &self, rb_encoder);
|
588
|
+
}
|
589
|
+
|
590
|
+
/*
|
591
|
+
* Document-class: Fixnum
|
592
|
+
*/
|
593
|
+
/*
|
594
|
+
* Document-method: to_json
|
595
|
+
*
|
596
|
+
* call-seq: to_json(encoder=Yajl::Encoder.new)
|
597
|
+
*
|
598
|
+
* +encoder+ is an existing Yajl::Encoder used to encode JSON
|
599
|
+
*
|
600
|
+
* Encodes an instance of Fixnum to JSON
|
601
|
+
*/
|
602
|
+
static VALUE rb_yajl_json_ext_fixnum_to_json(int argc, VALUE * argv, VALUE self) {
|
603
|
+
VALUE rb_encoder;
|
604
|
+
rb_scan_args(argc, argv, "01", &rb_encoder);
|
605
|
+
if (rb_encoder == Qnil) {
|
606
|
+
rb_encoder = rb_yajl_encoder_new(0, NULL, cEncoder);
|
607
|
+
}
|
608
|
+
return rb_yajl_encoder_encode(1, &self, rb_encoder);
|
609
|
+
}
|
610
|
+
|
611
|
+
/*
|
612
|
+
* Document-class: Float
|
613
|
+
*/
|
614
|
+
/*
|
615
|
+
* Document-method: to_json
|
616
|
+
*
|
617
|
+
* call-seq: to_json(encoder=Yajl::Encoder.new)
|
618
|
+
*
|
619
|
+
* +encoder+ is an existing Yajl::Encoder used to encode JSON
|
620
|
+
*
|
621
|
+
* Encodes an instance of Float to JSON
|
622
|
+
*/
|
623
|
+
static VALUE rb_yajl_json_ext_float_to_json(int argc, VALUE * argv, VALUE self) {
|
624
|
+
VALUE rb_encoder;
|
625
|
+
rb_scan_args(argc, argv, "01", &rb_encoder);
|
626
|
+
if (rb_encoder == Qnil) {
|
627
|
+
rb_encoder = rb_yajl_encoder_new(0, NULL, cEncoder);
|
628
|
+
}
|
629
|
+
return rb_yajl_encoder_encode(1, &self, rb_encoder);
|
630
|
+
}
|
631
|
+
|
632
|
+
/*
|
633
|
+
* Document-class: String
|
634
|
+
*/
|
635
|
+
/*
|
636
|
+
* Document-method: to_json
|
637
|
+
*
|
638
|
+
* call-seq: to_json(encoder=Yajl::Encoder.new)
|
639
|
+
*
|
640
|
+
* +encoder+ is an existing Yajl::Encoder used to encode JSON
|
641
|
+
*
|
642
|
+
* Encodes an instance of TrueClass to JSON
|
643
|
+
*/
|
644
|
+
static VALUE rb_yajl_json_ext_string_to_json(int argc, VALUE * argv, VALUE self) {
|
645
|
+
VALUE rb_encoder;
|
646
|
+
rb_scan_args(argc, argv, "01", &rb_encoder);
|
647
|
+
if (rb_encoder == Qnil) {
|
648
|
+
rb_encoder = rb_yajl_encoder_new(0, NULL, cEncoder);
|
649
|
+
}
|
650
|
+
return rb_yajl_encoder_encode(1, &self, rb_encoder);
|
651
|
+
}
|
652
|
+
|
653
|
+
/*
|
654
|
+
* Document-class: TrueClass
|
655
|
+
*/
|
656
|
+
/*
|
657
|
+
* Document-method: to_json
|
658
|
+
*
|
659
|
+
* call-seq: to_json(encoder=Yajl::Encoder.new)
|
660
|
+
*
|
661
|
+
* +encoder+ is an existing Yajl::Encoder used to encode JSON
|
662
|
+
*
|
663
|
+
* Encodes an instance of TrueClass to JSON
|
664
|
+
*/
|
665
|
+
static VALUE rb_yajl_json_ext_true_to_json(int argc, VALUE * argv, VALUE self) {
|
666
|
+
VALUE rb_encoder;
|
667
|
+
rb_scan_args(argc, argv, "01", &rb_encoder);
|
668
|
+
if (rb_encoder == Qnil) {
|
669
|
+
rb_encoder = rb_yajl_encoder_new(0, NULL, cEncoder);
|
670
|
+
}
|
671
|
+
return rb_yajl_encoder_encode(1, &self, rb_encoder);
|
672
|
+
}
|
673
|
+
|
674
|
+
/*
|
675
|
+
* Document-class: FalseClass
|
676
|
+
*/
|
677
|
+
/*
|
678
|
+
* Document-method: to_json
|
679
|
+
*
|
680
|
+
* call-seq: to_json(encoder=Yajl::Encoder.new)
|
681
|
+
*
|
682
|
+
* +encoder+ is an existing Yajl::Encoder used to encode JSON
|
683
|
+
*
|
684
|
+
* Encodes an instance of FalseClass to JSON
|
685
|
+
*/
|
686
|
+
static VALUE rb_yajl_json_ext_false_to_json(int argc, VALUE * argv, VALUE self) {
|
687
|
+
VALUE rb_encoder;
|
688
|
+
rb_scan_args(argc, argv, "01", &rb_encoder);
|
689
|
+
if (rb_encoder == Qnil) {
|
690
|
+
rb_encoder = rb_yajl_encoder_new(0, NULL, cEncoder);
|
691
|
+
}
|
692
|
+
return rb_yajl_encoder_encode(1, &self, rb_encoder);
|
693
|
+
}
|
694
|
+
|
695
|
+
/*
|
696
|
+
* Document-class: NilClass
|
697
|
+
*/
|
698
|
+
/*
|
699
|
+
* Document-method: to_json
|
700
|
+
*
|
701
|
+
* call-seq: to_json(encoder=Yajl::Encoder.new)
|
702
|
+
*
|
703
|
+
* +encoder+ is an existing Yajl::Encoder used to encode JSON
|
704
|
+
*
|
705
|
+
* Encodes an instance of NilClass to JSON
|
706
|
+
*/
|
707
|
+
static VALUE rb_yajl_json_ext_nil_to_json(int argc, VALUE * argv, VALUE self) {
|
708
|
+
VALUE rb_encoder;
|
709
|
+
rb_scan_args(argc, argv, "01", &rb_encoder);
|
710
|
+
if (rb_encoder == Qnil) {
|
711
|
+
rb_encoder = rb_yajl_encoder_new(0, NULL, cEncoder);
|
712
|
+
}
|
713
|
+
return rb_yajl_encoder_encode(1, &self, rb_encoder);
|
714
|
+
}
|
715
|
+
|
716
|
+
/*
|
717
|
+
* Document-class: Yajl::Encoder
|
718
|
+
*/
|
719
|
+
/*
|
720
|
+
* Document-method: enable_json_gem_compatability
|
721
|
+
*
|
722
|
+
* call-seq: enable_json_gem_compatability
|
723
|
+
*
|
724
|
+
* Enables the JSON gem compatibility API
|
725
|
+
*/
|
726
|
+
static VALUE rb_yajl_encoder_enable_json_gem_ext(VALUE klass) {
|
727
|
+
rb_define_method(rb_cObject, "to_json", rb_yajl_json_ext_object_to_json, -1);
|
728
|
+
rb_define_method(rb_cHash, "to_json", rb_yajl_json_ext_hash_to_json, -1);
|
729
|
+
rb_define_method(rb_cArray, "to_json", rb_yajl_json_ext_array_to_json, -1);
|
730
|
+
rb_define_method(rb_cFixnum, "to_json", rb_yajl_json_ext_fixnum_to_json, -1);
|
731
|
+
rb_define_method(rb_cFloat, "to_json", rb_yajl_json_ext_float_to_json, -1);
|
732
|
+
rb_define_method(rb_cString, "to_json", rb_yajl_json_ext_string_to_json, -1);
|
733
|
+
rb_define_method(rb_cTrueClass, "to_json", rb_yajl_json_ext_true_to_json, -1);
|
734
|
+
rb_define_method(rb_cFalseClass, "to_json", rb_yajl_json_ext_false_to_json, -1);
|
735
|
+
rb_define_method(rb_cNilClass, "to_json", rb_yajl_json_ext_nil_to_json, -1);
|
736
|
+
return Qnil;
|
737
|
+
}
|
738
|
+
|
739
|
+
|
518
740
|
// Ruby Extension initializer
|
519
741
|
void Init_yajl_ext() {
|
520
742
|
mYajl = rb_define_module("Yajl");
|
521
743
|
|
522
|
-
|
523
|
-
|
524
|
-
cEncodeError = rb_define_class_under(mYajl, "EncodeError", rb_cStandardError);
|
744
|
+
cParseError = rb_define_class_under(mYajl, "ParseError", rb_eStandardError);
|
745
|
+
cEncodeError = rb_define_class_under(mYajl, "EncodeError", rb_eStandardError);
|
525
746
|
|
526
747
|
cParser = rb_define_class_under(mYajl, "Parser", rb_cObject);
|
527
748
|
rb_define_singleton_method(cParser, "new", rb_yajl_parser_new, -1);
|
@@ -536,14 +757,18 @@ void Init_yajl_ext() {
|
|
536
757
|
rb_define_method(cEncoder, "initialize", rb_yajl_encoder_init, -1);
|
537
758
|
rb_define_method(cEncoder, "encode", rb_yajl_encoder_encode, -1);
|
538
759
|
|
760
|
+
rb_define_singleton_method(cEncoder, "enable_json_gem_compatability", rb_yajl_encoder_enable_json_gem_ext, 0);
|
761
|
+
|
539
762
|
intern_io_read = rb_intern("read");
|
540
763
|
intern_eof = rb_intern("eof?");
|
541
764
|
intern_call = rb_intern("call");
|
542
765
|
intern_keys = rb_intern("keys");
|
543
766
|
intern_to_s = rb_intern("to_s");
|
767
|
+
intern_to_json = rb_intern("to_json");
|
768
|
+
|
544
769
|
sym_allow_comments = rb_intern("allow_comments");
|
545
770
|
sym_check_utf8 = rb_intern("check_utf8");
|
546
771
|
sym_pretty = rb_intern("pretty");
|
547
772
|
sym_indent = rb_intern("indent");
|
548
773
|
sym_symbolize_keys = rb_intern("symbolize_keys");
|
549
|
-
}
|
774
|
+
}
|
data/ext/yajl_ext.h
CHANGED
@@ -6,7 +6,7 @@
|
|
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,
|
9
|
+
static ID intern_io_read, intern_eof, intern_call, intern_keys, intern_to_s, intern_to_json,
|
10
10
|
sym_allow_comments, sym_check_utf8, sym_pretty, sym_indent, sym_symbolize_keys;
|
11
11
|
|
12
12
|
#define GetParser(obj, sval) (sval = (struct yajl_parser_wrapper*)DATA_PTR(obj));
|
@@ -60,4 +60,15 @@ static VALUE rb_yajl_set_complete_cb(VALUE self, VALUE callback);
|
|
60
60
|
|
61
61
|
static VALUE rb_yajl_encoder_new(int argc, VALUE * argv, VALUE klass);
|
62
62
|
static VALUE rb_yajl_encoder_init(int argc, VALUE * argv, VALUE self);
|
63
|
-
static VALUE rb_yajl_encoder_encode(int argc, VALUE * argv, VALUE self);
|
63
|
+
static VALUE rb_yajl_encoder_encode(int argc, VALUE * argv, VALUE self);
|
64
|
+
|
65
|
+
static VALUE rb_yajl_json_ext_object_to_json(int argc, VALUE * argv, VALUE self);
|
66
|
+
static VALUE rb_yajl_json_ext_hash_to_json(int argc, VALUE * argv, VALUE self);
|
67
|
+
static VALUE rb_yajl_json_ext_array_to_json(int argc, VALUE * argv, VALUE self);
|
68
|
+
static VALUE rb_yajl_json_ext_fixnum_to_json(int argc, VALUE * argv, VALUE self);
|
69
|
+
static VALUE rb_yajl_json_ext_float_to_json(int argc, VALUE * argv, VALUE self);
|
70
|
+
static VALUE rb_yajl_json_ext_string_to_json(int argc, VALUE * argv, VALUE self);
|
71
|
+
static VALUE rb_yajl_json_ext_true_to_json(int argc, VALUE * argv, VALUE self);
|
72
|
+
static VALUE rb_yajl_json_ext_false_to_json(int argc, VALUE * argv, VALUE self);
|
73
|
+
static VALUE rb_yajl_json_ext_nil_to_json(int argc, VALUE * argv, VALUE self);
|
74
|
+
static VALUE rb_yajl_encoder_enable_json_gem_ext(VALUE klass);
|
data/ext/yajl_gen.c
CHANGED
@@ -152,9 +152,7 @@ yajl_gen_free(yajl_gen g)
|
|
152
152
|
break; \
|
153
153
|
} \
|
154
154
|
|
155
|
-
#define FINAL_NEWLINE
|
156
|
-
if (g->state[g->depth] == yajl_gen_start) \
|
157
|
-
yajl_buf_append(g->buf, "\n", 1);
|
155
|
+
#define FINAL_NEWLINE
|
158
156
|
|
159
157
|
yajl_gen_status
|
160
158
|
yajl_gen_integer(yajl_gen g, long int number)
|
data/lib/yajl/http_stream.rb
CHANGED
@@ -7,7 +7,7 @@ module Yajl
|
|
7
7
|
# are streamed directly into Yajl.
|
8
8
|
class HttpStream
|
9
9
|
|
10
|
-
# This Exception is thrown when an HTTP response isn't
|
10
|
+
# This Exception is thrown when an HTTP response isn't in ALLOWED_MIME_TYPES
|
11
11
|
# and therefore cannot be parsed.
|
12
12
|
class InvalidContentType < Exception; end
|
13
13
|
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'yajl' unless defined?(Yajl::Parser)
|
3
|
+
|
4
|
+
# NOTE: this is probably temporary until I can split out the JSON compat C code into it's own
|
5
|
+
# extension that can be included when this file is.
|
6
|
+
Yajl::Encoder.enable_json_gem_compatability
|
7
|
+
|
8
|
+
module JSON
|
9
|
+
|
10
|
+
class ParserError < Yajl::ParseError; end
|
11
|
+
|
12
|
+
def self.parse(str, opts={})
|
13
|
+
begin
|
14
|
+
Yajl::Parser.parse(str, opts)
|
15
|
+
rescue Yajl::ParseError => e
|
16
|
+
raise JSON::ParserError, e.message
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.generate(obj, opts={})
|
21
|
+
begin
|
22
|
+
options_map = {}
|
23
|
+
if opts.has_key?(:indent)
|
24
|
+
options_map[:pretty] = true
|
25
|
+
options_map[:indent] = opts[:indent]
|
26
|
+
end
|
27
|
+
Yajl::Encoder.encode(obj, options_map)
|
28
|
+
rescue Yajl::ParseError => e
|
29
|
+
raise JSON::ParserError, e.message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.pretty_generate(obj, opts={})
|
34
|
+
begin
|
35
|
+
options_map = {}
|
36
|
+
options_map[:pretty] = true
|
37
|
+
options_map[:indent] = opts[:indent] if opts.has_key?(:indent)
|
38
|
+
Yajl::Encoder.encode(obj, options_map)
|
39
|
+
rescue Yajl::ParseError => e
|
40
|
+
raise JSON::ParserError, e.message
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.load(input, *args)
|
45
|
+
begin
|
46
|
+
Yajl::Parser.parse(input)
|
47
|
+
rescue Yajl::ParseError => e
|
48
|
+
raise JSON::ParserError, e.message
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.dump(obj, io=nil, *args)
|
53
|
+
begin
|
54
|
+
Yajl::Encoder.encode(obj, io)
|
55
|
+
rescue Yajl::ParseError => e
|
56
|
+
raise JSON::ParserError, e.message
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
module ::Kernel
|
62
|
+
def JSON(object, opts = {})
|
63
|
+
if object.respond_to? :to_s
|
64
|
+
JSON.parse(object.to_s, opts)
|
65
|
+
else
|
66
|
+
JSON.generate(object, opts)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/yajl.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
|
3
3
|
|
4
|
+
class Dummy2
|
5
|
+
def to_json
|
6
|
+
"hawtness"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
4
10
|
describe "Yajl JSON encoder" do
|
5
11
|
FILES = Dir[File.dirname(__FILE__)+'/../../benchmark/subjects/*.json']
|
6
12
|
|
@@ -56,9 +62,9 @@ describe "Yajl JSON encoder" do
|
|
56
62
|
end
|
57
63
|
|
58
64
|
it "should encode with :pretty turned on and a single space indent, to an IO" do
|
59
|
-
output = "{\n \"foo\": {\n \"name\": \"bar\",\n \"id\": 1234\n }\n}
|
65
|
+
output = "{\n \"foo\": {\n \"name\": \"bar\",\n \"id\": 1234\n }\n}"
|
60
66
|
if RUBY_VERSION.include?('1.9') # FIXME
|
61
|
-
output = "{\n \"foo\": {\n \"id\": 1234,\n \"name\": \"bar\"\n }\n}
|
67
|
+
output = "{\n \"foo\": {\n \"id\": 1234,\n \"name\": \"bar\"\n }\n}"
|
62
68
|
end
|
63
69
|
obj = {:foo => {:id => 1234, :name => "bar"}}
|
64
70
|
io = StringIO.new
|
@@ -69,9 +75,9 @@ describe "Yajl JSON encoder" do
|
|
69
75
|
end
|
70
76
|
|
71
77
|
it "should encode with :pretty turned on and a single space indent, and return a String" do
|
72
|
-
output = "{\n \"foo\": {\n \"name\": \"bar\",\n \"id\": 1234\n }\n}
|
78
|
+
output = "{\n \"foo\": {\n \"name\": \"bar\",\n \"id\": 1234\n }\n}"
|
73
79
|
if RUBY_VERSION.include?('1.9') # FIXME
|
74
|
-
output = "{\n \"foo\": {\n \"id\": 1234,\n \"name\": \"bar\"\n }\n}
|
80
|
+
output = "{\n \"foo\": {\n \"id\": 1234,\n \"name\": \"bar\"\n }\n}"
|
75
81
|
end
|
76
82
|
obj = {:foo => {:id => 1234, :name => "bar"}}
|
77
83
|
encoder = Yajl::Encoder.new(:pretty => true, :indent => ' ')
|
@@ -80,9 +86,9 @@ describe "Yajl JSON encoder" do
|
|
80
86
|
end
|
81
87
|
|
82
88
|
it "should encode with :pretty turned on and a tab character indent, to an IO" do
|
83
|
-
output = "{\n\t\"foo\": {\n\t\t\"name\": \"bar\",\n\t\t\"id\": 1234\n\t}\n}
|
89
|
+
output = "{\n\t\"foo\": {\n\t\t\"name\": \"bar\",\n\t\t\"id\": 1234\n\t}\n}"
|
84
90
|
if RUBY_VERSION.include?('1.9') # FIXME
|
85
|
-
output = "{\n\t\"foo\": {\n\t\t\"id\": 1234,\n\t\t\"name\": \"bar\"\n\t}\n}
|
91
|
+
output = "{\n\t\"foo\": {\n\t\t\"id\": 1234,\n\t\t\"name\": \"bar\"\n\t}\n}"
|
86
92
|
end
|
87
93
|
obj = {:foo => {:id => 1234, :name => "bar"}}
|
88
94
|
io = StringIO.new
|
@@ -93,9 +99,9 @@ describe "Yajl JSON encoder" do
|
|
93
99
|
end
|
94
100
|
|
95
101
|
it "should encode with :pretty turned on and a tab character indent, and return a String" do
|
96
|
-
output = "{\n\t\"foo\": {\n\t\t\"name\": \"bar\",\n\t\t\"id\": 1234\n\t}\n}
|
102
|
+
output = "{\n\t\"foo\": {\n\t\t\"name\": \"bar\",\n\t\t\"id\": 1234\n\t}\n}"
|
97
103
|
if RUBY_VERSION.include?('1.9') # FIXME
|
98
|
-
output = "{\n\t\"foo\": {\n\t\t\"id\": 1234,\n\t\t\"name\": \"bar\"\n\t}\n}
|
104
|
+
output = "{\n\t\"foo\": {\n\t\t\"id\": 1234,\n\t\t\"name\": \"bar\"\n\t}\n}"
|
99
105
|
end
|
100
106
|
obj = {:foo => {:id => 1234, :name => "bar"}}
|
101
107
|
encoder = Yajl::Encoder.new(:pretty => true, :indent => "\t")
|
@@ -104,9 +110,9 @@ describe "Yajl JSON encoder" do
|
|
104
110
|
end
|
105
111
|
|
106
112
|
it "should encode with it's class method with :pretty and a tab character indent options set, to an IO" do
|
107
|
-
output = "{\n\t\"foo\": {\n\t\t\"name\": \"bar\",\n\t\t\"id\": 1234\n\t}\n}
|
113
|
+
output = "{\n\t\"foo\": {\n\t\t\"name\": \"bar\",\n\t\t\"id\": 1234\n\t}\n}"
|
108
114
|
if RUBY_VERSION.include?('1.9') # FIXME
|
109
|
-
output = "{\n\t\"foo\": {\n\t\t\"id\": 1234,\n\t\t\"name\": \"bar\"\n\t}\n}
|
115
|
+
output = "{\n\t\"foo\": {\n\t\t\"id\": 1234,\n\t\t\"name\": \"bar\"\n\t}\n}"
|
110
116
|
end
|
111
117
|
obj = {:foo => {:id => 1234, :name => "bar"}}
|
112
118
|
io = StringIO.new
|
@@ -116,9 +122,9 @@ describe "Yajl JSON encoder" do
|
|
116
122
|
end
|
117
123
|
|
118
124
|
it "should encode with it's class method with :pretty and a tab character indent options set, and return a String" do
|
119
|
-
output = "{\n\t\"foo\": {\n\t\t\"name\": \"bar\",\n\t\t\"id\": 1234\n\t}\n}
|
125
|
+
output = "{\n\t\"foo\": {\n\t\t\"name\": \"bar\",\n\t\t\"id\": 1234\n\t}\n}"
|
120
126
|
if RUBY_VERSION.include?('1.9') # FIXME
|
121
|
-
output = "{\n\t\"foo\": {\n\t\t\"id\": 1234,\n\t\t\"name\": \"bar\"\n\t}\n}
|
127
|
+
output = "{\n\t\"foo\": {\n\t\t\"id\": 1234,\n\t\t\"name\": \"bar\"\n\t}\n}"
|
122
128
|
end
|
123
129
|
obj = {:foo => {:id => 1234, :name => "bar"}}
|
124
130
|
output = Yajl::Encoder.encode(obj, :pretty => true, :indent => "\t")
|
@@ -126,9 +132,9 @@ describe "Yajl JSON encoder" do
|
|
126
132
|
end
|
127
133
|
|
128
134
|
it "should encode with it's class method with :pretty and a tab character indent options set, to a block" do
|
129
|
-
output = "{\n\t\"foo\": {\n\t\t\"name\": \"bar\",\n\t\t\"id\": 1234\n\t}\n}
|
135
|
+
output = "{\n\t\"foo\": {\n\t\t\"name\": \"bar\",\n\t\t\"id\": 1234\n\t}\n}"
|
130
136
|
if RUBY_VERSION.include?('1.9') # FIXME
|
131
|
-
output = "{\n\t\"foo\": {\n\t\t\"id\": 1234,\n\t\t\"name\": \"bar\"\n\t}\n}
|
137
|
+
output = "{\n\t\"foo\": {\n\t\t\"id\": 1234,\n\t\t\"name\": \"bar\"\n\t}\n}"
|
132
138
|
end
|
133
139
|
obj = {:foo => {:id => 1234, :name => "bar"}}
|
134
140
|
output = ''
|
@@ -147,9 +153,9 @@ describe "Yajl JSON encoder" do
|
|
147
153
|
encoder.encode(obj, io)
|
148
154
|
end
|
149
155
|
io.rewind
|
150
|
-
output = "{\"baz\":1234,\"foo\":\"bar\"}
|
156
|
+
output = "{\"baz\":1234,\"foo\":\"bar\"}{\"baz\":1234,\"foo\":\"bar\"}{\"baz\":1234,\"foo\":\"bar\"}{\"baz\":1234,\"foo\":\"bar\"}{\"baz\":1234,\"foo\":\"bar\"}"
|
151
157
|
if RUBY_VERSION.include?('1.9') # FIXME
|
152
|
-
output = "{\"foo\":\"bar\",\"baz\":1234}
|
158
|
+
output = "{\"foo\":\"bar\",\"baz\":1234}{\"foo\":\"bar\",\"baz\":1234}{\"foo\":\"bar\",\"baz\":1234}{\"foo\":\"bar\",\"baz\":1234}{\"foo\":\"bar\",\"baz\":1234}"
|
153
159
|
end
|
154
160
|
io.read.should == output
|
155
161
|
end
|
@@ -168,4 +174,13 @@ describe "Yajl JSON encoder" do
|
|
168
174
|
end
|
169
175
|
json_output.should == output
|
170
176
|
end
|
177
|
+
|
178
|
+
it "should encode all map keys as strings" do
|
179
|
+
Yajl::Encoder.encode({1=>1}).should eql("{\"1\":1}")
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should check for and call #to_json if it exists on custom objects" do
|
183
|
+
d = Dummy2.new
|
184
|
+
Yajl::Encoder.encode({:foo => d}).should eql('{"foo":"hawtness"}')
|
185
|
+
end
|
171
186
|
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
|
3
|
+
|
4
|
+
class Dummy; end
|
5
|
+
|
6
|
+
describe "JSON Gem compatability API" do
|
7
|
+
it "shoud not mixin #to_json on base objects until compatability has been enabled" do
|
8
|
+
d = Dummy.new
|
9
|
+
|
10
|
+
d.respond_to?(:to_json).should_not be_true
|
11
|
+
"".respond_to?(:to_json).should_not be_true
|
12
|
+
1.respond_to?(:to_json).should_not be_true
|
13
|
+
"1.5".to_f.respond_to?(:to_json).should_not be_true
|
14
|
+
[].respond_to?(:to_json).should_not be_true
|
15
|
+
{:foo => "bar"}.respond_to?(:to_json).should_not be_true
|
16
|
+
true.respond_to?(:to_json).should_not be_true
|
17
|
+
false.respond_to?(:to_json).should_not be_true
|
18
|
+
nil.respond_to?(:to_json).should_not be_true
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should mixin #to_json on base objects after compatability has been enabled" do
|
22
|
+
Yajl::Encoder.enable_json_gem_compatability
|
23
|
+
d = Dummy.new
|
24
|
+
|
25
|
+
d.respond_to?(:to_json).should be_true
|
26
|
+
"".respond_to?(:to_json).should be_true
|
27
|
+
1.respond_to?(:to_json).should be_true
|
28
|
+
"1.5".to_f.respond_to?(:to_json).should be_true
|
29
|
+
[].respond_to?(:to_json).should be_true
|
30
|
+
{:foo => "bar"}.respond_to?(:to_json).should be_true
|
31
|
+
true.respond_to?(:to_json).should be_true
|
32
|
+
false.respond_to?(:to_json).should be_true
|
33
|
+
nil.respond_to?(:to_json).should be_true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should require yajl/json_gem to enable the compatability API" do
|
37
|
+
require 'yajl/json_gem'
|
38
|
+
|
39
|
+
defined?(JSON).should be_true
|
40
|
+
|
41
|
+
JSON.respond_to?(:parse).should be_true
|
42
|
+
JSON.respond_to?(:generate).should be_true
|
43
|
+
JSON.respond_to?(:pretty_generate).should be_true
|
44
|
+
JSON.respond_to?(:load).should be_true
|
45
|
+
JSON.respond_to?(:dump).should be_true
|
46
|
+
end
|
47
|
+
|
48
|
+
context "ported tests for Unicode" do
|
49
|
+
it "should be able to encode and parse unicode" do
|
50
|
+
pending if RUBY_VERSION.include?('1.9') # FIXME: Some string encoding problem with 1.9
|
51
|
+
'""'.should eql(''.to_json)
|
52
|
+
'"\\b"'.should eql("\b".to_json)
|
53
|
+
'"\u0001"'.should eql(0x1.chr.to_json)
|
54
|
+
'"\u001F"'.should eql(0x1f.chr.to_json)
|
55
|
+
'" "'.should eql(' '.to_json)
|
56
|
+
"\"#{0x7f.chr}\"".should eql(0x7f.chr.to_json)
|
57
|
+
utf8 = [ "© ≠ €! \01" ]
|
58
|
+
json = '["© ≠ €! \u0001"]'
|
59
|
+
json.should eql(utf8.to_json)
|
60
|
+
utf8.should eql(JSON.parse(json))
|
61
|
+
utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
|
62
|
+
json = "[\"あいうえお\"]"
|
63
|
+
json.should eql(utf8.to_json)
|
64
|
+
utf8.should eql(JSON.parse(json))
|
65
|
+
utf8 = ['საქართველო']
|
66
|
+
json = "[\"საქართველო\"]"
|
67
|
+
json.should eql(utf8.to_json)
|
68
|
+
utf8.should eql(JSON.parse(json))
|
69
|
+
'["Ã"]'.should eql(JSON.generate(["Ã"]))
|
70
|
+
["€"].should eql(JSON.parse('["\u20ac"]'))
|
71
|
+
utf8_str = "\xf0\xa0\x80\x81"
|
72
|
+
utf8 = [utf8_str]
|
73
|
+
json = "[\"#{utf8_str}\"]"
|
74
|
+
json.should eql(JSON.generate(utf8))
|
75
|
+
utf8.should eql(JSON.parse(json))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "ported tests for generation" do
|
80
|
+
before(:all) do
|
81
|
+
@hash = {
|
82
|
+
'a' => 2,
|
83
|
+
'b' => 3.141,
|
84
|
+
'c' => 'c',
|
85
|
+
'd' => [ 1, "b", 3.14 ],
|
86
|
+
'e' => { 'foo' => 'bar' },
|
87
|
+
'g' => "blah",
|
88
|
+
'h' => 1000.0,
|
89
|
+
'i' => 0.001
|
90
|
+
}
|
91
|
+
|
92
|
+
@json2 = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},"g":"blah","h":1000.0,"i":0.001}'
|
93
|
+
|
94
|
+
@json3 = %{
|
95
|
+
{
|
96
|
+
"a": 2,
|
97
|
+
"b": 3.141,
|
98
|
+
"c": "c",
|
99
|
+
"d": [1, "b", 3.14],
|
100
|
+
"e": {"foo": "bar"},
|
101
|
+
"g": "blah",
|
102
|
+
"h": 1000.0,
|
103
|
+
"i": 0.001
|
104
|
+
}
|
105
|
+
}.chomp
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should be able to unparse" do
|
109
|
+
json = JSON.generate(@hash)
|
110
|
+
JSON.parse(@json2).should == JSON.parse(json)
|
111
|
+
parsed_json = JSON.parse(json)
|
112
|
+
@hash.should == parsed_json
|
113
|
+
json = JSON.generate({1=>2})
|
114
|
+
'{"1":2}'.should eql(json)
|
115
|
+
parsed_json = JSON.parse(json)
|
116
|
+
{"1"=>2}.should == parsed_json
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should be able to unparse pretty" do
|
120
|
+
json = JSON.pretty_generate(@hash)
|
121
|
+
JSON.parse(@json3).should == JSON.parse(json)
|
122
|
+
parsed_json = JSON.parse(json)
|
123
|
+
@hash.should == parsed_json
|
124
|
+
json = JSON.pretty_generate({1=>2})
|
125
|
+
test = "{\n \"1\": 2\n}".chomp
|
126
|
+
test.should == json
|
127
|
+
parsed_json = JSON.parse(json)
|
128
|
+
{"1"=>2}.should == parsed_json
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "ported fixture tests" do
|
133
|
+
fixtures = File.join(File.dirname(__FILE__), '../parsing/fixtures/*.json')
|
134
|
+
passed, failed = Dir[fixtures].partition { |f| f['pass'] }
|
135
|
+
JSON_PASSED = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
|
136
|
+
JSON_FAILED = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
|
137
|
+
|
138
|
+
JSON_FAILED.each do |name, source|
|
139
|
+
it "should not be able to parse #{File.basename(name)} as an IO" do
|
140
|
+
lambda {
|
141
|
+
JSON.parse(StringIO.new(source))
|
142
|
+
}.should raise_error(Yajl::ParseError)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
JSON_FAILED.each do |name, source|
|
147
|
+
it "should not be able to parse #{File.basename(name)} as a string" do
|
148
|
+
lambda {
|
149
|
+
JSON.parse(source)
|
150
|
+
}.should raise_error(Yajl::ParseError)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
JSON_PASSED.each do |name, source|
|
155
|
+
it "should be able to parse #{File.basename(name)} as an IO" do
|
156
|
+
lambda {
|
157
|
+
JSON.parse(StringIO.new(source))
|
158
|
+
}.should_not raise_error(Yajl::ParseError)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
JSON_PASSED.each do |name, source|
|
163
|
+
it "should be able to parse #{File.basename(name)} as a string" do
|
164
|
+
lambda {
|
165
|
+
JSON.parse(source)
|
166
|
+
}.should_not raise_error(Yajl::ParseError)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
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.5"
|
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-06-
|
9
|
+
s.date = %q{2009-06-18}
|
10
10
|
s.email = %q{seniorlopez@gmail.com}
|
11
11
|
s.extensions = ["ext/extconf.rb"]
|
12
12
|
s.extra_rdoc_files = [
|
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
|
|
28
28
|
"benchmark/parse_json_and_yaml.rb",
|
29
29
|
"benchmark/parse_stream.rb",
|
30
30
|
"benchmark/subjects/contacts.json",
|
31
|
+
"benchmark/subjects/contacts.marshal_dump",
|
31
32
|
"benchmark/subjects/contacts.yml",
|
32
33
|
"benchmark/subjects/item.json",
|
33
34
|
"benchmark/subjects/ohai.json",
|
@@ -69,12 +70,14 @@ Gem::Specification.new do |s|
|
|
69
70
|
"lib/yajl/gzip/stream_reader.rb",
|
70
71
|
"lib/yajl/gzip/stream_writer.rb",
|
71
72
|
"lib/yajl/http_stream.rb",
|
73
|
+
"lib/yajl/json_gem.rb",
|
72
74
|
"spec/encoding/encoding_spec.rb",
|
73
75
|
"spec/http/fixtures/http.bzip2.dump",
|
74
76
|
"spec/http/fixtures/http.deflate.dump",
|
75
77
|
"spec/http/fixtures/http.gzip.dump",
|
76
78
|
"spec/http/fixtures/http.raw.dump",
|
77
79
|
"spec/http/http_spec.rb",
|
80
|
+
"spec/json_gem_compatibility/compatibility_spec.rb",
|
78
81
|
"spec/parsing/active_support_spec.rb",
|
79
82
|
"spec/parsing/chunked_spec.rb",
|
80
83
|
"spec/parsing/fixtures/fail.15.json",
|
@@ -147,6 +150,7 @@ Gem::Specification.new do |s|
|
|
147
150
|
s.test_files = [
|
148
151
|
"spec/encoding/encoding_spec.rb",
|
149
152
|
"spec/http/http_spec.rb",
|
153
|
+
"spec/json_gem_compatibility/compatibility_spec.rb",
|
150
154
|
"spec/parsing/active_support_spec.rb",
|
151
155
|
"spec/parsing/chunked_spec.rb",
|
152
156
|
"spec/parsing/fixtures_spec.rb",
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brianmario-yajl-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.5
|
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-06-
|
13
|
+
date: 2009-06-18 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -38,6 +38,7 @@ files:
|
|
38
38
|
- benchmark/parse_json_and_yaml.rb
|
39
39
|
- benchmark/parse_stream.rb
|
40
40
|
- benchmark/subjects/contacts.json
|
41
|
+
- benchmark/subjects/contacts.marshal_dump
|
41
42
|
- benchmark/subjects/contacts.yml
|
42
43
|
- benchmark/subjects/item.json
|
43
44
|
- benchmark/subjects/ohai.json
|
@@ -79,12 +80,14 @@ files:
|
|
79
80
|
- lib/yajl/gzip/stream_reader.rb
|
80
81
|
- lib/yajl/gzip/stream_writer.rb
|
81
82
|
- lib/yajl/http_stream.rb
|
83
|
+
- lib/yajl/json_gem.rb
|
82
84
|
- spec/encoding/encoding_spec.rb
|
83
85
|
- spec/http/fixtures/http.bzip2.dump
|
84
86
|
- spec/http/fixtures/http.deflate.dump
|
85
87
|
- spec/http/fixtures/http.gzip.dump
|
86
88
|
- spec/http/fixtures/http.raw.dump
|
87
89
|
- spec/http/http_spec.rb
|
90
|
+
- spec/json_gem_compatibility/compatibility_spec.rb
|
88
91
|
- spec/parsing/active_support_spec.rb
|
89
92
|
- spec/parsing/chunked_spec.rb
|
90
93
|
- spec/parsing/fixtures/fail.15.json
|
@@ -178,6 +181,7 @@ summary: Ruby C bindings to the excellent Yajl JSON stream-based parser library.
|
|
178
181
|
test_files:
|
179
182
|
- spec/encoding/encoding_spec.rb
|
180
183
|
- spec/http/http_spec.rb
|
184
|
+
- spec/json_gem_compatibility/compatibility_spec.rb
|
181
185
|
- spec/parsing/active_support_spec.rb
|
182
186
|
- spec/parsing/chunked_spec.rb
|
183
187
|
- spec/parsing/fixtures_spec.rb
|