brianmario-yajl-ruby 0.5.4 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|