summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml5
-rw-r--r--Gemfile2
-rw-r--r--README.md13
-rw-r--r--TODO1
-rw-r--r--ext/json/ext/generator/generator.c34
-rw-r--r--ext/json/ext/generator/generator.h1
-rw-r--r--ext/json/ext/parser/parser.c162
-rw-r--r--ext/json/ext/parser/parser.rl16
-rw-r--r--java/src/json/ext/Generator.java7
-rw-r--r--java/src/json/ext/GeneratorState.java24
-rw-r--r--java/src/json/ext/OptionsReader.java2
-rw-r--r--java/src/json/ext/Parser.java518
-rw-r--r--java/src/json/ext/Parser.rl141
-rw-r--r--java/src/json/ext/RuntimeInfo.java4
-rw-r--r--json.gemspecbin4444 -> 4462 bytes
-rw-r--r--json_pure.gemspec4
-rw-r--r--lib/json/common.rb55
-rw-r--r--lib/json/ext.rb6
-rw-r--r--lib/json/pure.rb10
-rw-r--r--lib/json/pure/generator.rb161
-rw-r--r--lib/json/pure/parser.rb14
-rw-r--r--references/rfc7159.txt899
-rw-r--r--tests/json_common_interface_test.rb31
-rw-r--r--tests/json_encoding_test.rb19
-rw-r--r--tests/json_ext_parser_test.rb3
-rw-r--r--tests/json_generator_test.rb4
-rw-r--r--tests/json_parser_test.rb4
-rw-r--r--tests/test_helper.rb4
-rwxr-xr-xtools/fuzz.rb10
29 files changed, 1246 insertions, 908 deletions
diff --git a/.travis.yml b/.travis.yml
index e1ebeda..a8f9071 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,14 +4,11 @@ language: ruby
# Specify which ruby versions you wish to run your tests on, each version will be used
rvm:
- - 1.8.7
- - 1.9.2
- 1.9.3
- 2.0.0
- 2.1
- 2.2
- - 2.3.0
- - ree
+ - 2.3.1
- ruby-head
matrix:
include:
diff --git a/Gemfile b/Gemfile
index 71fac47..51ff10a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,3 +5,5 @@ source 'https://rubygems.org'
gemspec :name => 'json'
gemspec :name => 'json_pure'
gemspec :name => 'json-java'
+
+gem 'simplecov'
diff --git a/README.md b/README.md
index ea0810f..5691f3e 100644
--- a/README.md
+++ b/README.md
@@ -26,13 +26,6 @@ encoded, please use the to\_json\_raw\_object method of String (which produces
an object, that contains a byte array) and decode the result on the receiving
endpoint.
-The JSON parsers can parse UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, and UTF-32LE
-JSON documents under Ruby 1.8. Under Ruby 1.9 they take advantage of Ruby's
-M17n features and can parse all documents which have the correct
-String#encoding set. If a document string has ASCII-8BIT as an encoding the
-parser attempts to figure out which of the UTF encodings from above it is and
-trys to parse it.
-
## Installation
It's recommended to use the extension variant of JSON, because it's faster than
@@ -117,11 +110,7 @@ You can also use the `pretty_generate` method (which formats the output more
verbosely and nicely) or `fast_generate` (which doesn't do any of the security
checks generate performs, e. g. nesting deepness checks).
-To create a valid JSON document you have to make sure, that the output is
-embedded in either a JSON array `[]` or a JSON object `{}`. The easiest way to do
-this, is by putting your values in a Ruby Array or Hash instance.
-
-There are also the `JSON` and `JSON[]` methods which use parse on a String or
+There are also the JSON and JSON[] methods which use parse on a String or
generate a JSON document from an array or hash:
```ruby
diff --git a/TODO b/TODO
deleted file mode 100644
index 8b13789..0000000
--- a/TODO
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index 393e29c..2a3db29 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -14,7 +14,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
- i_quirks_mode, i_pack, i_unpack, i_create_id, i_extend, i_key_p,
+ i_pack, i_unpack, i_create_id, i_extend, i_key_p,
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
i_buffer_initial_length, i_dup;
@@ -622,8 +622,6 @@ static VALUE cState_configure(VALUE self, VALUE opts)
state->allow_nan = RTEST(tmp);
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
state->ascii_only = RTEST(tmp);
- tmp = rb_hash_aref(opts, ID2SYM(i_quirks_mode));
- state->quirks_mode = RTEST(tmp);
return self;
}
@@ -657,7 +655,6 @@ static VALUE cState_to_h(VALUE self)
rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
- rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
@@ -943,8 +940,6 @@ static VALUE cState_generate(VALUE self, VALUE obj)
* * *allow_nan*: true if NaN, Infinity, and -Infinity should be
* generated, otherwise an exception is thrown, if these values are
* encountered. This options defaults to false.
- * * *quirks_mode*: Enables quirks_mode for parser, that is for example
- * generating single JSON values instead of documents is possible.
* * *buffer_initial_length*: sets the initial length of the generator's
* internal buffer.
*/
@@ -1252,29 +1247,6 @@ static VALUE cState_ascii_only_p(VALUE self)
}
/*
- * call-seq: quirks_mode?
- *
- * Returns true, if quirks mode is enabled. Otherwise returns false.
- */
-static VALUE cState_quirks_mode_p(VALUE self)
-{
- GET_STATE(self);
- return state->quirks_mode ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq: quirks_mode=(enable)
- *
- * If set to true, enables the quirks_mode mode.
- */
-static VALUE cState_quirks_mode_set(VALUE self, VALUE enable)
-{
- GET_STATE(self);
- state->quirks_mode = RTEST(enable);
- return Qnil;
-}
-
-/*
* call-seq: depth
*
* This integer returns the current depth of data structure nesting.
@@ -1362,9 +1334,6 @@ void Init_generator(void)
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
- rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0);
- rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0);
- rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
rb_define_method(cState, "depth", cState_depth, 0);
rb_define_method(cState, "depth=", cState_depth_set, 1);
rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
@@ -1416,7 +1385,6 @@ void Init_generator(void)
i_max_nesting = rb_intern("max_nesting");
i_allow_nan = rb_intern("allow_nan");
i_ascii_only = rb_intern("ascii_only");
- i_quirks_mode = rb_intern("quirks_mode");
i_depth = rb_intern("depth");
i_buffer_initial_length = rb_intern("buffer_initial_length");
i_pack = rb_intern("pack");
diff --git a/ext/json/ext/generator/generator.h b/ext/json/ext/generator/generator.h
index 298c0a4..7432f26 100644
--- a/ext/json/ext/generator/generator.h
+++ b/ext/json/ext/generator/generator.h
@@ -73,7 +73,6 @@ typedef struct JSON_Generator_StateStruct {
long max_nesting;
char allow_nan;
char ascii_only;
- char quirks_mode;
long depth;
long buffer_initial_length;
} JSON_Generator_State;
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
index c63a462..5b2e61c 100644
--- a/ext/json/ext/parser/parser.c
+++ b/ext/json/ext/parser/parser.c
@@ -68,9 +68,8 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
}
#ifdef HAVE_RUBY_ENCODING_H
-static VALUE CEncoding_UTF_8;
-
-static ID i_encode;
+static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8;
+static ID i_encoding, i_encode;
#else
static ID i_iconv;
#endif
@@ -84,11 +83,11 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
i_match_string, i_aset, i_aref, i_leftshift;
-#line 110 "parser.rl"
+#line 109 "parser.rl"
-#line 92 "parser.c"
+#line 91 "parser.c"
static const int JSON_object_start = 1;
static const int JSON_object_first_final = 27;
static const int JSON_object_error = 0;
@@ -96,7 +95,7 @@ static const int JSON_object_error = 0;
static const int JSON_object_en_main = 1;
-#line 151 "parser.rl"
+#line 150 "parser.rl"
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -112,14 +111,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
-#line 116 "parser.c"
+#line 115 "parser.c"
{
cs = JSON_object_start;
}
-#line 166 "parser.rl"
+#line 165 "parser.rl"
-#line 123 "parser.c"
+#line 122 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -147,7 +146,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 133 "parser.rl"
+#line 132 "parser.rl"
{
char *np;
json->parsing_name = 1;
@@ -160,7 +159,7 @@ st3:
if ( ++p == pe )
goto _test_eof3;
case 3:
-#line 164 "parser.c"
+#line 163 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -227,7 +226,7 @@ case 8:
goto st8;
goto st0;
tr11:
-#line 118 "parser.rl"
+#line 117 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
@@ -247,7 +246,7 @@ st9:
if ( ++p == pe )
goto _test_eof9;
case 9:
-#line 251 "parser.c"
+#line 250 "parser.c"
switch( (*p) ) {
case 13: goto st9;
case 32: goto st9;
@@ -336,14 +335,14 @@ case 18:
goto st9;
goto st18;
tr4:
-#line 141 "parser.rl"
+#line 140 "parser.rl"
{ p--; {p++; cs = 27; goto _out;} }
goto st27;
st27:
if ( ++p == pe )
goto _test_eof27;
case 27:
-#line 347 "parser.c"
+#line 346 "parser.c"
goto st0;
st19:
if ( ++p == pe )
@@ -441,7 +440,7 @@ case 26:
_out: {}
}
-#line 167 "parser.rl"
+#line 166 "parser.rl"
if (cs >= JSON_object_first_final) {
if (json->create_additions) {
@@ -466,7 +465,7 @@ case 26:
-#line 470 "parser.c"
+#line 469 "parser.c"
static const int JSON_value_start = 1;
static const int JSON_value_first_final = 29;
static const int JSON_value_error = 0;
@@ -474,7 +473,7 @@ static const int JSON_value_error = 0;
static const int JSON_value_en_main = 1;
-#line 271 "parser.rl"
+#line 270 "parser.rl"
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -482,14 +481,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 486 "parser.c"
+#line 485 "parser.c"
{
cs = JSON_value_start;
}
-#line 278 "parser.rl"
+#line 277 "parser.rl"
-#line 493 "parser.c"
+#line 492 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -523,14 +522,14 @@ st0:
cs = 0;
goto _out;
tr2:
-#line 219 "parser.rl"
+#line 218 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, result);
if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;}
}
goto st29;
tr3:
-#line 224 "parser.rl"
+#line 223 "parser.rl"
{
char *np;
if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) {
@@ -550,7 +549,7 @@ tr3:
}
goto st29;
tr7:
-#line 242 "parser.rl"
+#line 241 "parser.rl"
{
char *np;
json->current_nesting++;
@@ -560,7 +559,7 @@ tr7:
}
goto st29;
tr11:
-#line 250 "parser.rl"
+#line 249 "parser.rl"
{
char *np;
json->current_nesting++;
@@ -570,7 +569,7 @@ tr11:
}
goto st29;
tr25:
-#line 212 "parser.rl"
+#line 211 "parser.rl"
{
if (json->allow_nan) {
*result = CInfinity;
@@ -580,7 +579,7 @@ tr25:
}
goto st29;
tr27:
-#line 205 "parser.rl"
+#line 204 "parser.rl"
{
if (json->allow_nan) {
*result = CNaN;
@@ -590,19 +589,19 @@ tr27:
}
goto st29;
tr31:
-#line 199 "parser.rl"
+#line 198 "parser.rl"
{
*result = Qfalse;
}
goto st29;
tr34:
-#line 196 "parser.rl"
+#line 195 "parser.rl"
{
*result = Qnil;
}
goto st29;
tr37:
-#line 202 "parser.rl"
+#line 201 "parser.rl"
{
*result = Qtrue;
}
@@ -611,9 +610,9 @@ st29:
if ( ++p == pe )
goto _test_eof29;
case 29:
-#line 258 "parser.rl"
+#line 257 "parser.rl"
{ p--; {p++; cs = 29; goto _out;} }
-#line 617 "parser.c"
+#line 616 "parser.c"
switch( (*p) ) {
case 13: goto st29;
case 32: goto st29;
@@ -854,7 +853,7 @@ case 28:
_out: {}
}
-#line 279 "parser.rl"
+#line 278 "parser.rl"
if (cs >= JSON_value_first_final) {
return p;
@@ -864,7 +863,7 @@ case 28:
}
-#line 868 "parser.c"
+#line 867 "parser.c"
static const int JSON_integer_start = 1;
static const int JSON_integer_first_final = 3;
static const int JSON_integer_error = 0;
@@ -872,7 +871,7 @@ static const int JSON_integer_error = 0;
static const int JSON_integer_en_main = 1;
-#line 295 "parser.rl"
+#line 294 "parser.rl"
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -880,15 +879,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
int cs = EVIL;
-#line 884 "parser.c"
+#line 883 "parser.c"
{
cs = JSON_integer_start;
}
-#line 302 "parser.rl"
+#line 301 "parser.rl"
json->memo = p;
-#line 892 "parser.c"
+#line 891 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -922,14 +921,14 @@ case 3:
goto st0;
goto tr4;
tr4:
-#line 292 "parser.rl"
+#line 291 "parser.rl"
{ p--; {p++; cs = 4; goto _out;} }
goto st4;
st4:
if ( ++p == pe )
goto _test_eof4;
case 4:
-#line 933 "parser.c"
+#line 932 "parser.c"
goto st0;
st5:
if ( ++p == pe )
@@ -948,7 +947,7 @@ case 5:
_out: {}
}
-#line 304 "parser.rl"
+#line 303 "parser.rl"
if (cs >= JSON_integer_first_final) {
long len = p - json->memo;
@@ -963,7 +962,7 @@ case 5:
}
-#line 967 "parser.c"
+#line 966 "parser.c"
static const int JSON_float_start = 1;
static const int JSON_float_first_final = 8;
static const int JSON_float_error = 0;
@@ -971,7 +970,7 @@ static const int JSON_float_error = 0;
static const int JSON_float_en_main = 1;
-#line 329 "parser.rl"
+#line 328 "parser.rl"
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -979,15 +978,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 983 "parser.c"
+#line 982 "parser.c"
{
cs = JSON_float_start;
}
-#line 336 "parser.rl"
+#line 335 "parser.rl"
json->memo = p;
-#line 991 "parser.c"
+#line 990 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1045,14 +1044,14 @@ case 8:
goto st0;
goto tr9;
tr9:
-#line 323 "parser.rl"
+#line 322 "parser.rl"
{ p--; {p++; cs = 9; goto _out;} }
goto st9;
st9:
if ( ++p == pe )
goto _test_eof9;
case 9:
-#line 1056 "parser.c"
+#line 1055 "parser.c"
goto st0;
st5:
if ( ++p == pe )
@@ -1113,7 +1112,7 @@ case 7:
_out: {}
}
-#line 338 "parser.rl"
+#line 337 "parser.rl"
if (cs >= JSON_float_first_final) {
long len = p - json->memo;
@@ -1129,7 +1128,7 @@ case 7:
-#line 1133 "parser.c"
+#line 1132 "parser.c"
static const int JSON_array_start = 1;
static const int JSON_array_first_final = 17;
static const int JSON_array_error = 0;
@@ -1137,7 +1136,7 @@ static const int JSON_array_error = 0;
static const int JSON_array_en_main = 1;
-#line 381 "parser.rl"
+#line 380 "parser.rl"
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -1151,14 +1150,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
-#line 1155 "parser.c"
+#line 1154 "parser.c"
{
cs = JSON_array_start;
}
-#line 394 "parser.rl"
+#line 393 "parser.rl"
-#line 1162 "parser.c"
+#line 1161 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1197,7 +1196,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 358 "parser.rl"
+#line 357 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
@@ -1217,7 +1216,7 @@ st3:
if ( ++p == pe )
goto _test_eof3;
case 3:
-#line 1221 "parser.c"
+#line 1220 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -1317,14 +1316,14 @@ case 12:
goto st3;
goto st12;
tr4:
-#line 373 "parser.rl"
+#line 372 "parser.rl"
{ p--; {p++; cs = 17; goto _out;} }
goto st17;
st17:
if ( ++p == pe )
goto _test_eof17;
case 17:
-#line 1328 "parser.c"
+#line 1327 "parser.c"
goto st0;
st13:
if ( ++p == pe )
@@ -1380,7 +1379,7 @@ case 16:
_out: {}
}
-#line 395 "parser.rl"
+#line 394 "parser.rl"
if(cs >= JSON_array_first_final) {
return p + 1;
@@ -1461,7 +1460,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
}
-#line 1465 "parser.c"
+#line 1464 "parser.c"
static const int JSON_string_start = 1;
static const int JSON_string_first_final = 8;
static const int JSON_string_error = 0;
@@ -1469,7 +1468,7 @@ static const int JSON_string_error = 0;
static const int JSON_string_en_main = 1;
-#line 494 "parser.rl"
+#line 493 "parser.rl"
static int
@@ -1491,15 +1490,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = rb_str_buf_new(0);
-#line 1495 "parser.c"
+#line 1494 "parser.c"
{
cs = JSON_string_start;
}
-#line 515 "parser.rl"
+#line 514 "parser.rl"
json->memo = p;
-#line 1503 "parser.c"
+#line 1502 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1524,7 +1523,7 @@ case 2:
goto st0;
goto st2;
tr2:
-#line 480 "parser.rl"
+#line 479 "parser.rl"
{
*result = json_string_unescape(*result, json->memo + 1, p);
if (NIL_P(*result)) {
@@ -1535,14 +1534,14 @@ tr2:
{p = (( p + 1))-1;}
}
}
-#line 491 "parser.rl"
+#line 490 "parser.rl"
{ p--; {p++; cs = 8; goto _out;} }
goto st8;
st8:
if ( ++p == pe )
goto _test_eof8;
case 8:
-#line 1546 "parser.c"
+#line 1545 "parser.c"
goto st0;
st3:
if ( ++p == pe )
@@ -1618,7 +1617,7 @@ case 7:
_out: {}
}
-#line 517 "parser.rl"
+#line 516 "parser.rl"
if (json->create_additions && RTEST(match_string = json->match_string)) {
VALUE klass;
@@ -1656,9 +1655,12 @@ case 7:
static VALUE convert_encoding(VALUE source)
{
#ifdef HAVE_RUBY_ENCODING_H
- {
- source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
- }
+ VALUE encoding = rb_funcall(source, i_encoding, 0);
+ if (encoding == CEncoding_ASCII_8BIT) {
+ FORCE_UTF8(source);
+ } else {
+ source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
+ }
#endif
return source;
}
@@ -1784,7 +1786,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
}
-#line 1788 "parser.c"
+#line 1790 "parser.c"
static const int JSON_start = 1;
static const int JSON_first_final = 10;
static const int JSON_error = 0;
@@ -1792,7 +1794,7 @@ static const int JSON_error = 0;
static const int JSON_en_main = 1;
-#line 696 "parser.rl"
+#line 698 "parser.rl"
/*
@@ -1809,16 +1811,16 @@ static VALUE cParser_parse(VALUE self)
GET_PARSER;
-#line 1813 "parser.c"
+#line 1815 "parser.c"
{
cs = JSON_start;
}
-#line 712 "parser.rl"
+#line 714 "parser.rl"
p = json->source;
pe = p + json->len;
-#line 1822 "parser.c"
+#line 1824 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1852,7 +1854,7 @@ st0:
cs = 0;
goto _out;
tr2:
-#line 688 "parser.rl"
+#line 690 "parser.rl"
{
char *np = JSON_parse_value(json, p, pe, &result);
if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
@@ -1862,7 +1864,7 @@ st10:
if ( ++p == pe )
goto _test_eof10;
case 10:
-#line 1866 "parser.c"
+#line 1868 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
@@ -1951,7 +1953,7 @@ case 9:
_out: {}
}
-#line 715 "parser.rl"
+#line 717 "parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
@@ -2051,6 +2053,8 @@ void Init_parser(void)
i_leftshift = rb_intern("<<");
#ifdef HAVE_RUBY_ENCODING_H
CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
+ CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
+ i_encoding = rb_intern("encoding");
i_encode = rb_intern("encode");
#else
i_iconv = rb_intern("iconv");
diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
index 6f73307..f3933cb 100644
--- a/ext/json/ext/parser/parser.rl
+++ b/ext/json/ext/parser/parser.rl
@@ -66,9 +66,8 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
}
#ifdef HAVE_RUBY_ENCODING_H
-static VALUE CEncoding_UTF_8;
-
-static ID i_encode;
+static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8;
+static ID i_encoding, i_encode;
#else
static ID i_iconv;
#endif
@@ -551,9 +550,12 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
static VALUE convert_encoding(VALUE source)
{
#ifdef HAVE_RUBY_ENCODING_H
- {
- source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
- }
+ VALUE encoding = rb_funcall(source, i_encoding, 0);
+ if (encoding == CEncoding_ASCII_8BIT) {
+ FORCE_UTF8(source);
+ } else {
+ source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
+ }
#endif
return source;
}
@@ -811,6 +813,8 @@ void Init_parser(void)
i_leftshift = rb_intern("<<");
#ifdef HAVE_RUBY_ENCODING_H
CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
+ CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
+ i_encoding = rb_intern("encoding");
i_encode = rb_intern("encode");
#else
i_iconv = rb_intern("iconv");
diff --git a/java/src/json/ext/Generator.java b/java/src/json/ext/Generator.java
index bb3a394..96a5e7e 100644
--- a/java/src/json/ext/Generator.java
+++ b/java/src/json/ext/Generator.java
@@ -172,9 +172,7 @@ public final class Generator {
result = RubyString.newString(session.getRuntime(), buffer);
ThreadContext context = session.getContext();
RuntimeInfo info = session.getInfo();
- if (info.encodingsSupported()) {
- result.force_encoding(context, info.utf8.get());
- }
+ result.force_encoding(context, info.utf8.get());
return result;
}
@@ -381,8 +379,7 @@ public final class Generator {
RuntimeInfo info = session.getInfo();
RubyString src;
- if (info.encodingsSupported() &&
- object.encoding(session.getContext()) != info.utf8.get()) {
+ if (object.encoding(session.getContext()) != info.utf8.get()) {
src = (RubyString)object.encode(session.getContext(),
info.utf8.get());
} else {
diff --git a/java/src/json/ext/GeneratorState.java b/java/src/json/ext/GeneratorState.java
index 11d98d0..44a9311 100644
--- a/java/src/json/ext/GeneratorState.java
+++ b/java/src/json/ext/GeneratorState.java
@@ -208,9 +208,7 @@ public class GeneratorState extends RubyObject {
public IRubyObject generate(ThreadContext context, IRubyObject obj) {
RubyString result = Generator.generateJson(context, obj, this);
RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
- if (info.encodingsSupported()) {
- result.force_encoding(context, info.utf8.get());
- }
+ result.force_encoding(context, info.utf8.get());
return result;
}
@@ -366,17 +364,6 @@ public class GeneratorState extends RubyObject {
return context.getRuntime().newBoolean(asciiOnly);
}
- @JRubyMethod(name="quirks_mode")
- public RubyBoolean quirks_mode_get(ThreadContext context) {
- return context.getRuntime().newBoolean(quirksMode);
- }
-
- @JRubyMethod(name="quirks_mode=")
- public IRubyObject quirks_mode_set(IRubyObject quirks_mode) {
- quirksMode = quirks_mode.isTrue();
- return quirks_mode.getRuntime().newBoolean(quirksMode);
- }
-
@JRubyMethod(name="buffer_initial_length")
public RubyInteger buffer_initial_length_get(ThreadContext context) {
return context.getRuntime().newFixnum(bufferInitialLength);
@@ -389,11 +376,6 @@ public class GeneratorState extends RubyObject {
return buffer_initial_length;
}
- @JRubyMethod(name="quirks_mode?")
- public RubyBoolean quirks_mode_p(ThreadContext context) {
- return context.getRuntime().newBoolean(quirksMode);
- }
-
public int getDepth() {
return depth;
}
@@ -412,7 +394,7 @@ public class GeneratorState extends RubyObject {
private ByteList prepareByteList(ThreadContext context, IRubyObject value) {
RubyString str = value.convertToString();
RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
- if (info.encodingsSupported() && str.encoding(context) != info.utf8.get()) {
+ if (str.encoding(context) != info.utf8.get()) {
str = (RubyString)str.encode(context, info.utf8.get());
}
return str.getByteList().dup();
@@ -448,7 +430,6 @@ public class GeneratorState extends RubyObject {
maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
allowNaN = opts.getBool("allow_nan", DEFAULT_ALLOW_NAN);
asciiOnly = opts.getBool("ascii_only", DEFAULT_ASCII_ONLY);
- quirksMode = opts.getBool("quirks_mode", DEFAULT_QUIRKS_MODE);
bufferInitialLength = opts.getInt("buffer_initial_length", DEFAULT_BUFFER_INITIAL_LENGTH);
depth = opts.getInt("depth", 0);
@@ -475,7 +456,6 @@ public class GeneratorState extends RubyObject {
result.op_aset(context, runtime.newSymbol("array_nl"), array_nl_get(context));
result.op_aset(context, runtime.newSymbol("allow_nan"), allow_nan_p(context));
result.op_aset(context, runtime.newSymbol("ascii_only"), ascii_only_p(context));
- result.op_aset(context, runtime.newSymbol("quirks_mode"), quirks_mode_p(context));
result.op_aset(context, runtime.newSymbol("max_nesting"), max_nesting_get(context));
result.op_aset(context, runtime.newSymbol("depth"), depth_get(context));
result.op_aset(context, runtime.newSymbol("buffer_initial_length"), buffer_initial_length_get(context));
diff --git a/java/src/json/ext/OptionsReader.java b/java/src/json/ext/OptionsReader.java
index 9bb6e64..70426d4 100644
--- a/java/src/json/ext/OptionsReader.java
+++ b/java/src/json/ext/OptionsReader.java
@@ -84,7 +84,7 @@ final class OptionsReader {
RubyString str = value.convertToString();
RuntimeInfo info = getRuntimeInfo();
- if (info.encodingsSupported() && str.encoding(context) != info.utf8.get()) {
+ if (str.encoding(context) != info.utf8.get()) {
str = (RubyString)str.encode(context, info.utf8.get());
}
return str;
diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java
index 5458fb1..8c33840 100644
--- a/java/src/json/ext/Parser.java
+++ b/java/src/json/ext/Parser.java
@@ -52,10 +52,9 @@ public class Parser extends RubyObject {
private int maxNesting;
private boolean allowNaN;
private boolean symbolizeNames;
- private boolean quirksMode;
private RubyClass objectClass;
private RubyClass arrayClass;
- private RubyHash match_string;
+ private RubyHash matchString;
private static final int DEFAULT_MAX_NESTING = 100;
@@ -123,10 +122,6 @@ public class Parser extends RubyObject {
* <dd>If set to <code>true</code>, returns symbols for the names (keys) in
* a JSON object. Otherwise strings are returned, which is also the default.
*
- * <dt><code>:quirks_mode?</code>
- * <dd>If set to <code>true</code>, if the parse is in quirks_mode, false
- * otherwise.
- *
* <dt><code>:create_additions</code>
* <dd>If set to <code>false</code>, the Parser doesn't create additions
* even if a matching class and <code>create_id</code> was found. This option
@@ -138,9 +133,6 @@ public class Parser extends RubyObject {
* <dt><code>:array_class</code>
* <dd>Defaults to Array.
*
- * <dt><code>:quirks_mode</code>
- * <dd>Enables quirks_mode for parser, that is for example parsing single
- * JSON values instead of documents is possible.
* </dl>
*/
@JRubyMethod(name = "new", required = 1, optional = 1, meta = true)
@@ -163,15 +155,20 @@ public class Parser extends RubyObject {
this.maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
this.allowNaN = opts.getBool("allow_nan", false);
this.symbolizeNames = opts.getBool("symbolize_names", false);
- this.quirksMode = opts.getBool("quirks_mode", false);
this.createId = opts.getString("create_id", getCreateId(context));
this.createAdditions = opts.getBool("create_additions", false);
this.objectClass = opts.getClass("object_class", runtime.getHash());
this.arrayClass = opts.getClass("array_class", runtime.getArray());
- this.match_string = opts.getHash("match_string");
+ this.matchString = opts.getHash("match_string");
+ if(symbolizeNames && createAdditions) {
+ throw runtime.newArgumentError(
+ "options :symbolize_names and :create_additions cannot be " +
+ " used in conjunction"
+ );
+ }
this.vSource = args[0].convertToString();
- if (!quirksMode) this.vSource = convertEncoding(context, vSource);
+ this.vSource = convertEncoding(context, vSource);
return this;
}
@@ -182,33 +179,13 @@ public class Parser extends RubyObject {
* Returns the source string if no conversion is needed.
*/
private RubyString convertEncoding(ThreadContext context, RubyString source) {
- ByteList bl = source.getByteList();
- int len = bl.length();
- if (len < 2) {
- throw Utils.newException(context, Utils.M_PARSER_ERROR,
- "A JSON text must at least contain two octets!");
- }
-
- if (info.encodingsSupported()) {
- RubyEncoding encoding = (RubyEncoding)source.encoding(context);
- if (encoding != info.ascii8bit.get()) {
- return (RubyString)source.encode(context, info.utf8.get());
- }
-
- String sniffedEncoding = sniffByteList(bl);
- if (sniffedEncoding == null) return source; // assume UTF-8
- return reinterpretEncoding(context, source, sniffedEncoding);
- }
-
- String sniffedEncoding = sniffByteList(bl);
- if (sniffedEncoding == null) return source; // assume UTF-8
- Ruby runtime = context.getRuntime();
- return (RubyString)info.jsonModule.get().
- callMethod(context, "iconv",
- new IRubyObject[] {
- runtime.newString("utf-8"),
- runtime.newString(sniffedEncoding),
- source});
+ RubyEncoding encoding = (RubyEncoding)source.encoding(context);
+ if (encoding == info.ascii8bit.get()) {
+ source.force_encoding(context, info.utf8.get());
+ } else {
+ source = (RubyString) source.encode(context, info.utf8.get());
+ }
+ return source;
}
/**
@@ -261,17 +238,6 @@ public class Parser extends RubyObject {
return checkAndGetSource().dup();
}
- /**
- * <code>Parser#quirks_mode?()</code>
- *
- * <p>If set to <code>true</code>, if the parse is in quirks_mode, false
- * otherwise.
- */
- @JRubyMethod(name = "quirks_mode?")
- public IRubyObject quirks_mode_p(ThreadContext context) {
- return context.getRuntime().newBoolean(quirksMode);
- }
-
public RubyString checkAndGetSource() {
if (vSource != null) {
return vSource;
@@ -338,11 +304,11 @@ public class Parser extends RubyObject {
}
-// line 365 "Parser.rl"
+// line 330 "Parser.rl"
-// line 347 "Parser.java"
+// line 312 "Parser.java"
private static byte[] init__JSON_value_actions_0()
{
return new byte [] {
@@ -456,7 +422,7 @@ static final int JSON_value_error = 0;
static final int JSON_value_en_main = 1;
-// line 471 "Parser.rl"
+// line 436 "Parser.rl"
void parseValue(ParserResult res, int p, int pe) {
@@ -464,14 +430,14 @@ static final int JSON_value_en_main = 1;
IRubyObject result = null;
-// line 469 "Parser.java"
+// line 434 "Parser.java"
{
cs = JSON_value_start;
}
-// line 478 "Parser.rl"
+// line 443 "Parser.rl"
-// line 476 "Parser.java"
+// line 441 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -497,13 +463,13 @@ case 1:
while ( _nacts-- > 0 ) {
switch ( _JSON_value_actions[_acts++] ) {
case 9:
-// line 456 "Parser.rl"
+// line 421 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 508 "Parser.java"
+// line 473 "Parser.java"
}
}
@@ -566,25 +532,25 @@ case 1:
switch ( _JSON_value_actions[_acts++] )
{
case 0:
-// line 373 "Parser.rl"
+// line 338 "Parser.rl"
{
result = getRuntime().getNil();
}
break;
case 1:
-// line 376 "Parser.rl"
+// line 341 "Parser.rl"
{
result = getRuntime().getFalse();
}
break;
case 2:
-// line 379 "Parser.rl"
+// line 344 "Parser.rl"
{
result = getRuntime().getTrue();
}
break;
case 3:
-// line 382 "Parser.rl"
+// line 347 "Parser.rl"
{
if (parser.allowNaN) {
result = getConstant(CONST_NAN);
@@ -594,7 +560,7 @@ case 1:
}
break;
case 4:
-// line 389 "Parser.rl"
+// line 354 "Parser.rl"
{
if (parser.allowNaN) {
result = getConstant(CONST_INFINITY);
@@ -604,9 +570,9 @@ case 1:
}
break;
case 5:
-// line 396 "Parser.rl"
+// line 361 "Parser.rl"
{
- if (pe > p + 9 - (parser.quirksMode ? 1 : 0) &&
+ if (pe > p + 8 &&
absSubSequence(p, p + 9).equals(JSON_MINUS_INFINITY)) {
if (parser.allowNaN) {
@@ -633,7 +599,7 @@ case 1:
}
break;
case 6:
-// line 422 "Parser.rl"
+// line 387 "Parser.rl"
{
parseString(res, p, pe);
if (res.result == null) {
@@ -646,7 +612,7 @@ case 1:
}
break;
case 7:
-// line 432 "Parser.rl"
+// line 397 "Parser.rl"
{
currentNesting++;
parseArray(res, p, pe);
@@ -661,7 +627,7 @@ case 1:
}
break;
case 8:
-// line 444 "Parser.rl"
+// line 409 "Parser.rl"
{
currentNesting++;
parseObject(res, p, pe);
@@ -675,7 +641,7 @@ case 1:
}
}
break;
-// line 680 "Parser.java"
+// line 645 "Parser.java"
}
}
}
@@ -695,7 +661,7 @@ case 5:
break; }
}
-// line 479 "Parser.rl"
+// line 444 "Parser.rl"
if (cs >= JSON_value_first_final && result != null) {
res.update(result, p);
@@ -705,7 +671,7 @@ case 5:
}
-// line 710 "Parser.java"
+// line 675 "Parser.java"
private static byte[] init__JSON_integer_actions_0()
{
return new byte [] {
@@ -804,7 +770,7 @@ static final int JSON_integer_error = 0;
static final int JSON_integer_en_main = 1;
-// line 498 "Parser.rl"
+// line 463 "Parser.rl"
void parseInteger(ParserResult res, int p, int pe) {
@@ -822,15 +788,15 @@ static final int JSON_integer_en_main = 1;
int cs = EVIL;
-// line 827 "Parser.java"
+// line 792 "Parser.java"
{
cs = JSON_integer_start;
}
-// line 515 "Parser.rl"
+// line 480 "Parser.rl"
int memo = p;
-// line 835 "Parser.java"
+// line 800 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -911,13 +877,13 @@ case 1:
switch ( _JSON_integer_actions[_acts++] )
{
case 0:
-// line 492 "Parser.rl"
+// line 457 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 922 "Parser.java"
+// line 887 "Parser.java"
}
}
}
@@ -937,7 +903,7 @@ case 5:
break; }
}
-// line 517 "Parser.rl"
+// line 482 "Parser.rl"
if (cs < JSON_integer_first_final) {
return -1;
@@ -959,7 +925,7 @@ case 5:
}
-// line 964 "Parser.java"
+// line 929 "Parser.java"
private static byte[] init__JSON_float_actions_0()
{
return new byte [] {
@@ -1061,7 +1027,7 @@ static final int JSON_float_error = 0;
static final int JSON_float_en_main = 1;
-// line 552 "Parser.rl"
+// line 517 "Parser.rl"
void parseFloat(ParserResult res, int p, int pe) {
@@ -1079,15 +1045,15 @@ static final int JSON_float_en_main = 1;
int cs = EVIL;
-// line 1084 "Parser.java"
+// line 1049 "Parser.java"
{
cs = JSON_float_start;
}
-// line 569 "Parser.rl"
+// line 534 "Parser.rl"
int memo = p;
-// line 1092 "Parser.java"
+// line 1057 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1168,13 +1134,13 @@ case 1:
switch ( _JSON_float_actions[_acts++] )
{
case 0:
-// line 543 "Parser.rl"
+// line 508 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1179 "Parser.java"
+// line 1144 "Parser.java"
}
}
}
@@ -1194,7 +1160,7 @@ case 5:
break; }
}
-// line 571 "Parser.rl"
+// line 536 "Parser.rl"
if (cs < JSON_float_first_final) {
return -1;
@@ -1210,7 +1176,7 @@ case 5:
}
-// line 1215 "Parser.java"
+// line 1180 "Parser.java"
private static byte[] init__JSON_string_actions_0()
{
return new byte [] {
@@ -1312,7 +1278,7 @@ static final int JSON_string_error = 0;
static final int JSON_string_en_main = 1;
-// line 616 "Parser.rl"
+// line 581 "Parser.rl"
void parseString(ParserResult res, int p, int pe) {
@@ -1320,15 +1286,15 @@ static final int JSON_string_en_main = 1;
IRubyObject result = null;
-// line 1325 "Parser.java"
+// line 1290 "Parser.java"
{
cs = JSON_string_start;
}
-// line 623 "Parser.rl"
+// line 588 "Parser.rl"
int memo = p;
-// line 1333 "Parser.java"
+// line 1298 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1409,7 +1375,7 @@ case 1:
switch ( _JSON_string_actions[_acts++] )
{
case 0:
-// line 591 "Parser.rl"
+// line 556 "Parser.rl"
{
int offset = byteList.begin();
ByteList decoded = decoder.decode(byteList, memo + 1 - offset,
@@ -1424,13 +1390,13 @@ case 1:
}
break;
case 1:
-// line 604 "Parser.rl"
+// line 569 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1435 "Parser.java"
+// line 1400 "Parser.java"
}
}
}
@@ -1450,14 +1416,14 @@ case 5:
break; }
}
-// line 625 "Parser.rl"
+// line 590 "Parser.rl"
if (parser.createAdditions) {
- RubyHash match_string = parser.match_string;
- if (match_string != null) {
+ RubyHash matchString = parser.matchString;
+ if (matchString != null) {
final IRubyObject[] memoArray = { result, null };
try {
- match_string.visitAll(new RubyHash.Visitor() {
+ matchString.visitAll(new RubyHash.Visitor() {
@Override
public void visit(IRubyObject pattern, IRubyObject klass) {
if (pattern.callMethod(context, "===", memoArray[0]).isTrue()) {
@@ -1478,7 +1444,7 @@ case 5:
}
if (cs >= JSON_string_first_final && result != null) {
- if (info.encodingsSupported() && result instanceof RubyString) {
+ if (result instanceof RubyString) {
((RubyString)result).force_encoding(context, info.utf8.get());
}
res.update(result, p + 1);
@@ -1488,7 +1454,7 @@ case 5:
}
-// line 1493 "Parser.java"
+// line 1458 "Parser.java"
private static byte[] init__JSON_array_actions_0()
{
return new byte [] {
@@ -1601,7 +1567,7 @@ static final int JSON_array_error = 0;
static final int JSON_array_en_main = 1;
-// line 698 "Parser.rl"
+// line 663 "Parser.rl"
void parseArray(ParserResult res, int p, int pe) {
@@ -1621,14 +1587,14 @@ static final int JSON_array_en_main = 1;
}
-// line 1626 "Parser.java"
+// line 1591 "Parser.java"
{
cs = JSON_array_start;
}
-// line 717 "Parser.rl"
+// line 682 "Parser.rl"
-// line 1633 "Parser.java"
+// line 1598 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1709,7 +1675,7 @@ case 1:
switch ( _JSON_array_actions[_acts++] )
{
case 0:
-// line 667 "Parser.rl"
+// line 632 "Parser.rl"
{
parseValue(res, p, pe);
if (res.result == null) {
@@ -1726,13 +1692,13 @@ case 1:
}
break;
case 1:
-// line 682 "Parser.rl"
+// line 647 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1737 "Parser.java"
+// line 1702 "Parser.java"
}
}
}
@@ -1752,7 +1718,7 @@ case 5:
break; }
}
-// line 718 "Parser.rl"
+// line 683 "Parser.rl"
if (cs >= JSON_array_first_final) {
res.update(result, p + 1);
@@ -1762,7 +1728,7 @@ case 5:
}
-// line 1767 "Parser.java"
+// line 1732 "Parser.java"
private static byte[] init__JSON_object_actions_0()
{
return new byte [] {
@@ -1885,7 +1851,7 @@ static final int JSON_object_error = 0;
static final int JSON_object_en_main = 1;
-// line 777 "Parser.rl"
+// line 742 "Parser.rl"
void parseObject(ParserResult res, int p, int pe) {
@@ -1910,14 +1876,14 @@ static final int JSON_object_en_main = 1;
}
-// line 1915 "Parser.java"
+// line 1880 "Parser.java"
{
cs = JSON_object_start;
}
-// line 801 "Parser.rl"
+// line 766 "Parser.rl"
-// line 1922 "Parser.java"
+// line 1887 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1998,7 +1964,7 @@ case 1:
switch ( _JSON_object_actions[_acts++] )
{
case 0:
-// line 732 "Parser.rl"
+// line 697 "Parser.rl"
{
parseValue(res, p, pe);
if (res.result == null) {
@@ -2015,7 +1981,7 @@ case 1:
}
break;
case 1:
-// line 747 "Parser.rl"
+// line 712 "Parser.rl"
{
parseString(res, p, pe);
if (res.result == null) {
@@ -2035,13 +2001,13 @@ case 1:
}
break;
case 2:
-// line 765 "Parser.rl"
+// line 730 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 2046 "Parser.java"
+// line 2011 "Parser.java"
}
}
}
@@ -2061,7 +2027,7 @@ case 5:
break; }
}
-// line 802 "Parser.rl"
+// line 767 "Parser.rl"
if (cs < JSON_object_first_final) {
res.update(null, p + 1);
@@ -2094,11 +2060,11 @@ case 5:
}
-// line 2099 "Parser.java"
+// line 2064 "Parser.java"
private static byte[] init__JSON_actions_0()
{
return new byte [] {
- 0, 1, 0, 1, 1
+ 0, 1, 0
};
}
@@ -2108,7 +2074,7 @@ private static final byte _JSON_actions[] = init__JSON_actions_0();
private static byte[] init__JSON_key_offsets_0()
{
return new byte [] {
- 0, 0, 7, 9, 10, 12, 13, 15, 16, 18, 19
+ 0, 0, 16, 18, 19, 21, 22, 24, 25, 27, 28
};
}
@@ -2118,9 +2084,9 @@ private static final byte _JSON_key_offsets[] = init__JSON_key_offsets_0();
private static char[] init__JSON_trans_keys_0()
{
return new char [] {
- 13, 32, 47, 91, 123, 9, 10, 42, 47, 42, 42, 47,
- 10, 42, 47, 42, 42, 47, 10, 13, 32, 47, 9, 10,
- 0
+ 13, 32, 34, 45, 47, 73, 78, 91, 102, 110, 116, 123,
+ 9, 10, 48, 57, 42, 47, 42, 42, 47, 10, 42, 47,
+ 42, 42, 47, 10, 13, 32, 47, 9, 10, 0
};
}
@@ -2130,7 +2096,7 @@ private static final char _JSON_trans_keys[] = init__JSON_trans_keys_0();
private static byte[] init__JSON_single_lengths_0()
{
return new byte [] {
- 0, 5, 2, 1, 2, 1, 2, 1, 2, 1, 3
+ 0, 12, 2, 1, 2, 1, 2, 1, 2, 1, 3
};
}
@@ -2140,7 +2106,7 @@ private static final byte _JSON_single_lengths[] = init__JSON_single_lengths_0()
private static byte[] init__JSON_range_lengths_0()
{
return new byte [] {
- 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
}
@@ -2150,7 +2116,7 @@ private static final byte _JSON_range_lengths[] = init__JSON_range_lengths_0();
private static byte[] init__JSON_index_offsets_0()
{
return new byte [] {
- 0, 0, 7, 10, 12, 15, 17, 20, 22, 25, 27
+ 0, 0, 15, 18, 20, 23, 25, 28, 30, 33, 35
};
}
@@ -2160,9 +2126,10 @@ private static final byte _JSON_index_offsets[] = init__JSON_index_offsets_0();
private static byte[] init__JSON_indicies_0()
{
return new byte [] {
- 0, 0, 2, 3, 4, 0, 1, 5, 6, 1, 7, 5,
- 7, 0, 5, 0, 6, 8, 9, 1, 10, 8, 10, 11,
- 8, 11, 9, 11, 11, 12, 11, 1, 0
+ 0, 0, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 1, 4, 5, 1, 6, 4, 6, 7, 4, 7,
+ 5, 8, 9, 1, 10, 8, 10, 0, 8, 0, 9, 7,
+ 7, 11, 7, 1, 0
};
}
@@ -2172,8 +2139,7 @@ private static final byte _JSON_indicies[] = init__JSON_indicies_0();
private static byte[] init__JSON_trans_targs_0()
{
return new byte [] {
- 1, 0, 2, 10, 10, 3, 5, 4, 7, 9, 8, 10,
- 6
+ 1, 0, 10, 6, 3, 5, 4, 10, 7, 9, 8, 2
};
}
@@ -2183,8 +2149,7 @@ private static final byte _JSON_trans_targs[] = init__JSON_trans_targs_0();
private static byte[] init__JSON_trans_actions_0()
{
return new byte [] {
- 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0,
- 0
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
}
@@ -2198,26 +2163,26 @@ static final int JSON_error = 0;
static final int JSON_en_main = 1;
-// line 867 "Parser.rl"
+// line 818 "Parser.rl"
- public IRubyObject parseStrict() {
+ public IRubyObject parseImplemetation() {
int cs = EVIL;
int p, pe;
IRubyObject result = null;
ParserResult res = new ParserResult();
-// line 2213 "Parser.java"
+// line 2177 "Parser.java"
{
cs = JSON_start;
}
-// line 876 "Parser.rl"
+// line 827 "Parser.rl"
p = byteList.begin();
pe = p + byteList.length();
-// line 2222 "Parser.java"
+// line 2186 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -2298,267 +2263,7 @@ case 1:
switch ( _JSON_actions[_acts++] )
{
case 0:
-// line 839 "Parser.rl"
- {
- currentNesting = 1;
- parseObject(res, p, pe);
- if (res.result == null) {
- p--;
- { p += 1; _goto_targ = 5; if (true) continue _goto;}
- } else {
- result = res.result;
- {p = (( res.p))-1;}
- }
- }
- break;
- case 1:
-// line 851 "Parser.rl"
- {
- currentNesting = 1;
- parseArray(res, p, pe);
- if (res.result == null) {
- p--;
- { p += 1; _goto_targ = 5; if (true) continue _goto;}
- } else {
- result = res.result;
- {p = (( res.p))-1;}
- }
- }
- break;
-// line 2330 "Parser.java"
- }
- }
- }
-
-case 2:
- if ( cs == 0 ) {
- _goto_targ = 5;
- continue _goto;
- }
- if ( ++p != pe ) {
- _goto_targ = 1;
- continue _goto;
- }
-case 4:
-case 5:
- }
- break; }
- }
-
-// line 879 "Parser.rl"
-
- if (cs >= JSON_first_final && p == pe) {
- return result;
- } else {
- throw unexpectedToken(p, pe);
- }
- }
-
-
-// line 2360 "Parser.java"
-private static byte[] init__JSON_quirks_mode_actions_0()
-{
- return new byte [] {
- 0, 1, 0
- };
-}
-
-private static final byte _JSON_quirks_mode_actions[] = init__JSON_quirks_mode_actions_0();
-
-
-private static byte[] init__JSON_quirks_mode_key_offsets_0()
-{
- return new byte [] {
- 0, 0, 16, 18, 19, 21, 22, 24, 25, 27, 28
- };
-}
-
-private static final byte _JSON_quirks_mode_key_offsets[] = init__JSON_quirks_mode_key_offsets_0();
-
-
-private static char[] init__JSON_quirks_mode_trans_keys_0()
-{
- return new char [] {
- 13, 32, 34, 45, 47, 73, 78, 91, 102, 110, 116, 123,
- 9, 10, 48, 57, 42, 47, 42, 42, 47, 10, 42, 47,
- 42, 42, 47, 10, 13, 32, 47, 9, 10, 0
- };
-}
-
-private static final char _JSON_quirks_mode_trans_keys[] = init__JSON_quirks_mode_trans_keys_0();
-
-
-private static byte[] init__JSON_quirks_mode_single_lengths_0()
-{
- return new byte [] {
- 0, 12, 2, 1, 2, 1, 2, 1, 2, 1, 3
- };
-}
-
-private static final byte _JSON_quirks_mode_single_lengths[] = init__JSON_quirks_mode_single_lengths_0();
-
-
-private static byte[] init__JSON_quirks_mode_range_lengths_0()
-{
- return new byte [] {
- 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1
- };
-}
-
-private static final byte _JSON_quirks_mode_range_lengths[] = init__JSON_quirks_mode_range_lengths_0();
-
-
-private static byte[] init__JSON_quirks_mode_index_offsets_0()
-{
- return new byte [] {
- 0, 0, 15, 18, 20, 23, 25, 28, 30, 33, 35
- };
-}
-
-private static final byte _JSON_quirks_mode_index_offsets[] = init__JSON_quirks_mode_index_offsets_0();
-
-
-private static byte[] init__JSON_quirks_mode_indicies_0()
-{
- return new byte [] {
- 0, 0, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2,
- 0, 2, 1, 4, 5, 1, 6, 4, 6, 7, 4, 7,
- 5, 8, 9, 1, 10, 8, 10, 0, 8, 0, 9, 7,
- 7, 11, 7, 1, 0
- };
-}
-
-private static final byte _JSON_quirks_mode_indicies[] = init__JSON_quirks_mode_indicies_0();
-
-
-private static byte[] init__JSON_quirks_mode_trans_targs_0()
-{
- return new byte [] {
- 1, 0, 10, 6, 3, 5, 4, 10, 7, 9, 8, 2
- };
-}
-
-private static final byte _JSON_quirks_mode_trans_targs[] = init__JSON_quirks_mode_trans_targs_0();
-
-
-private static byte[] init__JSON_quirks_mode_trans_actions_0()
-{
- return new byte [] {
- 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
-}
-
-private static final byte _JSON_quirks_mode_trans_actions[] = init__JSON_quirks_mode_trans_actions_0();
-
-
-static final int JSON_quirks_mode_start = 1;
-static final int JSON_quirks_mode_first_final = 10;
-static final int JSON_quirks_mode_error = 0;
-
-static final int JSON_quirks_mode_en_main = 1;
-
-
-// line 907 "Parser.rl"
-
-
- public IRubyObject parseQuirksMode() {
- int cs = EVIL;
- int p, pe;
- IRubyObject result = null;
- ParserResult res = new ParserResult();
-
-
-// line 2473 "Parser.java"
- {
- cs = JSON_quirks_mode_start;
- }
-
-// line 916 "Parser.rl"
- p = byteList.begin();
- pe = p + byteList.length();
-
-// line 2482 "Parser.java"
- {
- int _klen;
- int _trans = 0;
- int _acts;
- int _nacts;
- int _keys;
- int _goto_targ = 0;
-
- _goto: while (true) {
- switch ( _goto_targ ) {
- case 0:
- if ( p == pe ) {
- _goto_targ = 4;
- continue _goto;
- }
- if ( cs == 0 ) {
- _goto_targ = 5;
- continue _goto;
- }
-case 1:
- _match: do {
- _keys = _JSON_quirks_mode_key_offsets[cs];
- _trans = _JSON_quirks_mode_index_offsets[cs];
- _klen = _JSON_quirks_mode_single_lengths[cs];
- if ( _klen > 0 ) {
- int _lower = _keys;
- int _mid;
- int _upper = _keys + _klen - 1;
- while (true) {
- if ( _upper < _lower )
- break;
-
- _mid = _lower + ((_upper-_lower) >> 1);
- if ( data[p] < _JSON_quirks_mode_trans_keys[_mid] )
- _upper = _mid - 1;
- else if ( data[p] > _JSON_quirks_mode_trans_keys[_mid] )
- _lower = _mid + 1;
- else {
- _trans += (_mid - _keys);
- break _match;
- }
- }
- _keys += _klen;
- _trans += _klen;
- }
-
- _klen = _JSON_quirks_mode_range_lengths[cs];
- if ( _klen > 0 ) {
- int _lower = _keys;
- int _mid;
- int _upper = _keys + (_klen<<1) - 2;
- while (true) {
- if ( _upper < _lower )
- break;
-
- _mid = _lower + (((_upper-_lower) >> 1) & ~1);
- if ( data[p] < _JSON_quirks_mode_trans_keys[_mid] )
- _upper = _mid - 2;
- else if ( data[p] > _JSON_quirks_mode_trans_keys[_mid+1] )
- _lower = _mid + 2;
- else {
- _trans += ((_mid - _keys)>>1);
- break _match;
- }
- }
- _trans += _klen;
- }
- } while (false);
-
- _trans = _JSON_quirks_mode_indicies[_trans];
- cs = _JSON_quirks_mode_trans_targs[_trans];
-
- if ( _JSON_quirks_mode_trans_actions[_trans] != 0 ) {
- _acts = _JSON_quirks_mode_trans_actions[_trans];
- _nacts = (int) _JSON_quirks_mode_actions[_acts++];
- while ( _nacts-- > 0 )
- {
- switch ( _JSON_quirks_mode_actions[_acts++] )
- {
- case 0:
-// line 893 "Parser.rl"
+// line 804 "Parser.rl"
{
parseValue(res, p, pe);
if (res.result == null) {
@@ -2570,7 +2275,7 @@ case 1:
}
}
break;
-// line 2575 "Parser.java"
+// line 2279 "Parser.java"
}
}
}
@@ -2590,9 +2295,9 @@ case 5:
break; }
}
-// line 919 "Parser.rl"
+// line 830 "Parser.rl"
- if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ if (cs >= JSON_first_final && p == pe) {
return result;
} else {
throw unexpectedToken(p, pe);
@@ -2600,12 +2305,7 @@ case 5:
}
public IRubyObject parse() {
- if (parser.quirksMode) {
- return parseQuirksMode();
- } else {
- return parseStrict();
- }
-
+ return parseImplemetation();
}
/**
diff --git a/java/src/json/ext/Parser.rl b/java/src/json/ext/Parser.rl
index d43c74f..28247ea 100644
--- a/java/src/json/ext/Parser.rl
+++ b/java/src/json/ext/Parser.rl
@@ -50,10 +50,9 @@ public class Parser extends RubyObject {
private int maxNesting;
private boolean allowNaN;
private boolean symbolizeNames;
- private boolean quirksMode;
private RubyClass objectClass;
private RubyClass arrayClass;
- private RubyHash match_string;
+ private RubyHash matchString;
private static final int DEFAULT_MAX_NESTING = 100;
@@ -121,10 +120,6 @@ public class Parser extends RubyObject {
* <dd>If set to <code>true</code>, returns symbols for the names (keys) in
* a JSON object. Otherwise strings are returned, which is also the default.
*
- * <dt><code>:quirks_mode?</code>
- * <dd>If set to <code>true</code>, if the parse is in quirks_mode, false
- * otherwise.
- *
* <dt><code>:create_additions</code>
* <dd>If set to <code>false</code>, the Parser doesn't create additions
* even if a matching class and <code>create_id</code> was found. This option
@@ -136,9 +131,6 @@ public class Parser extends RubyObject {
* <dt><code>:array_class</code>
* <dd>Defaults to Array.
*
- * <dt><code>:quirks_mode</code>
- * <dd>Enables quirks_mode for parser, that is for example parsing single
- * JSON values instead of documents is possible.
* </dl>
*/
@JRubyMethod(name = "new", required = 1, optional = 1, meta = true)
@@ -161,15 +153,20 @@ public class Parser extends RubyObject {
this.maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
this.allowNaN = opts.getBool("allow_nan", false);
this.symbolizeNames = opts.getBool("symbolize_names", false);
- this.quirksMode = opts.getBool("quirks_mode", false);
this.createId = opts.getString("create_id", getCreateId(context));
this.createAdditions = opts.getBool("create_additions", false);
this.objectClass = opts.getClass("object_class", runtime.getHash());
this.arrayClass = opts.getClass("array_class", runtime.getArray());
- this.match_string = opts.getHash("match_string");
+ this.matchString = opts.getHash("match_string");
+ if(symbolizeNames && createAdditions) {
+ throw runtime.newArgumentError(
+ "options :symbolize_names and :create_additions cannot be " +
+ " used in conjunction"
+ );
+ }
this.vSource = args[0].convertToString();
- if (!quirksMode) this.vSource = convertEncoding(context, vSource);
+ this.vSource = convertEncoding(context, vSource);
return this;
}
@@ -180,33 +177,13 @@ public class Parser extends RubyObject {
* Returns the source string if no conversion is needed.
*/
private RubyString convertEncoding(ThreadContext context, RubyString source) {
- ByteList bl = source.getByteList();
- int len = bl.length();
- if (len < 2) {
- throw Utils.newException(context, Utils.M_PARSER_ERROR,
- "A JSON text must at least contain two octets!");
- }
-
- if (info.encodingsSupported()) {
- RubyEncoding encoding = (RubyEncoding)source.encoding(context);
- if (encoding != info.ascii8bit.get()) {
- return (RubyString)source.encode(context, info.utf8.get());
- }
-
- String sniffedEncoding = sniffByteList(bl);
- if (sniffedEncoding == null) return source; // assume UTF-8
- return reinterpretEncoding(context, source, sniffedEncoding);
- }
-
- String sniffedEncoding = sniffByteList(bl);
- if (sniffedEncoding == null) return source; // assume UTF-8
- Ruby runtime = context.getRuntime();
- return (RubyString)info.jsonModule.get().
- callMethod(context, "iconv",
- new IRubyObject[] {
- runtime.newString("utf-8"),
- runtime.newString(sniffedEncoding),
- source});
+ RubyEncoding encoding = (RubyEncoding)source.encoding(context);
+ if (encoding == info.ascii8bit.get()) {
+ source.force_encoding(context, info.utf8.get());
+ } else {
+ source = (RubyString) source.encode(context, info.utf8.get());
+ }
+ return source;
}
/**
@@ -259,17 +236,6 @@ public class Parser extends RubyObject {
return checkAndGetSource().dup();
}
- /**
- * <code>Parser#quirks_mode?()</code>
- *
- * <p>If set to <code>true</code>, if the parse is in quirks_mode, false
- * otherwise.
- */
- @JRubyMethod(name = "quirks_mode?")
- public IRubyObject quirks_mode_p(ThreadContext context) {
- return context.getRuntime().newBoolean(quirksMode);
- }
-
public RubyString checkAndGetSource() {
if (vSource != null) {
return vSource;
@@ -393,7 +359,7 @@ public class Parser extends RubyObject {
}
}
action parse_number {
- if (pe > fpc + 9 - (parser.quirksMode ? 1 : 0) &&
+ if (pe > fpc + 8 &&
absSubSequence(fpc, fpc + 9).equals(JSON_MINUS_INFINITY)) {
if (parser.allowNaN) {
@@ -623,11 +589,11 @@ public class Parser extends RubyObject {
%% write exec;
if (parser.createAdditions) {
- RubyHash match_string = parser.match_string;
- if (match_string != null) {
+ RubyHash matchString = parser.matchString;
+ if (matchString != null) {
final IRubyObject[] memoArray = { result, null };
try {
- match_string.visitAll(new RubyHash.Visitor() {
+ matchString.visitAll(new RubyHash.Visitor() {
@Override
public void visit(IRubyObject pattern, IRubyObject klass) {
if (pattern.callMethod(context, "===", memoArray[0]).isTrue()) {
@@ -648,7 +614,7 @@ public class Parser extends RubyObject {
}
if (cs >= JSON_string_first_final && result != null) {
- if (info.encodingsSupported() && result instanceof RubyString) {
+ if (result instanceof RubyString) {
((RubyString)result).force_encoding(context, info.utf8.get());
}
res.update(result, p + 1);
@@ -835,60 +801,6 @@ public class Parser extends RubyObject {
write data;
- action parse_object {
- currentNesting = 1;
- parseObject(res, fpc, pe);
- if (res.result == null) {
- fhold;
- fbreak;
- } else {
- result = res.result;
- fexec res.p;
- }
- }
-
- action parse_array {
- currentNesting = 1;
- parseArray(res, fpc, pe);
- if (res.result == null) {
- fhold;
- fbreak;
- } else {
- result = res.result;
- fexec res.p;
- }
- }
-
- main := ignore*
- ( begin_object >parse_object
- | begin_array >parse_array )
- ignore*;
- }%%
-
- public IRubyObject parseStrict() {
- int cs = EVIL;
- int p, pe;
- IRubyObject result = null;
- ParserResult res = new ParserResult();
-
- %% write init;
- p = byteList.begin();
- pe = p + byteList.length();
- %% write exec;
-
- if (cs >= JSON_first_final && p == pe) {
- return result;
- } else {
- throw unexpectedToken(p, pe);
- }
- }
-
- %%{
- machine JSON_quirks_mode;
- include JSON_common;
-
- write data;
-
action parse_value {
parseValue(res, fpc, pe);
if (res.result == null) {
@@ -905,7 +817,7 @@ public class Parser extends RubyObject {
ignore*;
}%%
- public IRubyObject parseQuirksMode() {
+ public IRubyObject parseImplemetation() {
int cs = EVIL;
int p, pe;
IRubyObject result = null;
@@ -916,7 +828,7 @@ public class Parser extends RubyObject {
pe = p + byteList.length();
%% write exec;
- if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ if (cs >= JSON_first_final && p == pe) {
return result;
} else {
throw unexpectedToken(p, pe);
@@ -924,12 +836,7 @@ public class Parser extends RubyObject {
}
public IRubyObject parse() {
- if (parser.quirksMode) {
- return parseQuirksMode();
- } else {
- return parseStrict();
- }
-
+ return parseImplemetation();
}
/**
diff --git a/java/src/json/ext/RuntimeInfo.java b/java/src/json/ext/RuntimeInfo.java
index ceaca5b..2323bd9 100644
--- a/java/src/json/ext/RuntimeInfo.java
+++ b/java/src/json/ext/RuntimeInfo.java
@@ -90,10 +90,6 @@ final class RuntimeInfo {
}
}
- public boolean encodingsSupported() {
- return utf8 != null && utf8.get() != null;
- }
-
public RubyEncoding getEncoding(ThreadContext context, String name) {
synchronized (encodings) {
WeakReference<RubyEncoding> encoding = encodings.get(name);
diff --git a/json.gemspec b/json.gemspec
index a9493ff..ca023f7 100644
--- a/json.gemspec
+++ b/json.gemspec
Binary files differ
diff --git a/json_pure.gemspec b/json_pure.gemspec
index 13c8e8b..c2fb15f 100644
--- a/json_pure.gemspec
+++ b/json_pure.gemspec
@@ -8,11 +8,11 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib"]
s.authors = ["Florian Frank"]
- s.date = "2016-02-25"
+ s.date = "2016-06-07"
s.description = "This is a JSON implementation in pure Ruby."
s.email = "flori@ping.de"
s.extra_rdoc_files = ["README.md"]
- s.files = ["./tests/test_helper.rb", ".gitignore", ".travis.yml", "CHANGES", "Gemfile", "README-json-jruby.markdown", "README.md", "Rakefile", "TODO", "VERSION", "data/example.json", "data/index.html", "data/prototype.js", "diagrams/.keep", "ext/json/ext/fbuffer/fbuffer.h", "ext/json/ext/generator/depend", "ext/json/ext/generator/extconf.rb", "ext/json/ext/generator/generator.c", "ext/json/ext/generator/generator.h", "ext/json/ext/parser/depend", "ext/json/ext/parser/extconf.rb", "ext/json/ext/parser/parser.c", "ext/json/ext/parser/parser.h", "ext/json/ext/parser/parser.rl", "ext/json/extconf.rb", "install.rb", "java/src/json/ext/ByteListTranscoder.java", "java/src/json/ext/Generator.java", "java/src/json/ext/GeneratorMethods.java", "java/src/json/ext/GeneratorService.java", "java/src/json/ext/GeneratorState.java", "java/src/json/ext/OptionsReader.java", "java/src/json/ext/Parser.java", "java/src/json/ext/Parser.rl", "java/src/json/ext/ParserService.java", "java/src/json/ext/RuntimeInfo.java", "java/src/json/ext/StringDecoder.java", "java/src/json/ext/StringEncoder.java", "java/src/json/ext/Utils.java", "json-java.gemspec", "json.gemspec", "json_pure.gemspec", "lib/json.rb", "lib/json/add/bigdecimal.rb", "lib/json/add/complex.rb", "lib/json/add/core.rb", "lib/json/add/date.rb", "lib/json/add/date_time.rb", "lib/json/add/exception.rb", "lib/json/add/ostruct.rb", "lib/json/add/range.rb", "lib/json/add/rational.rb", "lib/json/add/regexp.rb", "lib/json/add/struct.rb", "lib/json/add/symbol.rb", "lib/json/add/time.rb", "lib/json/common.rb", "lib/json/ext.rb", "lib/json/ext/.keep", "lib/json/generic_object.rb", "lib/json/pure.rb", "lib/json/pure/generator.rb", "lib/json/pure/parser.rb", "lib/json/version.rb", "tests/fixtures/fail10.json", "tests/fixtures/fail11.json", "tests/fixtures/fail12.json", "tests/fixtures/fail13.json", "tests/fixtures/fail14.json", "tests/fixtures/fail18.json", "tests/fixtures/fail19.json", "tests/fixtures/fail2.json", "tests/fixtures/fail20.json", "tests/fixtures/fail21.json", "tests/fixtures/fail22.json", "tests/fixtures/fail23.json", "tests/fixtures/fail24.json", "tests/fixtures/fail25.json", "tests/fixtures/fail27.json", "tests/fixtures/fail28.json", "tests/fixtures/fail3.json", "tests/fixtures/fail4.json", "tests/fixtures/fail5.json", "tests/fixtures/fail6.json", "tests/fixtures/fail7.json", "tests/fixtures/fail8.json", "tests/fixtures/fail9.json", "tests/fixtures/obsolete_fail1.json", "tests/fixtures/pass1.json", "tests/fixtures/pass15.json", "tests/fixtures/pass16.json", "tests/fixtures/pass17.json", "tests/fixtures/pass2.json", "tests/fixtures/pass26.json", "tests/fixtures/pass3.json", "tests/json_addition_test.rb", "tests/json_common_interface_test.rb", "tests/json_encoding_test.rb", "tests/json_ext_parser_test.rb", "tests/json_fixtures_test.rb", "tests/json_generator_test.rb", "tests/json_generic_object_test.rb", "tests/json_parser_test.rb", "tests/json_string_matching_test.rb", "tests/test_helper.rb", "tools/fuzz.rb", "tools/server.rb"]
+ s.files = ["./tests/test_helper.rb", ".gitignore", ".travis.yml", "CHANGES", "Gemfile", "README-json-jruby.markdown", "README.md", "Rakefile", "VERSION", "data/example.json", "data/index.html", "data/prototype.js", "diagrams/.keep", "ext/json/ext/fbuffer/fbuffer.h", "ext/json/ext/generator/depend", "ext/json/ext/generator/extconf.rb", "ext/json/ext/generator/generator.c", "ext/json/ext/generator/generator.h", "ext/json/ext/parser/depend", "ext/json/ext/parser/extconf.rb", "ext/json/ext/parser/parser.c", "ext/json/ext/parser/parser.h", "ext/json/ext/parser/parser.rl", "ext/json/extconf.rb", "install.rb", "java/src/json/ext/ByteListTranscoder.java", "java/src/json/ext/Generator.java", "java/src/json/ext/GeneratorMethods.java", "java/src/json/ext/GeneratorService.java", "java/src/json/ext/GeneratorState.java", "java/src/json/ext/OptionsReader.java", "java/src/json/ext/Parser.java", "java/src/json/ext/Parser.rl", "java/src/json/ext/ParserService.java", "java/src/json/ext/RuntimeInfo.java", "java/src/json/ext/StringDecoder.java", "java/src/json/ext/StringEncoder.java", "java/src/json/ext/Utils.java", "json-java.gemspec", "json.gemspec", "json_pure.gemspec", "lib/json.rb", "lib/json/add/bigdecimal.rb", "lib/json/add/complex.rb", "lib/json/add/core.rb", "lib/json/add/date.rb", "lib/json/add/date_time.rb", "lib/json/add/exception.rb", "lib/json/add/ostruct.rb", "lib/json/add/range.rb", "lib/json/add/rational.rb", "lib/json/add/regexp.rb", "lib/json/add/struct.rb", "lib/json/add/symbol.rb", "lib/json/add/time.rb", "lib/json/common.rb", "lib/json/ext.rb", "lib/json/ext/.keep", "lib/json/generic_object.rb", "lib/json/pure.rb", "lib/json/pure/generator.rb", "lib/json/pure/parser.rb", "lib/json/version.rb", "references/rfc7159.txt", "tests/fixtures/fail10.json", "tests/fixtures/fail11.json", "tests/fixtures/fail12.json", "tests/fixtures/fail13.json", "tests/fixtures/fail14.json", "tests/fixtures/fail18.json", "tests/fixtures/fail19.json", "tests/fixtures/fail2.json", "tests/fixtures/fail20.json", "tests/fixtures/fail21.json", "tests/fixtures/fail22.json", "tests/fixtures/fail23.json", "tests/fixtures/fail24.json", "tests/fixtures/fail25.json", "tests/fixtures/fail27.json", "tests/fixtures/fail28.json", "tests/fixtures/fail3.json", "tests/fixtures/fail4.json", "tests/fixtures/fail5.json", "tests/fixtures/fail6.json", "tests/fixtures/fail7.json", "tests/fixtures/fail8.json", "tests/fixtures/fail9.json", "tests/fixtures/obsolete_fail1.json", "tests/fixtures/pass1.json", "tests/fixtures/pass15.json", "tests/fixtures/pass16.json", "tests/fixtures/pass17.json", "tests/fixtures/pass2.json", "tests/fixtures/pass26.json", "tests/fixtures/pass3.json", "tests/json_addition_test.rb", "tests/json_common_interface_test.rb", "tests/json_encoding_test.rb", "tests/json_ext_parser_test.rb", "tests/json_fixtures_test.rb", "tests/json_generator_test.rb", "tests/json_generic_object_test.rb", "tests/json_parser_test.rb", "tests/json_string_matching_test.rb", "tests/test_helper.rb", "tools/fuzz.rb", "tools/server.rb"]
s.homepage = "http://flori.github.com/json"
s.licenses = ["Ruby"]
s.rdoc_options = ["--title", "JSON implemention for ruby", "--main", "README.md"]
diff --git a/lib/json/common.rb b/lib/json/common.rb
index 1215d41..55908f8 100644
--- a/lib/json/common.rb
+++ b/lib/json/common.rb
@@ -24,7 +24,7 @@ module JSON
# Set the JSON parser class _parser_ to be used by JSON.
def parser=(parser) # :nodoc:
@parser = parser
- remove_const :Parser if JSON.const_defined_in?(self, :Parser)
+ remove_const :Parser if const_defined?(:Parser, true)
const_set :Parser, parser
end
@@ -35,8 +35,8 @@ module JSON
def deep_const_get(path) # :nodoc:
path.to_s.split(/::/).inject(Object) do |p, c|
case
- when c.empty? then p
- when JSON.const_defined_in?(p, c) then p.const_get(c)
+ when c.empty? then p
+ when p.const_defined?(c, true) then p.const_get(c)
else
begin
p.const_missing(c)
@@ -141,7 +141,7 @@ module JSON
# structures. Disable depth checking with :max_nesting => false. It
# defaults to 100.
# * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
- # defiance of RFC 4627 to be parsed by the Parser. This option defaults
+ # defiance of RFC 7159 to be parsed by the Parser. This option defaults
# to false.
# * *symbolize_names*: If set to true, returns symbols for the names
# (keys) in a JSON object. Otherwise strings are returned. Strings are
@@ -165,7 +165,7 @@ module JSON
# parse! methods defaults to not doing max depth checking: This can be
# dangerous if someone wants to fill up your stack.
# * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
- # defiance of RFC 4627 to be parsed by the Parser. This option defaults
+ # defiance of RFC 7159 to be parsed by the Parser. This option defaults
# to true.
# * *create_additions*: If set to false, the Parser doesn't create
# additions even if a matching class and create_id was found. This option
@@ -174,7 +174,7 @@ module JSON
opts = {
:max_nesting => false,
:allow_nan => true
- }.update(opts)
+ }.merge(opts)
Parser.new(source, opts).parse
end
@@ -295,13 +295,13 @@ module JSON
# The global default options for the JSON.load method:
# :max_nesting: false
# :allow_nan: true
- # :quirks_mode: true
+ # :allow_blank: true
attr_accessor :load_default_options
end
self.load_default_options = {
:max_nesting => false,
:allow_nan => true,
- :quirks_mode => true,
+ :allow_blank => true,
:create_additions => true,
}
@@ -328,7 +328,7 @@ module JSON
elsif source.respond_to?(:read)
source = source.read
end
- if opts[:quirks_mode] && (source.nil? || source.empty?)
+ if opts[:allow_blank] && (source.nil? || source.empty?)
source = 'null'
end
result = parse(source, opts)
@@ -357,13 +357,12 @@ module JSON
# The global default options for the JSON.dump method:
# :max_nesting: false
# :allow_nan: true
- # :quirks_mode: true
+ # :allow_blank: true
attr_accessor :dump_default_options
end
self.dump_default_options = {
:max_nesting => false,
:allow_nan => true,
- :quirks_mode => true,
}
# Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
@@ -402,37 +401,9 @@ module JSON
raise ArgumentError, "exceed depth limit"
end
- # Swap consecutive bytes of _string_ in place.
- def self.swap!(string) # :nodoc:
- 0.upto(string.size / 2) do |i|
- break unless string[2 * i + 1]
- string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
- end
- string
- end
-
- # Shortcut for iconv.
- if ::String.method_defined?(:encode)
- # Encodes string using Ruby's _String.encode_
- def self.iconv(to, from, string)
- string.encode(to, from)
- end
- else
- require 'iconv'
- # Encodes string using _iconv_ library
- def self.iconv(to, from, string)
- Iconv.conv(to, from, string)
- end
- end
-
- if ::Object.method(:const_defined?).arity == 1
- def self.const_defined_in?(modul, constant)
- modul.const_defined?(constant)
- end
- else
- def self.const_defined_in?(modul, constant)
- modul.const_defined?(constant, false)
- end
+ # Encodes string using Ruby's _String.encode_
+ def self.iconv(to, from, string)
+ string.encode(to, from)
end
end
diff --git a/lib/json/ext.rb b/lib/json/ext.rb
index c5f8131..7264a85 100644
--- a/lib/json/ext.rb
+++ b/lib/json/ext.rb
@@ -1,9 +1,3 @@
-if ENV['SIMPLECOV_COVERAGE'].to_i == 1
- require 'simplecov'
- SimpleCov.start do
- add_filter "/tests/"
- end
-end
require 'json/common'
module JSON
diff --git a/lib/json/pure.rb b/lib/json/pure.rb
index b68668b..53178b3 100644
--- a/lib/json/pure.rb
+++ b/lib/json/pure.rb
@@ -1,17 +1,11 @@
-if ENV['SIMPLECOV_COVERAGE'].to_i == 1
- require 'simplecov'
- SimpleCov.start do
- add_filter "/tests/"
- end
-end
require 'json/common'
-require 'json/pure/parser'
-require 'json/pure/generator'
module JSON
# This module holds all the modules/classes that implement JSON's
# functionality in pure ruby.
module Pure
+ require 'json/pure/parser'
+ require 'json/pure/generator'
$DEBUG and warn "Using Pure library for JSON."
JSON.parser = Parser
JSON.generator = Generator
diff --git a/lib/json/pure/generator.rb b/lib/json/pure/generator.rb
index cc8b0fd..98bc369 100644
--- a/lib/json/pure/generator.rb
+++ b/lib/json/pure/generator.rb
@@ -38,85 +38,45 @@ module JSON
# Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
# UTF16 big endian characters as \u????, and return it.
- if defined?(::Encoding)
- def utf8_to_json(string) # :nodoc:
- string = string.dup
- string.force_encoding(::Encoding::ASCII_8BIT)
- string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
- string.force_encoding(::Encoding::UTF_8)
- string
- end
-
- def utf8_to_json_ascii(string) # :nodoc:
- string = string.dup
- string.force_encoding(::Encoding::ASCII_8BIT)
- string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] }
- string.gsub!(/(
- (?:
- [\xc2-\xdf][\x80-\xbf] |
- [\xe0-\xef][\x80-\xbf]{2} |
- [\xf0-\xf4][\x80-\xbf]{3}
- )+ |
- [\x80-\xc1\xf5-\xff] # invalid
- )/nx) { |c|
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
- s.force_encoding(::Encoding::ASCII_8BIT)
- s.gsub!(/.{4}/n, '\\\\u\&')
- s.force_encoding(::Encoding::UTF_8)
- }
- string.force_encoding(::Encoding::UTF_8)
- string
- rescue => e
- raise GeneratorError.wrap(e)
- end
-
- def valid_utf8?(string)
- encoding = string.encoding
- (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
- string.valid_encoding?
- end
- module_function :valid_utf8?
- else
- def utf8_to_json(string) # :nodoc:
- string.gsub(/["\\\x0-\x1f]/n) { MAP[$&] }
- end
+ def utf8_to_json(string) # :nodoc:
+ string = string.dup
+ string.force_encoding(::Encoding::ASCII_8BIT)
+ string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
+ string.force_encoding(::Encoding::UTF_8)
+ string
+ end
- def utf8_to_json_ascii(string) # :nodoc:
- string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
- string.gsub!(/(
- (?:
- [\xc2-\xdf][\x80-\xbf] |
- [\xe0-\xef][\x80-\xbf]{2} |
- [\xf0-\xf4][\x80-\xbf]{3}
- )+ |
- [\x80-\xc1\xf5-\xff] # invalid
- )/nx) { |c|
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
- s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
- s.gsub!(/.{4}/n, '\\\\u\&')
- }
- string
- rescue => e
- raise GeneratorError.wrap(e)
- end
+ def utf8_to_json_ascii(string) # :nodoc:
+ string = string.dup
+ string.force_encoding(::Encoding::ASCII_8BIT)
+ string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] }
+ string.gsub!(/(
+ (?:
+ [\xc2-\xdf][\x80-\xbf] |
+ [\xe0-\xef][\x80-\xbf]{2} |
+ [\xf0-\xf4][\x80-\xbf]{3}
+ )+ |
+ [\x80-\xc1\xf5-\xff] # invalid
+ )/nx) { |c|
+ c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
+ s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
+ s.force_encoding(::Encoding::ASCII_8BIT)
+ s.gsub!(/.{4}/n, '\\\\u\&')
+ s.force_encoding(::Encoding::UTF_8)
+ }
+ string.force_encoding(::Encoding::UTF_8)
+ string
+ rescue => e
+ raise GeneratorError.wrap(e)
+ end
- def valid_utf8?(string)
- string =~
- /\A( [\x09\x0a\x0d\x20-\x7e] # ASCII
- | [\xc2-\xdf][\x80-\xbf] # non-overlong 2-byte
- | \xe0[\xa0-\xbf][\x80-\xbf] # excluding overlongs
- | [\xe1-\xec\xee\xef][\x80-\xbf]{2} # straight 3-byte
- | \xed[\x80-\x9f][\x80-\xbf] # excluding surrogates
- | \xf0[\x90-\xbf][\x80-\xbf]{2} # planes 1-3
- | [\xf1-\xf3][\x80-\xbf]{3} # planes 4-15
- | \xf4[\x80-\x8f][\x80-\xbf]{2} # plane 16
- )*\z/nx
- end
+ def valid_utf8?(string)
+ encoding = string.encoding
+ (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
+ string.valid_encoding?
end
module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
-
module Pure
module Generator
# This class is used to create State instances, that are use to hold data
@@ -154,8 +114,6 @@ module JSON
# * *allow_nan*: true if NaN, Infinity, and -Infinity should be
# generated, otherwise an exception is thrown, if these values are
# encountered. This options defaults to false.
- # * *quirks_mode*: Enables quirks_mode for parser, that is for example
- # generating single JSON values instead of documents is possible.
def initialize(opts = {})
@indent = ''
@space = ''
@@ -164,7 +122,6 @@ module JSON
@array_nl = ''
@allow_nan = false
@ascii_only = false
- @quirks_mode = false
@buffer_initial_length = 1024
configure opts
end
@@ -190,10 +147,6 @@ module JSON
# the generated JSON, max_nesting = 0 if no maximum is checked.
attr_accessor :max_nesting
- # If this attribute is set to true, quirks mode is enabled, otherwise
- # it's disabled.
- attr_accessor :quirks_mode
-
# :stopdoc:
attr_reader :buffer_initial_length
@@ -233,11 +186,6 @@ module JSON
@ascii_only
end
- # Returns true, if quirks mode is enabled. Otherwise returns false.
- def quirks_mode?
- @quirks_mode
- end
-
# Configure this State instance with the Hash _opts_, and return
# itself.
def configure(opts)
@@ -259,7 +207,6 @@ module JSON
@allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
@ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
@depth = opts[:depth] || 0
- @quirks_mode = opts[:quirks_mode] if opts.key?(:quirks_mode)
@buffer_initial_length ||= opts[:buffer_initial_length]
if !opts.key?(:max_nesting) # defaults to 100
@@ -439,34 +386,20 @@ module JSON
end
module String
- if defined?(::Encoding)
- # This string should be encoded with UTF-8 A call to this method
- # returns a JSON string encoded with UTF16 big endian characters as
- # \u????.
- def to_json(state = nil, *args)
- state = State.from_state(state)
- if encoding == ::Encoding::UTF_8
- string = self
- else
- string = encode(::Encoding::UTF_8)
- end
- if state.ascii_only?
- '"' << JSON.utf8_to_json_ascii(string) << '"'
- else
- '"' << JSON.utf8_to_json(string) << '"'
- end
+ # This string should be encoded with UTF-8 A call to this method
+ # returns a JSON string encoded with UTF16 big endian characters as
+ # \u????.
+ def to_json(state = nil, *args)
+ state = State.from_state(state)
+ if encoding == ::Encoding::UTF_8
+ string = self
+ else
+ string = encode(::Encoding::UTF_8)
end
- else
- # This string should be encoded with UTF-8 A call to this method
- # returns a JSON string encoded with UTF16 big endian characters as
- # \u????.
- def to_json(state = nil, *args)
- state = State.from_state(state)
- if state.ascii_only?
- '"' << JSON.utf8_to_json_ascii(self) << '"'
- else
- '"' << JSON.utf8_to_json(self) << '"'
- end
+ if state.ascii_only?
+ '"' << JSON.utf8_to_json_ascii(string) << '"'
+ else
+ '"' << JSON.utf8_to_json(string) << '"'
end
end
diff --git a/lib/json/pure/parser.rb b/lib/json/pure/parser.rb
index c5d1501..f02f408 100644
--- a/lib/json/pure/parser.rb
+++ b/lib/json/pure/parser.rb
@@ -58,7 +58,7 @@ module JSON
# structures. Disable depth checking with :max_nesting => false|nil|0,
# it defaults to 100.
# * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
- # defiance of RFC 4627 to be parsed by the Parser. This option defaults
+ # defiance of RFC 7159 to be parsed by the Parser. This option defaults
# to false.
# * *symbolize_names*: If set to true, returns symbols for the names
# (keys) in a JSON object. Otherwise strings are returned, which is
@@ -69,13 +69,9 @@ module JSON
# option defaults to false.
# * *object_class*: Defaults to Hash
# * *array_class*: Defaults to Array
- # * *quirks_mode*: Enables quirks_mode for parser, that is for example
- # parsing single JSON values instead of documents is possible.
def initialize(source, opts = {})
opts ||= {}
- unless @quirks_mode = opts[:quirks_mode]
- source = convert_encoding source
- end
+ source = convert_encoding source
super source
if !opts.key?(:max_nesting) # defaults to 100
@max_nesting = 100
@@ -102,10 +98,6 @@ module JSON
alias source string
- def quirks_mode?
- !!@quirks_mode
- end
-
def reset
super
@current_nesting = 0
@@ -138,7 +130,7 @@ module JSON
raise TypeError,
"#{source.inspect} is not like a string"
end
- if defined?(::Encoding)
+ if source.encoding != ::Encoding::ASCII_8BIT
source = source.encode(::Encoding::UTF_8)
source.force_encoding(::Encoding::ASCII_8BIT)
end
diff --git a/references/rfc7159.txt b/references/rfc7159.txt
new file mode 100644
index 0000000..64fcada
--- /dev/null
+++ b/references/rfc7159.txt
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+Internet Engineering Task Force (IETF) T. Bray, Ed.
+Request for Comments: 7159 Google, Inc.
+Obsoletes: 4627, 7158 March 2014
+Category: Standards Track
+ISSN: 2070-1721
+
+
+ The JavaScript Object Notation (JSON) Data Interchange Format
+
+Abstract
+
+ JavaScript Object Notation (JSON) is a lightweight, text-based,
+ language-independent data interchange format. It was derived from
+ the ECMAScript Programming Language Standard. JSON defines a small
+ set of formatting rules for the portable representation of structured
+ data.
+
+ This document removes inconsistencies with other specifications of
+ JSON, repairs specification errors, and offers experience-based
+ interoperability guidance.
+
+Status of This Memo
+
+ This is an Internet Standards Track document.
+
+ This document is a product of the Internet Engineering Task Force
+ (IETF). It represents the consensus of the IETF community. It has
+ received public review and has been approved for publication by the
+ Internet Engineering Steering Group (IESG). Further information on
+ Internet Standards is available in Section 2 of RFC 5741.
+
+ Information about the current status of this document, any errata,
+ and how to provide feedback on it may be obtained at
+ http://www.rfc-editor.org/info/rfc7159.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bray Standards Track [Page 1]
+
+RFC 7159 JSON March 2014
+
+
+Copyright Notice
+
+ Copyright (c) 2014 IETF Trust and the persons identified as the
+ document authors. All rights reserved.
+
+ This document is subject to BCP 78 and the IETF Trust's Legal
+ Provisions Relating to IETF Documents
+ (http://trustee.ietf.org/license-info) in effect on the date of
+ publication of this document. Please review these documents
+ carefully, as they describe your rights and restrictions with respect
+ to this document. Code Components extracted from this document must
+ include Simplified BSD License text as described in Section 4.e of
+ the Trust Legal Provisions and are provided without warranty as
+ described in the Simplified BSD License.
+
+ This document may contain material from IETF Documents or IETF
+ Contributions published or made publicly available before November
+ 10, 2008. The person(s) controlling the copyright in some of this
+ material may not have granted the IETF Trust the right to allow
+ modifications of such material outside the IETF Standards Process.
+ Without obtaining an adequate license from the person(s) controlling
+ the copyright in such materials, this document may not be modified
+ outside the IETF Standards Process, and derivative works of it may
+ not be created outside the IETF Standards Process, except to format
+ it for publication as an RFC or to translate it into languages other
+ than English.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bray Standards Track [Page 2]
+
+RFC 7159 JSON March 2014
+
+
+Table of Contents
+
+ 1. Introduction ....................................................3
+ 1.1. Conventions Used in This Document ..........................4
+ 1.2. Specifications of JSON .....................................4
+ 1.3. Introduction to This Revision ..............................4
+ 2. JSON Grammar ....................................................4
+ 3. Values ..........................................................5
+ 4. Objects .........................................................6
+ 5. Arrays ..........................................................6
+ 6. Numbers .........................................................6
+ 7. Strings .........................................................8
+ 8. String and Character Issues .....................................9
+ 8.1. Character Encoding .........................................9
+ 8.2. Unicode Characters .........................................9
+ 8.3. String Comparison ..........................................9
+ 9. Parsers ........................................................10
+ 10. Generators ....................................................10
+ 11. IANA Considerations ...........................................10
+ 12. Security Considerations .......................................11
+ 13. Examples ......................................................12
+ 14. Contributors ..................................................13
+ 15. References ....................................................13
+ 15.1. Normative References .....................................13
+ 15.2. Informative References ...................................13
+ Appendix A. Changes from RFC 4627 .................................15
+
+1. Introduction
+
+ JavaScript Object Notation (JSON) is a text format for the
+ serialization of structured data. It is derived from the object
+ literals of JavaScript, as defined in the ECMAScript Programming
+ Language Standard, Third Edition [ECMA-262].
+
+ JSON can represent four primitive types (strings, numbers, booleans,
+ and null) and two structured types (objects and arrays).
+
+ A string is a sequence of zero or more Unicode characters [UNICODE].
+ Note that this citation references the latest version of Unicode
+ rather than a specific release. It is not expected that future
+ changes in the UNICODE specification will impact the syntax of JSON.
+
+ An object is an unordered collection of zero or more name/value
+ pairs, where a name is a string and a value is a string, number,
+ boolean, null, object, or array.
+
+ An array is an ordered sequence of zero or more values.
+
+
+
+
+Bray Standards Track [Page 3]
+
+RFC 7159 JSON March 2014
+
+
+ The terms "object" and "array" come from the conventions of
+ JavaScript.
+
+ JSON's design goals were for it to be minimal, portable, textual, and
+ a subset of JavaScript.
+
+1.1. Conventions Used in This Document
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+ The grammatical rules in this document are to be interpreted as
+ described in [RFC5234].
+
+1.2. Specifications of JSON
+
+ This document updates [RFC4627], which describes JSON and registers
+ the media type "application/json".
+
+ A description of JSON in ECMAScript terms appears in Version 5.1 of
+ the ECMAScript specification [ECMA-262], Section 15.12. JSON is also
+ described in [ECMA-404].
+
+ All of the specifications of JSON syntax agree on the syntactic
+ elements of the language.
+
+1.3. Introduction to This Revision
+
+ In the years since the publication of RFC 4627, JSON has found very
+ wide use. This experience has revealed certain patterns, which,
+ while allowed by its specifications, have caused interoperability
+ problems.
+
+ Also, a small number of errata have been reported (see RFC Errata IDs
+ 607 [Err607] and 3607 [Err3607]).
+
+ This document's goal is to apply the errata, remove inconsistencies
+ with other specifications of JSON, and highlight practices that can
+ lead to interoperability problems.
+
+2. JSON Grammar
+
+ A JSON text is a sequence of tokens. The set of tokens includes six
+ structural characters, strings, numbers, and three literal names.
+
+ A JSON text is a serialized value. Note that certain previous
+ specifications of JSON constrained a JSON text to be an object or an
+
+
+
+Bray Standards Track [Page 4]
+
+RFC 7159 JSON March 2014
+
+
+ array. Implementations that generate only objects or arrays where a
+ JSON text is called for will be interoperable in the sense that all
+ implementations will accept these as conforming JSON texts.
+
+ JSON-text = ws value ws
+
+ These are the six structural characters:
+
+ begin-array = ws %x5B ws ; [ left square bracket
+
+ begin-object = ws %x7B ws ; { left curly bracket
+
+ end-array = ws %x5D ws ; ] right square bracket
+
+ end-object = ws %x7D ws ; } right curly bracket
+
+ name-separator = ws %x3A ws ; : colon
+
+ value-separator = ws %x2C ws ; , comma
+
+ Insignificant whitespace is allowed before or after any of the six
+ structural characters.
+
+ ws = *(
+ %x20 / ; Space
+ %x09 / ; Horizontal tab
+ %x0A / ; Line feed or New line
+ %x0D ) ; Carriage return
+
+3. Values
+
+ A JSON value MUST be an object, array, number, or string, or one of
+ the following three literal names:
+
+ false null true
+
+ The literal names MUST be lowercase. No other literal names are
+ allowed.
+
+ value = false / null / true / object / array / number / string
+
+ false = %x66.61.6c.73.65 ; false
+
+ null = %x6e.75.6c.6c ; null
+
+ true = %x74.72.75.65 ; true
+
+
+
+
+
+Bray Standards Track [Page 5]
+
+RFC 7159 JSON March 2014
+
+
+4. Objects
+
+ An object structure is represented as a pair of curly brackets
+ surrounding zero or more name/value pairs (or members). A name is a
+ string. A single colon comes after each name, separating the name
+ from the value. A single comma separates a value from a following
+ name. The names within an object SHOULD be unique.
+
+ object = begin-object [ member *( value-separator member ) ]
+ end-object
+
+ member = string name-separator value
+
+ An object whose names are all unique is interoperable in the sense
+ that all software implementations receiving that object will agree on
+ the name-value mappings. When the names within an object are not
+ unique, the behavior of software that receives such an object is
+ unpredictable. Many implementations report the last name/value pair
+ only. Other implementations report an error or fail to parse the
+ object, and some implementations report all of the name/value pairs,
+ including duplicates.
+
+ JSON parsing libraries have been observed to differ as to whether or
+ not they make the ordering of object members visible to calling
+ software. Implementations whose behavior does not depend on member
+ ordering will be interoperable in the sense that they will not be
+ affected by these differences.
+
+5. Arrays
+
+ An array structure is represented as square brackets surrounding zero
+ or more values (or elements). Elements are separated by commas.
+
+ array = begin-array [ value *( value-separator value ) ] end-array
+
+ There is no requirement that the values in an array be of the same
+ type.
+
+6. Numbers
+
+ The representation of numbers is similar to that used in most
+ programming languages. A number is represented in base 10 using
+ decimal digits. It contains an integer component that may be
+ prefixed with an optional minus sign, which may be followed by a
+ fraction part and/or an exponent part. Leading zeros are not
+ allowed.
+
+ A fraction part is a decimal point followed by one or more digits.
+
+
+
+Bray Standards Track [Page 6]
+
+RFC 7159 JSON March 2014
+
+
+ An exponent part begins with the letter E in upper or lower case,
+ which may be followed by a plus or minus sign. The E and optional
+ sign are followed by one or more digits.
+
+ Numeric values that cannot be represented in the grammar below (such
+ as Infinity and NaN) are not permitted.
+
+ number = [ minus ] int [ frac ] [ exp ]
+
+ decimal-point = %x2E ; .
+
+ digit1-9 = %x31-39 ; 1-9
+
+ e = %x65 / %x45 ; e E
+
+ exp = e [ minus / plus ] 1*DIGIT
+
+ frac = decimal-point 1*DIGIT
+
+ int = zero / ( digit1-9 *DIGIT )
+
+ minus = %x2D ; -
+
+ plus = %x2B ; +
+
+ zero = %x30 ; 0
+
+ This specification allows implementations to set limits on the range
+ and precision of numbers accepted. Since software that implements
+ IEEE 754-2008 binary64 (double precision) numbers [IEEE754] is
+ generally available and widely used, good interoperability can be
+ achieved by implementations that expect no more precision or range
+ than these provide, in the sense that implementations will
+ approximate JSON numbers within the expected precision. A JSON
+ number such as 1E400 or 3.141592653589793238462643383279 may indicate
+ potential interoperability problems, since it suggests that the
+ software that created it expects receiving software to have greater
+ capabilities for numeric magnitude and precision than is widely
+ available.
+
+ Note that when such software is used, numbers that are integers and
+ are in the range [-(2**53)+1, (2**53)-1] are interoperable in the
+ sense that implementations will agree exactly on their numeric
+ values.
+
+
+
+
+
+
+
+Bray Standards Track [Page 7]
+
+RFC 7159 JSON March 2014
+
+
+7. Strings
+
+ The representation of strings is similar to conventions used in the C
+ family of programming languages. A string begins and ends with
+ quotation marks. All Unicode characters may be placed within the
+ quotation marks, except for the characters that must be escaped:
+ quotation mark, reverse solidus, and the control characters (U+0000
+ through U+001F).
+
+ Any character may be escaped. If the character is in the Basic
+ Multilingual Plane (U+0000 through U+FFFF), then it may be
+ represented as a six-character sequence: a reverse solidus, followed
+ by the lowercase letter u, followed by four hexadecimal digits that
+ encode the character's code point. The hexadecimal letters A though
+ F can be upper or lower case. So, for example, a string containing
+ only a single reverse solidus character may be represented as
+ "\u005C".
+
+ Alternatively, there are two-character sequence escape
+ representations of some popular characters. So, for example, a
+ string containing only a single reverse solidus character may be
+ represented more compactly as "\\".
+
+ To escape an extended character that is not in the Basic Multilingual
+ Plane, the character is represented as a 12-character sequence,
+ encoding the UTF-16 surrogate pair. So, for example, a string
+ containing only the G clef character (U+1D11E) may be represented as
+ "\uD834\uDD1E".
+
+ string = quotation-mark *char quotation-mark
+
+ char = unescaped /
+ escape (
+ %x22 / ; " quotation mark U+0022
+ %x5C / ; \ reverse solidus U+005C
+ %x2F / ; / solidus U+002F
+ %x62 / ; b backspace U+0008
+ %x66 / ; f form feed U+000C
+ %x6E / ; n line feed U+000A
+ %x72 / ; r carriage return U+000D
+ %x74 / ; t tab U+0009
+ %x75 4HEXDIG ) ; uXXXX U+XXXX
+
+ escape = %x5C ; \
+
+ quotation-mark = %x22 ; "
+
+ unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
+
+
+
+Bray Standards Track [Page 8]
+
+RFC 7159 JSON March 2014
+
+
+8. String and Character Issues
+
+8.1. Character Encoding
+
+ JSON text SHALL be encoded in UTF-8, UTF-16, or UTF-32. The default
+ encoding is UTF-8, and JSON texts that are encoded in UTF-8 are
+ interoperable in the sense that they will be read successfully by the
+ maximum number of implementations; there are many implementations
+ that cannot successfully read texts in other encodings (such as
+ UTF-16 and UTF-32).
+
+ Implementations MUST NOT add a byte order mark to the beginning of a
+ JSON text. In the interests of interoperability, implementations
+ that parse JSON texts MAY ignore the presence of a byte order mark
+ rather than treating it as an error.
+
+8.2. Unicode Characters
+
+ When all the strings represented in a JSON text are composed entirely
+ of Unicode characters [UNICODE] (however escaped), then that JSON
+ text is interoperable in the sense that all software implementations
+ that parse it will agree on the contents of names and of string
+ values in objects and arrays.
+
+ However, the ABNF in this specification allows member names and
+ string values to contain bit sequences that cannot encode Unicode
+ characters; for example, "\uDEAD" (a single unpaired UTF-16
+ surrogate). Instances of this have been observed, for example, when
+ a library truncates a UTF-16 string without checking whether the
+ truncation split a surrogate pair. The behavior of software that
+ receives JSON texts containing such values is unpredictable; for
+ example, implementations might return different values for the length
+ of a string value or even suffer fatal runtime exceptions.
+
+8.3. String Comparison
+
+ Software implementations are typically required to test names of
+ object members for equality. Implementations that transform the
+ textual representation into sequences of Unicode code units and then
+ perform the comparison numerically, code unit by code unit, are
+ interoperable in the sense that implementations will agree in all
+ cases on equality or inequality of two strings. For example,
+ implementations that compare strings with escaped characters
+ unconverted may incorrectly find that "a\\b" and "a\u005Cb" are not
+ equal.
+
+
+
+
+
+
+Bray Standards Track [Page 9]
+
+RFC 7159 JSON March 2014
+
+
+9. Parsers
+
+ A JSON parser transforms a JSON text into another representation. A
+ JSON parser MUST accept all texts that conform to the JSON grammar.
+ A JSON parser MAY accept non-JSON forms or extensions.
+
+ An implementation may set limits on the size of texts that it
+ accepts. An implementation may set limits on the maximum depth of
+ nesting. An implementation may set limits on the range and precision
+ of numbers. An implementation may set limits on the length and
+ character contents of strings.
+
+10. Generators
+
+ A JSON generator produces JSON text. The resulting text MUST
+ strictly conform to the JSON grammar.
+
+11. IANA Considerations
+
+ The MIME media type for JSON text is application/json.
+
+ Type name: application
+
+ Subtype name: json
+
+ Required parameters: n/a
+
+ Optional parameters: n/a
+
+ Encoding considerations: binary
+
+ Security considerations: See [RFC7159], Section 12.
+
+ Interoperability considerations: Described in [RFC7159]
+
+ Published specification: [RFC7159]
+
+ Applications that use this media type:
+ JSON has been used to exchange data between applications written
+ in all of these programming languages: ActionScript, C, C#,
+ Clojure, ColdFusion, Common Lisp, E, Erlang, Go, Java, JavaScript,
+ Lua, Objective CAML, Perl, PHP, Python, Rebol, Ruby, Scala, and
+ Scheme.
+
+
+
+
+
+
+
+
+Bray Standards Track [Page 10]
+
+RFC 7159 JSON March 2014
+
+
+ Additional information:
+ Magic number(s): n/a
+ File extension(s): .json
+ Macintosh file type code(s): TEXT
+
+ Person & email address to contact for further information:
+ IESG
+ <iesg@ietf.org>
+
+ Intended usage: COMMON
+
+ Restrictions on usage: none
+
+ Author:
+ Douglas Crockford
+ <douglas@crockford.com>
+
+ Change controller:
+ IESG
+ <iesg@ietf.org>
+
+ Note: No "charset" parameter is defined for this registration.
+ Adding one really has no effect on compliant recipients.
+
+12. Security Considerations
+
+ Generally, there are security issues with scripting languages. JSON
+ is a subset of JavaScript but excludes assignment and invocation.
+
+ Since JSON's syntax is borrowed from JavaScript, it is possible to
+ use that language's "eval()" function to parse JSON texts. This
+ generally constitutes an unacceptable security risk, since the text
+ could contain executable code along with data declarations. The same
+ consideration applies to the use of eval()-like functions in any
+ other programming language in which JSON texts conform to that
+ language's syntax.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bray Standards Track [Page 11]
+
+RFC 7159 JSON March 2014
+
+
+13. Examples
+
+ This is a JSON object:
+
+ {
+ "Image": {
+ "Width": 800,
+ "Height": 600,
+ "Title": "View from 15th Floor",
+ "Thumbnail": {
+ "Url": "http://www.example.com/image/481989943",
+ "Height": 125,
+ "Width": 100
+ },
+ "Animated" : false,
+ "IDs": [116, 943, 234, 38793]
+ }
+ }
+
+ Its Image member is an object whose Thumbnail member is an object and
+ whose IDs member is an array of numbers.
+
+ This is a JSON array containing two objects:
+
+ [
+ {
+ "precision": "zip",
+ "Latitude": 37.7668,
+ "Longitude": -122.3959,
+ "Address": "",
+ "City": "SAN FRANCISCO",
+ "State": "CA",
+ "Zip": "94107",
+ "Country": "US"
+ },
+ {
+ "precision": "zip",
+ "Latitude": 37.371991,
+ "Longitude": -122.026020,
+ "Address": "",
+ "City": "SUNNYVALE",
+ "State": "CA",
+ "Zip": "94085",
+ "Country": "US"
+ }
+ ]
+
+
+
+
+
+Bray Standards Track [Page 12]
+
+RFC 7159 JSON March 2014
+
+
+ Here are three small JSON texts containing only values:
+
+ "Hello world!"
+
+ 42
+
+ true
+
+14. Contributors
+
+ RFC 4627 was written by Douglas Crockford. This document was
+ constructed by making a relatively small number of changes to that
+ document; thus, the vast majority of the text here is his.
+
+15. References
+
+15.1. Normative References
+
+ [IEEE754] IEEE, "IEEE Standard for Floating-Point Arithmetic", IEEE
+ Standard 754, August 2008,
+ <http://grouper.ieee.org/groups/754/>.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", STD 68, RFC 5234, January 2008.
+
+ [UNICODE] The Unicode Consortium, "The Unicode Standard",
+ <http://www.unicode.org/versions/latest/>.
+
+15.2. Informative References
+
+ [ECMA-262] Ecma International, "ECMAScript Language Specification
+ Edition 5.1", Standard ECMA-262, June 2011,
+ <http://www.ecma-international.org/publications/standards/
+ Ecma-262.htm>.
+
+ [ECMA-404] Ecma International, "The JSON Data Interchange Format",
+ Standard ECMA-404, October 2013,
+ <http://www.ecma-international.org/publications/standards/
+ Ecma-404.htm>.
+
+ [Err3607] RFC Errata, Errata ID 3607, RFC 3607,
+ <http://www.rfc-editor.org>.
+
+
+
+
+
+
+Bray Standards Track [Page 13]
+
+RFC 7159 JSON March 2014
+
+
+ [Err607] RFC Errata, Errata ID 607, RFC 607,
+ <http://www.rfc-editor.org>.
+
+ [RFC4627] Crockford, D., "The application/json Media Type for
+ JavaScript Object Notation (JSON)", RFC 4627, July 2006.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bray Standards Track [Page 14]
+
+RFC 7159 JSON March 2014
+
+
+Appendix A. Changes from RFC 4627
+
+ This section lists changes between this document and the text in RFC
+ 4627.
+
+ o Changed the title and abstract of the document.
+
+ o Changed the reference to [UNICODE] to be not version specific.
+
+ o Added a "Specifications of JSON" section.
+
+ o Added an "Introduction to This Revision" section.
+
+ o Changed the definition of "JSON text" so that it can be any JSON
+ value, removing the constraint that it be an object or array.
+
+ o Added language about duplicate object member names, member
+ ordering, and interoperability.
+
+ o Clarified the absence of a requirement that values in an array be
+ of the same JSON type.
+
+ o Applied erratum #607 from RFC 4627 to correctly align the artwork
+ for the definition of "object".
+
+ o Changed "as sequences of digits" to "in the grammar below" in the
+ "Numbers" section, and made base-10-ness explicit.
+
+ o Added language about number interoperability as a function of
+ IEEE754, and added an IEEE754 reference.
+
+ o Added language about interoperability and Unicode characters and
+ about string comparisons. To do this, turned the old "Encoding"
+ section into a "String and Character Issues" section, with three
+ subsections: "Character Encoding", "Unicode Characters", and
+ "String Comparison".
+
+ o Changed guidance in the "Parsers" section to point out that
+ implementations may set limits on the range "and precision" of
+ numbers.
+
+ o Updated and tidied the "IANA Considerations" section.
+
+ o Made a real "Security Considerations" section and lifted the text
+ out of the previous "IANA Considerations" section.
+
+
+
+
+
+
+Bray Standards Track [Page 15]
+
+RFC 7159 JSON March 2014
+
+
+ o Applied erratum #3607 from RFC 4627 by removing the security
+ consideration that begins "A JSON text can be safely passed" and
+ the JavaScript code that went with that consideration.
+
+ o Added a note to the "Security Considerations" section pointing out
+ the risks of using the "eval()" function in JavaScript or any
+ other language in which JSON texts conform to that language's
+ syntax.
+
+ o Added a note to the "IANA Considerations" clarifying the absence
+ of a "charset" parameter for the application/json media type.
+
+ o Changed "100" to 100 and added a boolean field, both in the first
+ example.
+
+ o Added examples of JSON texts with simple values, neither objects
+ nor arrays.
+
+ o Added a "Contributors" section crediting Douglas Crockford.
+
+ o Added a reference to RFC 4627.
+
+ o Moved the ECMAScript reference from Normative to Informative and
+ updated it to reference ECMAScript 5.1, and added a reference to
+ ECMA 404.
+
+Author's Address
+
+ Tim Bray (editor)
+ Google, Inc.
+
+ EMail: tbray@textuality.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bray Standards Track [Page 16]
+
diff --git a/tests/json_common_interface_test.rb b/tests/json_common_interface_test.rb
index 6485328..38136fa 100644
--- a/tests/json_common_interface_test.rb
+++ b/tests/json_common_interface_test.rb
@@ -17,37 +17,57 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
'i' => 0.001
}
@json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
- '"g":"\\"\\u0000\\u001f","h":1.0E3,"i":1.0E-3}'
+ '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
end
def test_index
+ assert_equal @json, JSON[@hash]
+ assert_equal @hash, JSON[@json]
end
def test_parser
+ assert_match /::Parser\z/, JSON.parser.name
end
def test_generator
+ assert_match /::Generator\z/, JSON.generator.name
end
def test_state
+ assert_match /::Generator::State\z/, JSON.state.name
end
def test_create_id
+ assert_equal 'json_class', JSON.create_id
+ JSON.create_id = 'foo_bar'
+ assert_equal 'foo_bar', JSON.create_id
+ ensure
+ JSON.create_id = 'json_class'
+ end
+
+ def test_deep_const_get
+ assert_raises(ArgumentError) { JSON.deep_const_get('Nix::Da') }
+ assert_equal File::SEPARATOR, JSON.deep_const_get('File::SEPARATOR')
end
def test_parse
+ assert_equal [ 1, 2, 3, ], JSON.parse('[ 1, 2, 3 ]')
end
def test_parse_bang
+ assert_equal [ 1, NaN, 3, ], JSON.parse!('[ 1, NaN, 3 ]')
end
def test_generate
+ assert_equal '[1,2,3]', JSON.generate([ 1, 2, 3 ])
end
def test_fast_generate
+ assert_equal '[1,2,3]', JSON.generate([ 1, 2, 3 ])
end
def test_pretty_generate
+ assert_equal "[\n 1,\n 2,\n 3\n]", JSON.pretty_generate([ 1, 2, 3 ])
end
def test_load
@@ -70,6 +90,12 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
assert JSON.load(json, nil, :allow_nan => true)['foo'].nan?
end
+ def test_load_null
+ assert_equal nil, JSON.load(nil, nil, :allow_blank => true)
+ assert_raises(TypeError) { JSON.load(nil, nil, :allow_blank => false) }
+ assert_raises(JSON::ParserError) { JSON.load('', nil, :allow_blank => false) }
+ end
+
def test_dump
too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
assert_equal too_deep, dump(eval(too_deep))
@@ -92,7 +118,8 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
assert_equal max_nesting, JSON.dump_default_options[:max_nesting]
end
-
def test_JSON
+ assert_equal @json, JSON(@hash)
+ assert_equal @hash, JSON(@json)
end
end
diff --git a/tests/json_encoding_test.rb b/tests/json_encoding_test.rb
index 86335a1..d983e12 100644
--- a/tests/json_encoding_test.rb
+++ b/tests/json_encoding_test.rb
@@ -1,12 +1,14 @@
+# encoding: utf-8
require 'test_helper'
class JSONEncodingTest < Test::Unit::TestCase
include JSON
def setup
- @utf_8 = '"© ≠ €!"'
- @parsed = "© ≠ €!"
- @generated = '"\u00a9 \u2260 \u20ac!"'
+ @utf_8 = '"© ≠ €!"'
+ @ascii_8bit = @utf_8.dup.force_encoding('ascii-8bit')
+ @parsed = "© ≠ €!"
+ @generated = '"\u00a9 \u2260 \u20ac!"'
if String.method_defined?(:encode)
@utf_16_data = @parsed.encode('utf-16be', 'utf-8')
@utf_16be = @utf_8.encode('utf-16be', 'utf-8')
@@ -24,6 +26,7 @@ class JSONEncodingTest < Test::Unit::TestCase
end
def test_parse
+ assert_equal @parsed, JSON.parse(@ascii_8bit)
assert_equal @parsed, JSON.parse(@utf_8)
assert_equal @parsed, JSON.parse(@utf_16be)
assert_equal @parsed, JSON.parse(@utf_16le)
@@ -33,15 +36,7 @@ class JSONEncodingTest < Test::Unit::TestCase
def test_generate
assert_equal @generated, JSON.generate(@parsed, :ascii_only => true)
- if defined?(::Encoding)
- assert_equal @generated, JSON.generate(@utf_16_data, :ascii_only => true)
- else
- # XXX checking of correct utf8 data is not as strict (yet?) without
- # :ascii_only
- assert_raises(JSON::GeneratorError) do
- JSON.generate(@utf_16_data, :ascii_only => true)
- end
- end
+ assert_equal @generated, JSON.generate(@utf_16_data, :ascii_only => true)
end
def test_unicode
diff --git a/tests/json_ext_parser_test.rb b/tests/json_ext_parser_test.rb
index da3bdc1..ade9784 100644
--- a/tests/json_ext_parser_test.rb
+++ b/tests/json_ext_parser_test.rb
@@ -1,7 +1,4 @@
require 'test_helper'
-require 'stringio'
-require 'tempfile'
-require 'ostruct'
class JSONExtParserTest < Test::Unit::TestCase
if defined?(JSON::Ext::Parser)
diff --git a/tests/json_generator_test.rb b/tests/json_generator_test.rb
index 2bb7e15..7087471 100644
--- a/tests/json_generator_test.rb
+++ b/tests/json_generator_test.rb
@@ -135,7 +135,6 @@ EOT
:array_nl => "\n",
:ascii_only => false,
:buffer_initial_length => 1024,
- :quirks_mode => false,
:depth => 0,
:indent => " ",
:max_nesting => 100,
@@ -152,7 +151,6 @@ EOT
:array_nl => "",
:ascii_only => false,
:buffer_initial_length => 1024,
- :quirks_mode => false,
:depth => 0,
:indent => "",
:max_nesting => 100,
@@ -169,7 +167,6 @@ EOT
:array_nl => "",
:ascii_only => false,
:buffer_initial_length => 1024,
- :quirks_mode => false,
:depth => 0,
:indent => "",
:max_nesting => 0,
@@ -375,6 +372,5 @@ EOT
assert_nothing_raised(SystemStackError) do
assert_equal '["foo"]', JSON.generate([s.new('foo')])
end
-
end
end
diff --git a/tests/json_parser_test.rb b/tests/json_parser_test.rb
index b21e7ec..a5793f9 100644
--- a/tests/json_parser_test.rb
+++ b/tests/json_parser_test.rb
@@ -1,3 +1,5 @@
+# encoding: utf-8
+
require 'test_helper'
require 'stringio'
require 'tempfile'
@@ -135,7 +137,7 @@ class JSONParserTest < Test::Unit::TestCase
assert parse('NaN', :allow_nan => true).nan?
assert parse('Infinity', :allow_nan => true).infinite?
assert parse('-Infinity', :allow_nan => true).infinite?
- assert_raise(JSON::ParserError) { parse('[ 1, ]', :quirks_mode => true) }
+ assert_raise(JSON::ParserError) { parse('[ 1, ]') }
end
def test_parse_some_strings
diff --git a/tests/test_helper.rb b/tests/test_helper.rb
index 752f5f5..9d3665d 100644
--- a/tests/test_helper.rb
+++ b/tests/test_helper.rb
@@ -17,3 +17,7 @@ begin
require 'byebug'
rescue LoadError
end
+if ENV['START_SIMPLECOV'].to_i == 1
+ require 'simplecov'
+ SimpleCov.start
+end
diff --git a/tools/fuzz.rb b/tools/fuzz.rb
index c0fae12..8261930 100755
--- a/tools/fuzz.rb
+++ b/tools/fuzz.rb
@@ -1,13 +1,5 @@
require 'json'
-require 'iconv'
-ISO_8859_1_TO_UTF8 = Iconv.new('utf-8', 'iso-8859-15')
-class ::String
- def to_utf8
- ISO_8859_1_TO_UTF8.iconv self
- end
-end
-
class Fuzzer
def initialize(n, freqs = {})
sum = freqs.inject(0.0) { |s, x| s + x.last }
@@ -25,7 +17,7 @@ class Fuzzer
def random_string
s = ''
30.times { s << @alpha[rand(@alpha.size)] }
- s.to_utf8
+ s
end
def pick