json 2.6.3 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +39 -0
- data/README.md +4 -4
- data/VERSION +1 -1
- data/ext/json/ext/generator/generator.c +84 -19
- data/ext/json/ext/generator/generator.h +8 -5
- data/ext/json/ext/parser/parser.c +1828 -2964
- data/ext/json/ext/parser/parser.rl +79 -94
- data/json.gemspec +3 -3
- data/lib/json/add/bigdecimal.rb +5 -2
- data/lib/json/add/range.rb +22 -7
- data/lib/json/common.rb +11 -27
- data/lib/json/pure/generator.rb +62 -28
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +9 -0
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 69c4723749fff4656746bdf94f5f0a580e7159f52fac2eb403ed5cd93b3c6a42
|
|
4
|
+
data.tar.gz: 1dbf07b0f5aa76c4daace5af98486c7d1b51b599e193944385873ff385e38383
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5e0b326ca829e7bc720ebc211b68afcaff80606d370faccf76610ce711bd1d9c128e38ec88bdff803ee7b4f2454cfa84db4f40f719024f17c99099fd9a386485
|
|
7
|
+
data.tar.gz: 9daaad6f0e574f80878ad50a9402c646d6b27387ef34711cc75167f3902d7e295ad3633976632ecfd90db898022973fcf3aa81f8bf48c969f2b83298f242003b
|
data/CHANGES.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
### 2023-12-01 (2.7.0)
|
|
4
|
+
|
|
5
|
+
* Add a strict option to Generator #519
|
|
6
|
+
* `escape_slash` option was renamed as `script_safe` and now also escape U+2028 and U+2029. `escape_slash` is now an alias of `script_safe` #525
|
|
7
|
+
* Remove unnecessary initialization of create_id in JSON.parse() #454
|
|
8
|
+
* Improvements to Hash#to_json in pure implementation generator #203
|
|
9
|
+
* Use ruby_xfree to free buffers #518
|
|
10
|
+
* Fix "unexpected token" offset for Infinity #507
|
|
11
|
+
* Avoid using deprecated BigDecimal.new on JRuby #546
|
|
12
|
+
* Removed code for Ruby 1.8 #540
|
|
13
|
+
* Rename JSON::ParseError to JSON:ParserError #530
|
|
14
|
+
* Call super in included hook #486
|
|
15
|
+
* JRuby requires a minimum of Java 8 #516
|
|
16
|
+
* Always indent even if empty #517
|
|
17
|
+
|
|
18
|
+
### 2022-11-30 (2.6.3)
|
|
19
|
+
|
|
20
|
+
* bugfix json/pure mixing escaped with literal unicode raises Encoding::CompatibilityError #483
|
|
21
|
+
* Stop including the parser source __LINE__ in exceptions #470
|
|
22
|
+
|
|
23
|
+
### 2022-11-17 (2.6.2)
|
|
24
|
+
|
|
25
|
+
* Remove unknown keyword arg from DateTime.parse #488
|
|
26
|
+
* Ignore java artifacts by @hsbt #489
|
|
27
|
+
* Fix parser bug for empty string allocation #496
|
|
28
|
+
|
|
3
29
|
### 2021-10-24 (2.6.1)
|
|
4
30
|
|
|
5
31
|
* Restore version.rb with 2.6.1
|
|
@@ -105,6 +131,19 @@
|
|
|
105
131
|
I changed these mentions to be consistent with the Ruby license setting in
|
|
106
132
|
the gemspec files which were already correct now.
|
|
107
133
|
|
|
134
|
+
## 2017-01-13 (1.8.6)
|
|
135
|
+
* Be compatible with ancient ruby 1.8 (maybe?)
|
|
136
|
+
|
|
137
|
+
## 2015-09-11 (1.8.5)
|
|
138
|
+
* Be compatible with ruby 2.4.0
|
|
139
|
+
* There were still some mentions of dual GPL licensing in the source, but JSON
|
|
140
|
+
has just the Ruby license that itself includes an explicit dual-licensing
|
|
141
|
+
clause that allows covered software to be distributed under the terms of
|
|
142
|
+
the Simplified BSD License instead for all ruby versions >= 1.9.3. This is
|
|
143
|
+
however a GPL compatible license according to the Free Software Foundation.
|
|
144
|
+
I changed these mentions to be consistent with the Ruby license setting in
|
|
145
|
+
the gemspec files which were already correct now.
|
|
146
|
+
|
|
108
147
|
## 2015-06-01 (1.8.3)
|
|
109
148
|
* Fix potential memory leak, thx to nobu.
|
|
110
149
|
|
data/README.md
CHANGED
|
@@ -12,8 +12,7 @@ will be two variants available:
|
|
|
12
12
|
extensions, which are both part of the ruby standard library.
|
|
13
13
|
* The quite a bit faster native extension variant, which is in parts
|
|
14
14
|
implemented in C or Java and comes with its own unicode conversion
|
|
15
|
-
functions and a parser generated by the
|
|
16
|
-
http://www.complang.org/ragel/ .
|
|
15
|
+
functions and a parser generated by the [Ragel] state machine compiler.
|
|
17
16
|
|
|
18
17
|
Both variants of the JSON generator generate UTF-8 character sequences by
|
|
19
18
|
default. If an :ascii\_only option with a true value is given, they escape all
|
|
@@ -71,8 +70,7 @@ with:
|
|
|
71
70
|
## Compiling the extensions yourself
|
|
72
71
|
|
|
73
72
|
If you want to create the `parser.c` file from its `parser.rl` file or draw nice
|
|
74
|
-
graphviz images of the state machines, you need
|
|
75
|
-
http://www.complang.org/ragel/
|
|
73
|
+
graphviz images of the state machines, you need [Ragel].
|
|
76
74
|
|
|
77
75
|
## Usage
|
|
78
76
|
|
|
@@ -423,3 +421,5 @@ The latest version of this library can be downloaded at
|
|
|
423
421
|
Online Documentation should be located at
|
|
424
422
|
|
|
425
423
|
* https://www.rubydoc.info/gems/json
|
|
424
|
+
|
|
425
|
+
[Ragel]: http://www.colm.net/open-source/ragel/
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.7.0
|
|
@@ -16,7 +16,7 @@ static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
|
|
|
16
16
|
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
|
|
17
17
|
i_pack, i_unpack, i_create_id, i_extend, i_key_p,
|
|
18
18
|
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
|
|
19
|
-
i_buffer_initial_length, i_dup, i_escape_slash;
|
|
19
|
+
i_buffer_initial_length, i_dup, i_script_safe, i_escape_slash, i_strict;
|
|
20
20
|
|
|
21
21
|
/*
|
|
22
22
|
* Copyright 2001-2004 Unicode, Inc.
|
|
@@ -124,7 +124,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
|
|
|
124
124
|
|
|
125
125
|
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
|
|
126
126
|
* and control characters are JSON escaped. */
|
|
127
|
-
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char
|
|
127
|
+
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char script_safe)
|
|
128
128
|
{
|
|
129
129
|
const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
|
|
130
130
|
const UTF8 *sourceEnd = source + RSTRING_LEN(string);
|
|
@@ -175,7 +175,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escap
|
|
|
175
175
|
fbuffer_append(buffer, "\\\"", 2);
|
|
176
176
|
break;
|
|
177
177
|
case '/':
|
|
178
|
-
if(
|
|
178
|
+
if(script_safe) {
|
|
179
179
|
fbuffer_append(buffer, "\\/", 2);
|
|
180
180
|
break;
|
|
181
181
|
}
|
|
@@ -228,7 +228,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escap
|
|
|
228
228
|
* characters required by the JSON standard are JSON escaped. The remaining
|
|
229
229
|
* characters (should be UTF8) are just passed through and appended to the
|
|
230
230
|
* result. */
|
|
231
|
-
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char
|
|
231
|
+
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char script_safe)
|
|
232
232
|
{
|
|
233
233
|
const char *ptr = RSTRING_PTR(string), *p;
|
|
234
234
|
unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
|
|
@@ -280,7 +280,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slas
|
|
|
280
280
|
escape_len = 2;
|
|
281
281
|
break;
|
|
282
282
|
case '/':
|
|
283
|
-
if(
|
|
283
|
+
if(script_safe) {
|
|
284
284
|
escape = "\\/";
|
|
285
285
|
escape_len = 2;
|
|
286
286
|
break;
|
|
@@ -294,6 +294,22 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slas
|
|
|
294
294
|
rb_raise(rb_path2class("JSON::GeneratorError"),
|
|
295
295
|
"partial character in source, but hit end");
|
|
296
296
|
}
|
|
297
|
+
|
|
298
|
+
if (script_safe && c == 0xE2) {
|
|
299
|
+
unsigned char c2 = (unsigned char) *(p+1);
|
|
300
|
+
unsigned char c3 = (unsigned char) *(p+2);
|
|
301
|
+
if (c2 == 0x80 && (c3 == 0xA8 || c3 == 0xA9)) {
|
|
302
|
+
fbuffer_append(buffer, ptr + start, end - start);
|
|
303
|
+
start = end = (end + clen);
|
|
304
|
+
if (c3 == 0xA8) {
|
|
305
|
+
fbuffer_append(buffer, "\\u2028", 6);
|
|
306
|
+
} else {
|
|
307
|
+
fbuffer_append(buffer, "\\u2029", 6);
|
|
308
|
+
}
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
297
313
|
if (!isLegalUTF8((UTF8 *) p, clen)) {
|
|
298
314
|
rb_raise(rb_path2class("JSON::GeneratorError"),
|
|
299
315
|
"source sequence is illegal/malformed utf-8");
|
|
@@ -478,6 +494,7 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
|
|
|
478
494
|
*/
|
|
479
495
|
static VALUE mString_included_s(VALUE self, VALUE modul) {
|
|
480
496
|
VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
|
|
497
|
+
rb_call_super(1, &modul);
|
|
481
498
|
return result;
|
|
482
499
|
}
|
|
483
500
|
|
|
@@ -726,8 +743,14 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
|
726
743
|
state->allow_nan = RTEST(tmp);
|
|
727
744
|
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
|
|
728
745
|
state->ascii_only = RTEST(tmp);
|
|
729
|
-
tmp = rb_hash_aref(opts, ID2SYM(
|
|
730
|
-
state->
|
|
746
|
+
tmp = rb_hash_aref(opts, ID2SYM(i_script_safe));
|
|
747
|
+
state->script_safe = RTEST(tmp);
|
|
748
|
+
if (!state->script_safe) {
|
|
749
|
+
tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
|
|
750
|
+
state->script_safe = RTEST(tmp);
|
|
751
|
+
}
|
|
752
|
+
tmp = rb_hash_aref(opts, ID2SYM(i_strict));
|
|
753
|
+
state->strict = RTEST(tmp);
|
|
731
754
|
return self;
|
|
732
755
|
}
|
|
733
756
|
|
|
@@ -762,7 +785,8 @@ static VALUE cState_to_h(VALUE self)
|
|
|
762
785
|
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
|
|
763
786
|
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
|
|
764
787
|
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
|
|
765
|
-
rb_hash_aset(result, ID2SYM(
|
|
788
|
+
rb_hash_aset(result, ID2SYM(i_script_safe), state->script_safe ? Qtrue : Qfalse);
|
|
789
|
+
rb_hash_aset(result, ID2SYM(i_strict), state->strict ? Qtrue : Qfalse);
|
|
766
790
|
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
|
|
767
791
|
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
|
|
768
792
|
return result;
|
|
@@ -947,9 +971,9 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
|
|
|
947
971
|
}
|
|
948
972
|
#endif
|
|
949
973
|
if (state->ascii_only) {
|
|
950
|
-
convert_UTF8_to_JSON_ASCII(buffer, obj, state->
|
|
974
|
+
convert_UTF8_to_JSON_ASCII(buffer, obj, state->script_safe);
|
|
951
975
|
} else {
|
|
952
|
-
convert_UTF8_to_JSON(buffer, obj, state->
|
|
976
|
+
convert_UTF8_to_JSON(buffer, obj, state->script_safe);
|
|
953
977
|
}
|
|
954
978
|
fbuffer_append_char(buffer, '"');
|
|
955
979
|
}
|
|
@@ -1028,6 +1052,8 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
|
|
|
1028
1052
|
generate_json_bignum(buffer, Vstate, state, obj);
|
|
1029
1053
|
} else if (klass == rb_cFloat) {
|
|
1030
1054
|
generate_json_float(buffer, Vstate, state, obj);
|
|
1055
|
+
} else if (state->strict) {
|
|
1056
|
+
rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(CLASS_OF(obj)));
|
|
1031
1057
|
} else if (rb_respond_to(obj, i_to_json)) {
|
|
1032
1058
|
tmp = rb_funcall(obj, i_to_json, 1, Vstate);
|
|
1033
1059
|
Check_Type(tmp, T_STRING);
|
|
@@ -1390,27 +1416,58 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
|
|
|
1390
1416
|
}
|
|
1391
1417
|
|
|
1392
1418
|
/*
|
|
1393
|
-
* call-seq:
|
|
1419
|
+
* call-seq: script_safe
|
|
1394
1420
|
*
|
|
1395
1421
|
* If this boolean is true, the forward slashes will be escaped in
|
|
1396
1422
|
* the json output.
|
|
1397
1423
|
*/
|
|
1398
|
-
static VALUE
|
|
1424
|
+
static VALUE cState_script_safe(VALUE self)
|
|
1399
1425
|
{
|
|
1400
1426
|
GET_STATE(self);
|
|
1401
|
-
return state->
|
|
1427
|
+
return state->script_safe ? Qtrue : Qfalse;
|
|
1402
1428
|
}
|
|
1403
1429
|
|
|
1404
1430
|
/*
|
|
1405
|
-
* call-seq:
|
|
1431
|
+
* call-seq: script_safe=(enable)
|
|
1406
1432
|
*
|
|
1407
1433
|
* This sets whether or not the forward slashes will be escaped in
|
|
1408
1434
|
* the json output.
|
|
1409
1435
|
*/
|
|
1410
|
-
static VALUE
|
|
1436
|
+
static VALUE cState_script_safe_set(VALUE self, VALUE enable)
|
|
1437
|
+
{
|
|
1438
|
+
GET_STATE(self);
|
|
1439
|
+
state->script_safe = RTEST(enable);
|
|
1440
|
+
return Qnil;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
/*
|
|
1444
|
+
* call-seq: strict
|
|
1445
|
+
*
|
|
1446
|
+
* If this boolean is false, types unsupported by the JSON format will
|
|
1447
|
+
* be serialized as strings.
|
|
1448
|
+
* If this boolean is true, types unsupported by the JSON format will
|
|
1449
|
+
* raise a JSON::GeneratorError.
|
|
1450
|
+
*/
|
|
1451
|
+
static VALUE cState_strict(VALUE self)
|
|
1452
|
+
{
|
|
1453
|
+
GET_STATE(self);
|
|
1454
|
+
return state->strict ? Qtrue : Qfalse;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
/*
|
|
1458
|
+
* call-seq: strict=(enable)
|
|
1459
|
+
*
|
|
1460
|
+
* This sets whether or not to serialize types unsupported by the
|
|
1461
|
+
* JSON format as strings.
|
|
1462
|
+
* If this boolean is false, types unsupported by the JSON format will
|
|
1463
|
+
* be serialized as strings.
|
|
1464
|
+
* If this boolean is true, types unsupported by the JSON format will
|
|
1465
|
+
* raise a JSON::GeneratorError.
|
|
1466
|
+
*/
|
|
1467
|
+
static VALUE cState_strict_set(VALUE self, VALUE enable)
|
|
1411
1468
|
{
|
|
1412
1469
|
GET_STATE(self);
|
|
1413
|
-
state->
|
|
1470
|
+
state->strict = RTEST(enable);
|
|
1414
1471
|
return Qnil;
|
|
1415
1472
|
}
|
|
1416
1473
|
|
|
@@ -1530,9 +1587,15 @@ void Init_generator(void)
|
|
|
1530
1587
|
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
|
|
1531
1588
|
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
|
|
1532
1589
|
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
|
|
1533
|
-
rb_define_method(cState, "
|
|
1534
|
-
rb_define_method(cState, "
|
|
1535
|
-
rb_define_method(cState, "
|
|
1590
|
+
rb_define_method(cState, "script_safe", cState_script_safe, 0);
|
|
1591
|
+
rb_define_method(cState, "script_safe?", cState_script_safe, 0);
|
|
1592
|
+
rb_define_method(cState, "script_safe=", cState_script_safe_set, 1);
|
|
1593
|
+
rb_define_alias(cState, "escape_slash", "script_safe");
|
|
1594
|
+
rb_define_alias(cState, "escape_slash?", "script_safe?");
|
|
1595
|
+
rb_define_alias(cState, "escape_slash=", "script_safe=");
|
|
1596
|
+
rb_define_method(cState, "strict", cState_strict, 0);
|
|
1597
|
+
rb_define_method(cState, "strict?", cState_strict, 0);
|
|
1598
|
+
rb_define_method(cState, "strict=", cState_strict_set, 1);
|
|
1536
1599
|
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
|
|
1537
1600
|
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
|
|
1538
1601
|
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
|
|
@@ -1589,7 +1652,9 @@ void Init_generator(void)
|
|
|
1589
1652
|
i_object_nl = rb_intern("object_nl");
|
|
1590
1653
|
i_array_nl = rb_intern("array_nl");
|
|
1591
1654
|
i_max_nesting = rb_intern("max_nesting");
|
|
1655
|
+
i_script_safe = rb_intern("script_safe");
|
|
1592
1656
|
i_escape_slash = rb_intern("escape_slash");
|
|
1657
|
+
i_strict = rb_intern("strict");
|
|
1593
1658
|
i_allow_nan = rb_intern("allow_nan");
|
|
1594
1659
|
i_ascii_only = rb_intern("ascii_only");
|
|
1595
1660
|
i_depth = rb_intern("depth");
|
|
@@ -49,8 +49,8 @@ static const UTF32 halfMask = 0x3FFUL;
|
|
|
49
49
|
static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length);
|
|
50
50
|
static void unicode_escape(char *buf, UTF16 character);
|
|
51
51
|
static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
|
|
52
|
-
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char
|
|
53
|
-
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char
|
|
52
|
+
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char script_safe);
|
|
53
|
+
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char script_safe);
|
|
54
54
|
static char *fstrndup(const char *ptr, unsigned long len);
|
|
55
55
|
|
|
56
56
|
/* ruby api and some helpers */
|
|
@@ -72,7 +72,8 @@ typedef struct JSON_Generator_StateStruct {
|
|
|
72
72
|
long max_nesting;
|
|
73
73
|
char allow_nan;
|
|
74
74
|
char ascii_only;
|
|
75
|
-
char
|
|
75
|
+
char script_safe;
|
|
76
|
+
char strict;
|
|
76
77
|
long depth;
|
|
77
78
|
long buffer_initial_length;
|
|
78
79
|
} JSON_Generator_State;
|
|
@@ -151,8 +152,10 @@ static VALUE cState_allow_nan_p(VALUE self);
|
|
|
151
152
|
static VALUE cState_ascii_only_p(VALUE self);
|
|
152
153
|
static VALUE cState_depth(VALUE self);
|
|
153
154
|
static VALUE cState_depth_set(VALUE self, VALUE depth);
|
|
154
|
-
static VALUE
|
|
155
|
-
static VALUE
|
|
155
|
+
static VALUE cState_script_safe(VALUE self);
|
|
156
|
+
static VALUE cState_script_safe_set(VALUE self, VALUE depth);
|
|
157
|
+
static VALUE cState_strict(VALUE self);
|
|
158
|
+
static VALUE cState_strict_set(VALUE self, VALUE strict);
|
|
156
159
|
static FBuffer *cState_prepare_buffer(VALUE self);
|
|
157
160
|
#ifndef ZALLOC
|
|
158
161
|
#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
|