json_pure 1.1.9 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +7 -0
- data/README +316 -34
- data/Rakefile +48 -28
- data/VERSION +1 -1
- data/ext/json/ext/generator/generator.c +21 -5
- data/ext/json/ext/generator/unicode.c +3 -3
- data/ext/json/ext/parser/parser.c +142 -91
- data/ext/json/ext/parser/parser.rl +68 -17
- data/ext/json/ext/parser/unicode.c +2 -2
- data/lib/json/common.rb +32 -17
- data/lib/json/pure/generator.rb +24 -10
- data/lib/json/pure/parser.rb +35 -1
- data/lib/json/version.rb +1 -1
- data/tests/test_json.rb +25 -17
- data/tests/test_json_encoding.rb +67 -0
- data/tests/test_json_generate.rb +21 -7
- data/tests/test_json_rails.rb +1 -1
- metadata +7 -6
- data/doc-main.txt +0 -283
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
case ENV['JSON']
|
6
|
+
when 'pure' then require 'json/pure'
|
7
|
+
when 'ext' then require 'json/ext'
|
8
|
+
else require 'json'
|
9
|
+
end
|
10
|
+
require 'iconv'
|
11
|
+
|
12
|
+
class TC_JSONEncoding < Test::Unit::TestCase
|
13
|
+
include JSON
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@utf_8 = '["© ≠ €!"]'
|
17
|
+
@parsed = [ "© ≠ €!" ]
|
18
|
+
@utf_16_data = Iconv.iconv('utf-16be', 'utf-8', @parsed.first)
|
19
|
+
@generated = '["\u00a9 \u2260 \u20ac!"]'
|
20
|
+
if defined?(::Encoding)
|
21
|
+
@utf_8_ascii_8bit = @utf_8.dup.force_encoding(Encoding::ASCII_8BIT)
|
22
|
+
@utf_16be, = Iconv.iconv('utf-16be', 'utf-8', @utf_8)
|
23
|
+
@utf_16be_ascii_8bit = @utf_16be.dup.force_encoding(Encoding::ASCII_8BIT)
|
24
|
+
@utf_16le, = Iconv.iconv('utf-16le', 'utf-8', @utf_8)
|
25
|
+
@utf_16le_ascii_8bit = @utf_16le.dup.force_encoding(Encoding::ASCII_8BIT)
|
26
|
+
@utf_32be, = Iconv.iconv('utf-32be', 'utf-8', @utf_8)
|
27
|
+
@utf_32be_ascii_8bit = @utf_32be.dup.force_encoding(Encoding::ASCII_8BIT)
|
28
|
+
@utf_32le, = Iconv.iconv('utf-32le', 'utf-8', @utf_8)
|
29
|
+
@utf_32le_ascii_8bit = @utf_32le.dup.force_encoding(Encoding::ASCII_8BIT)
|
30
|
+
else
|
31
|
+
@utf_8_ascii_8bit = @utf_8.dup
|
32
|
+
@utf_16be, = Iconv.iconv('utf-16be', 'utf-8', @utf_8)
|
33
|
+
@utf_16be_ascii_8bit = @utf_16be.dup
|
34
|
+
@utf_16le, = Iconv.iconv('utf-16le', 'utf-8', @utf_8)
|
35
|
+
@utf_16le_ascii_8bit = @utf_16le.dup
|
36
|
+
@utf_32be, = Iconv.iconv('utf-32be', 'utf-8', @utf_8)
|
37
|
+
@utf_32be_ascii_8bit = @utf_32be.dup
|
38
|
+
@utf_32le, = Iconv.iconv('utf-32le', 'utf-8', @utf_8)
|
39
|
+
@utf_32le_ascii_8bit = @utf_32le.dup
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_parse
|
44
|
+
assert_equal @parsed, JSON.parse(@utf_8)
|
45
|
+
assert_equal @parsed, JSON.parse(@utf_16be)
|
46
|
+
assert_equal @parsed, JSON.parse(@utf_16le)
|
47
|
+
assert_equal @parsed, JSON.parse(@utf_32be)
|
48
|
+
assert_equal @parsed, JSON.parse(@utf_32le)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_parse_ascii_8bit
|
52
|
+
assert_equal @parsed, JSON.parse(@utf_8_ascii_8bit)
|
53
|
+
assert_equal @parsed, JSON.parse(@utf_16be_ascii_8bit)
|
54
|
+
assert_equal @parsed, JSON.parse(@utf_16le_ascii_8bit)
|
55
|
+
assert_equal @parsed, JSON.parse(@utf_32be_ascii_8bit)
|
56
|
+
assert_equal @parsed, JSON.parse(@utf_32le_ascii_8bit)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_generate
|
60
|
+
assert_equal @generated, JSON.generate(@parsed)
|
61
|
+
if defined?(::Encoding)
|
62
|
+
assert_equal @generated, JSON.generate(@utf_16_data)
|
63
|
+
else
|
64
|
+
assert_raises(JSON::GeneratorError) { JSON.generate(@utf_16_data) }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/tests/test_json_generate.rb
CHANGED
@@ -44,8 +44,8 @@ class TC_JSONGenerate < Test::Unit::TestCase
|
|
44
44
|
EOT
|
45
45
|
end
|
46
46
|
|
47
|
-
def
|
48
|
-
json =
|
47
|
+
def test_generate
|
48
|
+
json = generate(@hash)
|
49
49
|
assert_equal(JSON.parse(@json2), JSON.parse(json))
|
50
50
|
parsed_json = parse(json)
|
51
51
|
assert_equal(@hash, parsed_json)
|
@@ -53,10 +53,11 @@ EOT
|
|
53
53
|
assert_equal('{"1":2}', json)
|
54
54
|
parsed_json = parse(json)
|
55
55
|
assert_equal({"1"=>2}, parsed_json)
|
56
|
+
assert_raise(GeneratorError) { generate(666) }
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
-
json =
|
59
|
+
def test_generate_pretty
|
60
|
+
json = pretty_generate(@hash)
|
60
61
|
assert_equal(JSON.parse(@json3), JSON.parse(json))
|
61
62
|
parsed_json = parse(json)
|
62
63
|
assert_equal(@hash, parsed_json)
|
@@ -68,6 +69,19 @@ EOT
|
|
68
69
|
EOT
|
69
70
|
parsed_json = parse(json)
|
70
71
|
assert_equal({"1"=>2}, parsed_json)
|
72
|
+
assert_raise(GeneratorError) { pretty_generate(666) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_fast_generate
|
76
|
+
json = fast_generate(@hash)
|
77
|
+
assert_equal(JSON.parse(@json2), JSON.parse(json))
|
78
|
+
parsed_json = parse(json)
|
79
|
+
assert_equal(@hash, parsed_json)
|
80
|
+
json = fast_generate({1=>2})
|
81
|
+
assert_equal('{"1":2}', json)
|
82
|
+
parsed_json = parse(json)
|
83
|
+
assert_equal({"1"=>2}, parsed_json)
|
84
|
+
assert_raise(GeneratorError) { fast_generate(666) }
|
71
85
|
end
|
72
86
|
|
73
87
|
def test_states
|
@@ -89,17 +103,17 @@ EOT
|
|
89
103
|
def test_allow_nan
|
90
104
|
assert_raises(GeneratorError) { generate([JSON::NaN]) }
|
91
105
|
assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
|
92
|
-
|
106
|
+
assert_raises(GeneratorError) { fast_generate([JSON::NaN]) }
|
93
107
|
assert_raises(GeneratorError) { pretty_generate([JSON::NaN]) }
|
94
108
|
assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
|
95
109
|
assert_raises(GeneratorError) { generate([JSON::Infinity]) }
|
96
110
|
assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
|
97
|
-
|
111
|
+
assert_raises(GeneratorError) { fast_generate([JSON::Infinity]) }
|
98
112
|
assert_raises(GeneratorError) { pretty_generate([JSON::Infinity]) }
|
99
113
|
assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
|
100
114
|
assert_raises(GeneratorError) { generate([JSON::MinusInfinity]) }
|
101
115
|
assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
|
102
|
-
|
116
|
+
assert_raises(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
|
103
117
|
assert_raises(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
|
104
118
|
assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
|
105
119
|
end
|
data/tests/test_json_rails.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_pure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08
|
12
|
+
date: 2009-11-08 00:00:00 +01:00
|
13
13
|
default_executable: edit_json.rb
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -21,7 +21,7 @@ executables:
|
|
21
21
|
extensions: []
|
22
22
|
|
23
23
|
extra_rdoc_files:
|
24
|
-
-
|
24
|
+
- README
|
25
25
|
files:
|
26
26
|
- CHANGES
|
27
27
|
- bin/edit_json.rb
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- data/example.json
|
98
98
|
- data/index.html
|
99
99
|
- data/prototype.js
|
100
|
+
- tests/test_json_encoding.rb
|
100
101
|
- tests/test_json_addition.rb
|
101
102
|
- tests/fixtures/pass16.json
|
102
103
|
- tests/fixtures/fail4.json
|
@@ -135,7 +136,6 @@ files:
|
|
135
136
|
- tests/test_json_unicode.rb
|
136
137
|
- tests/test_json_fixtures.rb
|
137
138
|
- COPYING
|
138
|
-
- doc-main.txt
|
139
139
|
- install.rb
|
140
140
|
has_rdoc: true
|
141
141
|
homepage: http://json.rubyforge.org
|
@@ -146,7 +146,7 @@ rdoc_options:
|
|
146
146
|
- --title
|
147
147
|
- JSON -- A JSON implemention
|
148
148
|
- --main
|
149
|
-
-
|
149
|
+
- README
|
150
150
|
require_paths:
|
151
151
|
- lib
|
152
152
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -164,11 +164,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
164
|
requirements: []
|
165
165
|
|
166
166
|
rubyforge_project: json
|
167
|
-
rubygems_version: 1.3.
|
167
|
+
rubygems_version: 1.3.5
|
168
168
|
signing_key:
|
169
169
|
specification_version: 3
|
170
170
|
summary: A JSON implementation in Ruby
|
171
171
|
test_files:
|
172
|
+
- tests/test_json_encoding.rb
|
172
173
|
- tests/test_json_addition.rb
|
173
174
|
- tests/test_json_rails.rb
|
174
175
|
- tests/test_json.rb
|
data/doc-main.txt
DELETED
@@ -1,283 +0,0 @@
|
|
1
|
-
== json - JSON Implementation for Ruby
|
2
|
-
|
3
|
-
=== Description
|
4
|
-
|
5
|
-
This is a implementation of the JSON specification according to RFC 4627
|
6
|
-
(http://www.ietf.org/rfc/rfc4627.txt). Starting from version 1.0.0 on there
|
7
|
-
will be two variants available:
|
8
|
-
|
9
|
-
* A pure ruby variant, that relies on the iconv and the stringscan
|
10
|
-
extensions, which are both part of the ruby standard library.
|
11
|
-
* The quite a bit faster C extension variant, which is in parts implemented
|
12
|
-
in C and comes with its own unicode conversion functions and a parser
|
13
|
-
generated by the ragel state machine compiler
|
14
|
-
(http://www.cs.queensu.ca/~thurston/ragel).
|
15
|
-
|
16
|
-
Both variants of the JSON generator escape all non-ASCII an control
|
17
|
-
characters with \uXXXX escape sequences, and support UTF-16 surrogate pairs
|
18
|
-
in order to be able to generate the whole range of unicode code points. This
|
19
|
-
means that generated JSON text is encoded as UTF-8 (because ASCII is a subset
|
20
|
-
of UTF-8) and at the same time avoids decoding problems for receiving
|
21
|
-
endpoints, that don't expect UTF-8 encoded texts. On the negative side this
|
22
|
-
may lead to a bit longer strings than necessarry.
|
23
|
-
|
24
|
-
All strings, that are to be encoded as JSON strings, should be UTF-8 byte
|
25
|
-
sequences on the Ruby side. To encode raw binary strings, that aren't UTF-8
|
26
|
-
encoded, please use the to_json_raw_object method of String (which produces
|
27
|
-
an object, that contains a byte array) and decode the result on the receiving
|
28
|
-
endpoint.
|
29
|
-
|
30
|
-
=== Author
|
31
|
-
|
32
|
-
Florian Frank <mailto:flori@ping.de>
|
33
|
-
|
34
|
-
=== License
|
35
|
-
|
36
|
-
This software is distributed under the same license as Ruby itself, see
|
37
|
-
http://www.ruby-lang.org/en/LICENSE.txt.
|
38
|
-
|
39
|
-
=== Download
|
40
|
-
|
41
|
-
The latest version of this library can be downloaded at
|
42
|
-
|
43
|
-
* http://rubyforge.org/frs?group_id=953
|
44
|
-
|
45
|
-
Online Documentation should be located at
|
46
|
-
|
47
|
-
* http://json.rubyforge.org
|
48
|
-
|
49
|
-
=== Usage
|
50
|
-
|
51
|
-
To use JSON you can
|
52
|
-
require 'json'
|
53
|
-
to load the installed variant (either the extension 'json' or the pure
|
54
|
-
variant 'json_pure'). If you have installed the extension variant, you can
|
55
|
-
pick either the extension variant or the pure variant by typing
|
56
|
-
require 'json/ext'
|
57
|
-
or
|
58
|
-
require 'json/pure'
|
59
|
-
|
60
|
-
You can choose to load a set of common additions to ruby core's objects if
|
61
|
-
you
|
62
|
-
require 'json/add/core'
|
63
|
-
|
64
|
-
After requiring this you can, e. g., serialise/deserialise Ruby ranges:
|
65
|
-
|
66
|
-
JSON JSON(1..10) # => 1..10
|
67
|
-
|
68
|
-
To find out how to add JSON support to other or your own classes, read the
|
69
|
-
Examples section below.
|
70
|
-
|
71
|
-
To get the best compatibility to rails' JSON implementation, you can
|
72
|
-
require 'json/add/rails'
|
73
|
-
|
74
|
-
Both of the additions attempt to require 'json' (like above) first, if it has
|
75
|
-
not been required yet.
|
76
|
-
|
77
|
-
=== Speed Comparisons
|
78
|
-
|
79
|
-
I have created some benchmark results (see the benchmarks/data-p4-3Ghz
|
80
|
-
subdir of the package) for the JSON-parser to estimate the speed up in the C
|
81
|
-
extension:
|
82
|
-
|
83
|
-
Comparing times (call_time_mean):
|
84
|
-
1 ParserBenchmarkExt#parser 900 repeats:
|
85
|
-
553.922304770 ( real) -> 21.500x
|
86
|
-
0.001805307
|
87
|
-
2 ParserBenchmarkYAML#parser 1000 repeats:
|
88
|
-
224.513358139 ( real) -> 8.714x
|
89
|
-
0.004454078
|
90
|
-
3 ParserBenchmarkPure#parser 1000 repeats:
|
91
|
-
26.755020642 ( real) -> 1.038x
|
92
|
-
0.037376163
|
93
|
-
4 ParserBenchmarkRails#parser 1000 repeats:
|
94
|
-
25.763381731 ( real) -> 1.000x
|
95
|
-
0.038814780
|
96
|
-
calls/sec ( time) -> speed covers
|
97
|
-
secs/call
|
98
|
-
|
99
|
-
In the table above 1 is JSON::Ext::Parser, 2 is YAML.load with YAML
|
100
|
-
compatbile JSON document, 3 is is JSON::Pure::Parser, and 4 is
|
101
|
-
ActiveSupport::JSON.decode. The ActiveSupport JSON-decoder converts the
|
102
|
-
input first to YAML and then uses the YAML-parser, the conversion seems to
|
103
|
-
slow it down so much that it is only as fast as the JSON::Pure::Parser!
|
104
|
-
|
105
|
-
If you look at the benchmark data you can see that this is mostly caused by
|
106
|
-
the frequent high outliers - the median of the Rails-parser runs is still
|
107
|
-
overall smaller than the median of the JSON::Pure::Parser runs:
|
108
|
-
|
109
|
-
Comparing times (call_time_median):
|
110
|
-
1 ParserBenchmarkExt#parser 900 repeats:
|
111
|
-
800.592479481 ( real) -> 26.936x
|
112
|
-
0.001249075
|
113
|
-
2 ParserBenchmarkYAML#parser 1000 repeats:
|
114
|
-
271.002390644 ( real) -> 9.118x
|
115
|
-
0.003690004
|
116
|
-
3 ParserBenchmarkRails#parser 1000 repeats:
|
117
|
-
30.227910865 ( real) -> 1.017x
|
118
|
-
0.033082008
|
119
|
-
4 ParserBenchmarkPure#parser 1000 repeats:
|
120
|
-
29.722384421 ( real) -> 1.000x
|
121
|
-
0.033644676
|
122
|
-
calls/sec ( time) -> speed covers
|
123
|
-
secs/call
|
124
|
-
|
125
|
-
I have benchmarked the JSON-Generator as well. This generated a few more
|
126
|
-
values, because there are different modes that also influence the achieved
|
127
|
-
speed:
|
128
|
-
|
129
|
-
Comparing times (call_time_mean):
|
130
|
-
1 GeneratorBenchmarkExt#generator_fast 1000 repeats:
|
131
|
-
547.354332608 ( real) -> 15.090x
|
132
|
-
0.001826970
|
133
|
-
2 GeneratorBenchmarkExt#generator_safe 1000 repeats:
|
134
|
-
443.968212317 ( real) -> 12.240x
|
135
|
-
0.002252414
|
136
|
-
3 GeneratorBenchmarkExt#generator_pretty 900 repeats:
|
137
|
-
375.104545883 ( real) -> 10.341x
|
138
|
-
0.002665923
|
139
|
-
4 GeneratorBenchmarkPure#generator_fast 1000 repeats:
|
140
|
-
49.978706968 ( real) -> 1.378x
|
141
|
-
0.020008521
|
142
|
-
5 GeneratorBenchmarkRails#generator 1000 repeats:
|
143
|
-
38.531868759 ( real) -> 1.062x
|
144
|
-
0.025952543
|
145
|
-
6 GeneratorBenchmarkPure#generator_safe 1000 repeats:
|
146
|
-
36.927649925 ( real) -> 1.018x 7 (>=3859)
|
147
|
-
0.027079979
|
148
|
-
7 GeneratorBenchmarkPure#generator_pretty 1000 repeats:
|
149
|
-
36.272134441 ( real) -> 1.000x 6 (>=3859)
|
150
|
-
0.027569373
|
151
|
-
calls/sec ( time) -> speed covers
|
152
|
-
secs/call
|
153
|
-
|
154
|
-
In the table above 1-3 are JSON::Ext::Generator methods. 4, 6, and 7 are
|
155
|
-
JSON::Pure::Generator methods and 5 is the Rails JSON generator. It is now a
|
156
|
-
bit faster than the generator_safe and generator_pretty methods of the pure
|
157
|
-
variant but slower than the others.
|
158
|
-
|
159
|
-
To achieve the fastest JSON text output, you can use the fast_generate
|
160
|
-
method. Beware, that this will disable the checking for circular Ruby data
|
161
|
-
structures, which may cause JSON to go into an infinite loop.
|
162
|
-
|
163
|
-
Here are the median comparisons for completeness' sake:
|
164
|
-
|
165
|
-
Comparing times (call_time_median):
|
166
|
-
1 GeneratorBenchmarkExt#generator_fast 1000 repeats:
|
167
|
-
708.258020939 ( real) -> 16.547x
|
168
|
-
0.001411915
|
169
|
-
2 GeneratorBenchmarkExt#generator_safe 1000 repeats:
|
170
|
-
569.105020353 ( real) -> 13.296x
|
171
|
-
0.001757145
|
172
|
-
3 GeneratorBenchmarkExt#generator_pretty 900 repeats:
|
173
|
-
482.825371244 ( real) -> 11.280x
|
174
|
-
0.002071142
|
175
|
-
4 GeneratorBenchmarkPure#generator_fast 1000 repeats:
|
176
|
-
62.717626652 ( real) -> 1.465x
|
177
|
-
0.015944481
|
178
|
-
5 GeneratorBenchmarkRails#generator 1000 repeats:
|
179
|
-
43.965681162 ( real) -> 1.027x
|
180
|
-
0.022745013
|
181
|
-
6 GeneratorBenchmarkPure#generator_safe 1000 repeats:
|
182
|
-
43.929073409 ( real) -> 1.026x 7 (>=3859)
|
183
|
-
0.022763968
|
184
|
-
7 GeneratorBenchmarkPure#generator_pretty 1000 repeats:
|
185
|
-
42.802514491 ( real) -> 1.000x 6 (>=3859)
|
186
|
-
0.023363113
|
187
|
-
calls/sec ( time) -> speed covers
|
188
|
-
secs/call
|
189
|
-
|
190
|
-
=== Examples
|
191
|
-
|
192
|
-
To create a JSON text from a ruby data structure, you can call JSON.generate
|
193
|
-
like that:
|
194
|
-
|
195
|
-
json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
196
|
-
# => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
|
197
|
-
|
198
|
-
To create a valid JSON text you have to make sure, that the output is
|
199
|
-
embedded in either a JSON array [] or a JSON object {}. The easiest way to do
|
200
|
-
this, is by putting your values in a Ruby Array or Hash instance.
|
201
|
-
|
202
|
-
To get back a ruby data structure from a JSON text, you have to call
|
203
|
-
JSON.parse on it:
|
204
|
-
|
205
|
-
JSON.parse json
|
206
|
-
# => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
|
207
|
-
|
208
|
-
Note, that the range from the original data structure is a simple
|
209
|
-
string now. The reason for this is, that JSON doesn't support ranges
|
210
|
-
or arbitrary classes. In this case the json library falls back to call
|
211
|
-
Object#to_json, which is the same as #to_s.to_json.
|
212
|
-
|
213
|
-
It's possible to add JSON support serialization to arbitrary classes by
|
214
|
-
simply implementing a more specialized version of the #to_json method, that
|
215
|
-
should return a JSON object (a hash converted to JSON with #to_json) like
|
216
|
-
this (don't forget the *a for all the arguments):
|
217
|
-
|
218
|
-
class Range
|
219
|
-
def to_json(*a)
|
220
|
-
{
|
221
|
-
'json_class' => self.class.name, # = 'Range'
|
222
|
-
'data' => [ first, last, exclude_end? ]
|
223
|
-
}.to_json(*a)
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
The hash key 'json_class' is the class, that will be asked to deserialise the
|
228
|
-
JSON representation later. In this case it's 'Range', but any namespace of
|
229
|
-
the form 'A::B' or '::A::B' will do. All other keys are arbitrary and can be
|
230
|
-
used to store the necessary data to configure the object to be deserialised.
|
231
|
-
|
232
|
-
If a the key 'json_class' is found in a JSON object, the JSON parser checks
|
233
|
-
if the given class responds to the json_create class method. If so, it is
|
234
|
-
called with the JSON object converted to a Ruby hash. So a range can
|
235
|
-
be deserialised by implementing Range.json_create like this:
|
236
|
-
|
237
|
-
class Range
|
238
|
-
def self.json_create(o)
|
239
|
-
new(*o['data'])
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
Now it possible to serialise/deserialise ranges as well:
|
244
|
-
|
245
|
-
json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
246
|
-
# => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
|
247
|
-
JSON.parse json
|
248
|
-
# => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
249
|
-
|
250
|
-
JSON.generate always creates the shortest possible string representation of a
|
251
|
-
ruby data structure in one line. This good for data storage or network
|
252
|
-
protocols, but not so good for humans to read. Fortunately there's also
|
253
|
-
JSON.pretty_generate (or JSON.pretty_generate) that creates a more
|
254
|
-
readable output:
|
255
|
-
|
256
|
-
puts JSON.pretty_generate([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
|
257
|
-
[
|
258
|
-
1,
|
259
|
-
2,
|
260
|
-
{
|
261
|
-
"a": 3.141
|
262
|
-
},
|
263
|
-
false,
|
264
|
-
true,
|
265
|
-
null,
|
266
|
-
{
|
267
|
-
"json_class": "Range",
|
268
|
-
"data": [
|
269
|
-
4,
|
270
|
-
10,
|
271
|
-
false
|
272
|
-
]
|
273
|
-
}
|
274
|
-
]
|
275
|
-
|
276
|
-
There are also the methods Kernel#j for generate, and Kernel#jj for
|
277
|
-
pretty_generate output to the console, that work analogous to Core Ruby's p
|
278
|
-
and the pp library's pp methods.
|
279
|
-
|
280
|
-
The script tools/server.rb contains a small example if you want to test, how
|
281
|
-
receiving a JSON object from a webrick server in your browser with the
|
282
|
-
javasript prototype library (http://www.prototypejs.org) works.
|
283
|
-
|