json 1.1.3 → 1.1.4

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

Potentially problematic release.


This version of json might be problematic. Click here for more details.

Files changed (67) hide show
  1. data/CHANGES +9 -0
  2. data/Rakefile +47 -53
  3. data/VERSION +1 -1
  4. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +52 -0
  5. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +1000 -0
  6. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +1001 -0
  7. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +900 -0
  8. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +901 -0
  9. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +1000 -0
  10. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +1001 -0
  11. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +261 -0
  12. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +1000 -0
  13. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +1001 -0
  14. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +1000 -0
  15. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +1001 -0
  16. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +1000 -0
  17. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +1001 -0
  18. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +262 -0
  19. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +1000 -0
  20. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +1001 -0
  21. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +82 -0
  22. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +34 -0
  23. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +900 -0
  24. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +901 -0
  25. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +81 -0
  26. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +1000 -0
  27. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +1001 -0
  28. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +82 -0
  29. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +1000 -0
  30. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +1001 -0
  31. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +82 -0
  32. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +1000 -0
  33. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +1001 -0
  34. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +82 -0
  35. data/benchmarks/generator_benchmark.rb +162 -0
  36. data/benchmarks/parser_benchmark.rb +193 -0
  37. data/bin/edit_json.rb +0 -1
  38. data/bin/prettify_json.rb +0 -1
  39. data/doc-templates/main.txt +284 -0
  40. data/ext/json/ext/generator/extconf.rb +2 -0
  41. data/ext/json/ext/generator/generator.c +62 -18
  42. data/ext/json/ext/parser/extconf.rb +2 -0
  43. data/ext/json/ext/parser/parser.c +128 -81
  44. data/ext/json/ext/parser/parser.rl +31 -7
  45. data/ext/json/ext/parser/unicode.c +4 -4
  46. data/lib/json.rb +0 -221
  47. data/lib/json/add/core.rb +1 -1
  48. data/lib/json/editor.rb +11 -2
  49. data/lib/json/ext.rb +2 -0
  50. data/lib/json/pure.rb +2 -0
  51. data/lib/json/pure/generator.rb +77 -41
  52. data/lib/json/pure/parser.rb +6 -2
  53. data/lib/json/version.rb +1 -1
  54. data/tests/test_json.rb +7 -4
  55. data/tests/test_json_addition.rb +8 -5
  56. data/tests/test_json_fixtures.rb +6 -2
  57. data/tests/test_json_generate.rb +8 -2
  58. data/tests/test_json_rails.rb +30 -2
  59. data/tests/test_json_unicode.rb +8 -7
  60. data/tools/fuzz.rb +0 -1
  61. data/tools/server.rb +0 -1
  62. metadata +46 -9
  63. data/benchmarks/benchmark.txt +0 -133
  64. data/benchmarks/benchmark_generator.rb +0 -48
  65. data/benchmarks/benchmark_parser.rb +0 -26
  66. data/benchmarks/benchmark_rails.rb +0 -26
  67. data/tests/runner.rb +0 -25
@@ -0,0 +1,284 @@
1
+ # = json - JSON 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 on on ruby 1.8.6 (2008-08-11
80
+ # patchlevel 287) [i686-linux] (see the benchmarks/data-p4-3Ghz-ruby18
81
+ # subdir of the package) for the JSON-parser to estimate the speed up in the C
82
+ # extension:
83
+ #
84
+ # Comparing times (call_time_mean):
85
+ # 1 ParserBenchmarkExt#parser 900 repeats:
86
+ # 553.922304770 ( real) -> 21.500x
87
+ # 0.001805307
88
+ # 2 ParserBenchmarkYAML#parser 1000 repeats:
89
+ # 224.513358139 ( real) -> 8.714x
90
+ # 0.004454078
91
+ # 3 ParserBenchmarkPure#parser 1000 repeats:
92
+ # 26.755020642 ( real) -> 1.038x
93
+ # 0.037376163
94
+ # 4 ParserBenchmarkRails#parser 1000 repeats:
95
+ # 25.763381731 ( real) -> 1.000x
96
+ # 0.038814780
97
+ # calls/sec ( time) -> speed covers
98
+ # secs/call
99
+ #
100
+ # In the table above 1 is JSON::Ext::Parser, 2 is YAML.load with YAML
101
+ # compatbile JSON document, 3 is is JSON::Pure::Parser, and 4 is
102
+ # ActiveSupport::JSON.decode. The ActiveSupport JSON-decoder converts the
103
+ # input first to YAML and then uses the YAML-parser, the conversion seems to
104
+ # slow it down so much that it is only as fast as the JSON::Pure::Parser!
105
+ #
106
+ # If you look at the benchmark data you can see that this is mostly caused by
107
+ # the frequent high outliers - the median of the Rails-parser runs is still
108
+ # overall smaller than the median of the JSON::Pure::Parser runs:
109
+ #
110
+ # Comparing times (call_time_median):
111
+ # 1 ParserBenchmarkExt#parser 900 repeats:
112
+ # 800.592479481 ( real) -> 26.936x
113
+ # 0.001249075
114
+ # 2 ParserBenchmarkYAML#parser 1000 repeats:
115
+ # 271.002390644 ( real) -> 9.118x
116
+ # 0.003690004
117
+ # 3 ParserBenchmarkRails#parser 1000 repeats:
118
+ # 30.227910865 ( real) -> 1.017x
119
+ # 0.033082008
120
+ # 4 ParserBenchmarkPure#parser 1000 repeats:
121
+ # 29.722384421 ( real) -> 1.000x
122
+ # 0.033644676
123
+ # calls/sec ( time) -> speed covers
124
+ # secs/call
125
+ #
126
+ # I have benchmarked the JSON-Generator as well. This generated a few more
127
+ # values, because there are different modes that also influence the achieved
128
+ # speed:
129
+ #
130
+ # Comparing times (call_time_mean):
131
+ # 1 GeneratorBenchmarkExt#generator_fast 1000 repeats:
132
+ # 547.354332608 ( real) -> 15.090x
133
+ # 0.001826970
134
+ # 2 GeneratorBenchmarkExt#generator_safe 1000 repeats:
135
+ # 443.968212317 ( real) -> 12.240x
136
+ # 0.002252414
137
+ # 3 GeneratorBenchmarkExt#generator_pretty 900 repeats:
138
+ # 375.104545883 ( real) -> 10.341x
139
+ # 0.002665923
140
+ # 4 GeneratorBenchmarkPure#generator_fast 1000 repeats:
141
+ # 49.978706968 ( real) -> 1.378x
142
+ # 0.020008521
143
+ # 5 GeneratorBenchmarkRails#generator 1000 repeats:
144
+ # 38.531868759 ( real) -> 1.062x
145
+ # 0.025952543
146
+ # 6 GeneratorBenchmarkPure#generator_safe 1000 repeats:
147
+ # 36.927649925 ( real) -> 1.018x 7 (>=3859)
148
+ # 0.027079979
149
+ # 7 GeneratorBenchmarkPure#generator_pretty 1000 repeats:
150
+ # 36.272134441 ( real) -> 1.000x 6 (>=3859)
151
+ # 0.027569373
152
+ # calls/sec ( time) -> speed covers
153
+ # secs/call
154
+ #
155
+ # In the table above 1-3 are JSON::Ext::Generator methods. 4, 6, and 7 are
156
+ # JSON::Pure::Generator methods and 5 is the Rails JSON generator. It is now a
157
+ # bit faster than the generator_safe and generator_pretty methods of the pure
158
+ # variant but slower than the others.
159
+ #
160
+ # To achieve the fastest JSON text output, you can use the fast_generate
161
+ # method. Beware, that this will disable the checking for circular Ruby data
162
+ # structures, which may cause JSON to go into an infinite loop.
163
+ #
164
+ # Here are the median comparisons for completeness' sake:
165
+ #
166
+ # Comparing times (call_time_median):
167
+ # 1 GeneratorBenchmarkExt#generator_fast 1000 repeats:
168
+ # 708.258020939 ( real) -> 16.547x
169
+ # 0.001411915
170
+ # 2 GeneratorBenchmarkExt#generator_safe 1000 repeats:
171
+ # 569.105020353 ( real) -> 13.296x
172
+ # 0.001757145
173
+ # 3 GeneratorBenchmarkExt#generator_pretty 900 repeats:
174
+ # 482.825371244 ( real) -> 11.280x
175
+ # 0.002071142
176
+ # 4 GeneratorBenchmarkPure#generator_fast 1000 repeats:
177
+ # 62.717626652 ( real) -> 1.465x
178
+ # 0.015944481
179
+ # 5 GeneratorBenchmarkRails#generator 1000 repeats:
180
+ # 43.965681162 ( real) -> 1.027x
181
+ # 0.022745013
182
+ # 6 GeneratorBenchmarkPure#generator_safe 1000 repeats:
183
+ # 43.929073409 ( real) -> 1.026x 7 (>=3859)
184
+ # 0.022763968
185
+ # 7 GeneratorBenchmarkPure#generator_pretty 1000 repeats:
186
+ # 42.802514491 ( real) -> 1.000x 6 (>=3859)
187
+ # 0.023363113
188
+ # calls/sec ( time) -> speed covers
189
+ # secs/call
190
+ #
191
+ # == Examples
192
+ #
193
+ # To create a JSON text from a ruby data structure, you can call JSON.generate
194
+ # like that:
195
+ #
196
+ # json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
197
+ # # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
198
+ #
199
+ # To create a valid JSON text you have to make sure, that the output is
200
+ # embedded in either a JSON array [] or a JSON object {}. The easiest way to do
201
+ # this, is by putting your values in a Ruby Array or Hash instance.
202
+ #
203
+ # To get back a ruby data structure from a JSON text, you have to call
204
+ # JSON.parse on it:
205
+ #
206
+ # JSON.parse json
207
+ # # => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
208
+ #
209
+ # Note, that the range from the original data structure is a simple
210
+ # string now. The reason for this is, that JSON doesn't support ranges
211
+ # or arbitrary classes. In this case the json library falls back to call
212
+ # Object#to_json, which is the same as #to_s.to_json.
213
+ #
214
+ # It's possible to add JSON support serialization to arbitrary classes by
215
+ # simply implementing a more specialized version of the #to_json method, that
216
+ # should return a JSON object (a hash converted to JSON with #to_json) like
217
+ # this (don't forget the *a for all the arguments):
218
+ #
219
+ # class Range
220
+ # def to_json(*a)
221
+ # {
222
+ # 'json_class' => self.class.name, # = 'Range'
223
+ # 'data' => [ first, last, exclude_end? ]
224
+ # }.to_json(*a)
225
+ # end
226
+ # end
227
+ #
228
+ # The hash key 'json_class' is the class, that will be asked to deserialise the
229
+ # JSON representation later. In this case it's 'Range', but any namespace of
230
+ # the form 'A::B' or '::A::B' will do. All other keys are arbitrary and can be
231
+ # used to store the necessary data to configure the object to be deserialised.
232
+ #
233
+ # If a the key 'json_class' is found in a JSON object, the JSON parser checks
234
+ # if the given class responds to the json_create class method. If so, it is
235
+ # called with the JSON object converted to a Ruby hash. So a range can
236
+ # be deserialised by implementing Range.json_create like this:
237
+ #
238
+ # class Range
239
+ # def self.json_create(o)
240
+ # new(*o['data'])
241
+ # end
242
+ # end
243
+ #
244
+ # Now it possible to serialise/deserialise ranges as well:
245
+ #
246
+ # json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
247
+ # # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
248
+ # JSON.parse json
249
+ # # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
250
+ #
251
+ # JSON.generate always creates the shortest possible string representation of a
252
+ # ruby data structure in one line. This good for data storage or network
253
+ # protocols, but not so good for humans to read. Fortunately there's also
254
+ # JSON.pretty_generate (or JSON.pretty_generate) that creates a more
255
+ # readable output:
256
+ #
257
+ # puts JSON.pretty_generate([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
258
+ # [
259
+ # 1,
260
+ # 2,
261
+ # {
262
+ # "a": 3.141
263
+ # },
264
+ # false,
265
+ # true,
266
+ # null,
267
+ # {
268
+ # "json_class": "Range",
269
+ # "data": [
270
+ # 4,
271
+ # 10,
272
+ # false
273
+ # ]
274
+ # }
275
+ # ]
276
+ #
277
+ # There are also the methods Kernel#j for generate, and Kernel#jj for
278
+ # pretty_generate output to the console, that work analogous to Core Ruby's p
279
+ # and the pp library's pp methods.
280
+ #
281
+ # The script tools/server.rb contains a small example if you want to test, how
282
+ # receiving a JSON object from a webrick server in your browser with the
283
+ # javasript prototype library (http://www.prototypejs.org) works.
284
+ #
@@ -6,4 +6,6 @@ if CONFIG['CC'] =~ /gcc/
6
6
  #$CFLAGS += ' -O0 -ggdb'
7
7
  end
8
8
 
9
+ have_header("ruby/st.h") || have_header("st.h")
10
+ have_header("ruby/encoding.h")
9
11
  create_makefile 'generator'
@@ -1,9 +1,33 @@
1
1
  #include <string.h>
2
2
  #include "ruby.h"
3
+ #if HAVE_RUBY_ST_H
4
+ #include "ruby/st.h"
5
+ #endif
6
+ #if HAVE_ST_H
3
7
  #include "st.h"
8
+ #endif
4
9
  #include "unicode.h"
5
10
  #include <math.h>
6
11
 
12
+ #ifndef RHASH_TBL
13
+ #define RHASH_TBL(hsh) (RHASH(hsh)->tbl)
14
+ #endif
15
+
16
+ #ifndef RHASH_SIZE
17
+ #define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
18
+ #endif
19
+
20
+ #ifndef RFLOAT_VALUE
21
+ #define RFLOAT_VALUE(val) (RFLOAT(val)->value)
22
+ #endif
23
+
24
+ #ifdef HAVE_RUBY_ENCODING_H
25
+ #include "ruby/encoding.h"
26
+ #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
27
+ #else
28
+ #define FORCE_UTF8(obj)
29
+ #endif
30
+
7
31
  #define check_max_nesting(state, depth) do { \
8
32
  long current_nesting = 1 + depth; \
9
33
  if (state->max_nesting != 0 && current_nesting > state->max_nesting) \
@@ -86,7 +110,7 @@ static int hash_to_json_state_i(VALUE key, VALUE value, VALUE Vstate)
86
110
  }
87
111
 
88
112
  inline static VALUE mHash_json_transfrom(VALUE self, VALUE Vstate, VALUE Vdepth) {
89
- long depth, len = RHASH(self)->tbl->num_entries;
113
+ long depth, len = RHASH_SIZE(self);
90
114
  VALUE result;
91
115
  GET_STATE(Vstate);
92
116
 
@@ -142,7 +166,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
142
166
  rb_scan_args(argc, argv, "02", &Vstate, &Vdepth);
143
167
  depth = NIL_P(Vdepth) ? 0 : FIX2LONG(Vdepth);
144
168
  if (NIL_P(Vstate)) {
145
- long len = RHASH(self)->tbl->num_entries;
169
+ long len = RHASH_SIZE(self);
146
170
  result = rb_str_buf_new(len);
147
171
  rb_str_buf_cat2(result, "{");
148
172
  rb_hash_foreach(self, hash_to_json_i, result);
@@ -164,6 +188,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
164
188
  }
165
189
  }
166
190
  OBJ_INFECT(result, self);
191
+ FORCE_UTF8(result);
167
192
  return result;
168
193
  }
169
194
 
@@ -261,6 +286,7 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
261
286
  result = mArray_json_transfrom(self, Vstate, Vdepth);
262
287
  }
263
288
  OBJ_INFECT(result, self);
289
+ FORCE_UTF8(result);
264
290
  return result;
265
291
  }
266
292
 
@@ -271,7 +297,9 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
271
297
  */
272
298
  static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
273
299
  {
274
- return rb_funcall(self, i_to_s, 0);
300
+ VALUE result = rb_funcall(self, i_to_s, 0);
301
+ FORCE_UTF8(result);
302
+ return result;
275
303
  }
276
304
 
277
305
  /*
@@ -282,27 +310,29 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
282
310
  static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
283
311
  {
284
312
  JSON_Generator_State *state = NULL;
285
- VALUE Vstate, rest, tmp;
286
- double value = RFLOAT(self)->value;
313
+ VALUE Vstate, rest, tmp, result;
314
+ double value = RFLOAT_VALUE(self);
287
315
  rb_scan_args(argc, argv, "01*", &Vstate, &rest);
288
316
  if (!NIL_P(Vstate)) Data_Get_Struct(Vstate, JSON_Generator_State, state);
289
317
  if (isinf(value)) {
290
318
  if (!state || state->allow_nan) {
291
- return rb_funcall(self, i_to_s, 0);
319
+ result = rb_funcall(self, i_to_s, 0);
292
320
  } else {
293
321
  tmp = rb_funcall(self, i_to_s, 0);
294
322
  rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
295
323
  }
296
324
  } else if (isnan(value)) {
297
325
  if (!state || state->allow_nan) {
298
- return rb_funcall(self, i_to_s, 0);
326
+ result = rb_funcall(self, i_to_s, 0);
299
327
  } else {
300
328
  tmp = rb_funcall(self, i_to_s, 0);
301
329
  rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
302
330
  }
303
331
  } else {
304
- return rb_funcall(self, i_to_s, 0);
332
+ result = rb_funcall(self, i_to_s, 0);
305
333
  }
334
+ FORCE_UTF8(result);
335
+ return result;
306
336
  }
307
337
 
308
338
  /*
@@ -311,7 +341,9 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
311
341
  * Extends _modul_ with the String::Extend module.
312
342
  */
313
343
  static VALUE mString_included_s(VALUE self, VALUE modul) {
314
- return rb_funcall(modul, i_extend, 1, mString_Extend);
344
+ VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
345
+ FORCE_UTF8(result);
346
+ return result;
315
347
  }
316
348
 
317
349
  /*
@@ -327,6 +359,7 @@ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
327
359
  rb_str_buf_cat2(result, "\"");
328
360
  JSON_convert_UTF8_to_JSON(result, self, strictConversion);
329
361
  rb_str_buf_cat2(result, "\"");
362
+ FORCE_UTF8(result);
330
363
  return result;
331
364
  }
332
365
 
@@ -344,6 +377,7 @@ static VALUE mString_to_json_raw_object(VALUE self) {
344
377
  rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
345
378
  ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
346
379
  rb_hash_aset(result, rb_str_new2("raw"), ary);
380
+ FORCE_UTF8(result);
347
381
  return result;
348
382
  }
349
383
 
@@ -354,9 +388,11 @@ static VALUE mString_to_json_raw_object(VALUE self) {
354
388
  * to_json_raw_object of this String.
355
389
  */
356
390
  static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self) {
357
- VALUE obj = mString_to_json_raw_object(self);
391
+ VALUE result, obj = mString_to_json_raw_object(self);
358
392
  Check_Type(obj, T_HASH);
359
- return mHash_to_json(argc, argv, obj);
393
+ result = mHash_to_json(argc, argv, obj);
394
+ FORCE_UTF8(result);
395
+ return result;
360
396
  }
361
397
 
362
398
  /*
@@ -379,7 +415,9 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o) {
379
415
  */
380
416
  static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
381
417
  {
382
- return rb_str_new2("true");
418
+ VALUE result = rb_str_new2("true");
419
+ FORCE_UTF8(result);
420
+ return result;
383
421
  }
384
422
 
385
423
  /*
@@ -389,7 +427,9 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
389
427
  */
390
428
  static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
391
429
  {
392
- return rb_str_new2("false");
430
+ VALUE result = rb_str_new2("false");
431
+ FORCE_UTF8(result);
432
+ return result;
393
433
  }
394
434
 
395
435
  /*
@@ -398,7 +438,9 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
398
438
  */
399
439
  static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
400
440
  {
401
- return rb_str_new2("null");
441
+ VALUE result = rb_str_new2("null");
442
+ FORCE_UTF8(result);
443
+ return result;
402
444
  }
403
445
 
404
446
  /*
@@ -410,9 +452,11 @@ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
410
452
  */
411
453
  static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
412
454
  {
413
- VALUE string = rb_funcall(self, i_to_s, 0);
455
+ VALUE result, string = rb_funcall(self, i_to_s, 0);
414
456
  Check_Type(string, T_STRING);
415
- return mString_to_json(argc, argv, string);
457
+ result = mString_to_json(argc, argv, string);
458
+ FORCE_UTF8(result);
459
+ return result;
416
460
  }
417
461
 
418
462
  /*
@@ -488,7 +532,7 @@ static inline VALUE cState_configure(VALUE self, VALUE opts)
488
532
  state->object_nl = tmp;
489
533
  }
490
534
  tmp = ID2SYM(i_check_circular);
491
- if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
535
+ if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
492
536
  tmp = rb_hash_aref(opts, ID2SYM(i_check_circular));
493
537
  state->check_circular = RTEST(tmp);
494
538
  } else {
@@ -496,7 +540,7 @@ static inline VALUE cState_configure(VALUE self, VALUE opts)
496
540
  }
497
541
  tmp = ID2SYM(i_max_nesting);
498
542
  state->max_nesting = 19;
499
- if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
543
+ if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
500
544
  VALUE max_nesting = rb_hash_aref(opts, tmp);
501
545
  if (RTEST(max_nesting)) {
502
546
  Check_Type(max_nesting, T_FIXNUM);