json 2.13.2 → 2.17.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 71499860706a6f27871853ec88fe26d5bd6a53f85fba2e9764b9ef0aadc170d9
4
- data.tar.gz: c07cd26190c4f36864490465890c162e1b9ce0ae1f262069e51c94d7cf74b117
3
+ metadata.gz: e803f3f9e7d45dba43221559016a34d8cc9e3ab491e39137d17b614713edb710
4
+ data.tar.gz: 429e3465eada0c9d985c94dbd13bbdd8d57e4b62cf7cf06273f22e136dafb4a8
5
5
  SHA512:
6
- metadata.gz: f1c626d30c67e99c56d9f411b7944b6263261676567c02f6d57ba7566087743b26835d3c6c4c1636a0dc76cc2b8c4e2739a1130f286cd069406c38c66138df97
7
- data.tar.gz: eb4fd62079fc730962359e4128f7abd36ca04c17b580506c3e8e3ebdd0e8e0c54c3cf75d1ae899dc53e13697bfa0c11c6c04277d701cfc83fa9ee611785ac85e
6
+ metadata.gz: adebc7ed56efc6651e23730720ea9f365e434ae234d70620469ae3e8a9240ada46f0ce7d6982f30a1301104fd2b033eaac57950c2657cfc5b2e7b79ffe73a925
7
+ data.tar.gz: 346c97276881d404414359ce0893fd16fe35d6413377b4ad3d71448a9f5fb919a61ef7630fc186a6aeef11fa6422273d0625eccfdd6a57a00c98c0e470c7ec92
data/CHANGES.md CHANGED
@@ -2,6 +2,69 @@
2
2
 
3
3
  ### Unreleased
4
4
 
5
+ ### 2025-12-04 (2.17.1)
6
+
7
+ * Fix a regression in parsing of unicode surogate pairs (`\uXX\uXX`) that could cause an invalid string to be returned.
8
+
9
+ ### 2025-12-03 (2.17.0)
10
+
11
+ * Improve `JSON.load` and `JSON.unsafe_load` to allow passing options as second argument.
12
+ * Fix the parser to no longer ignore invalid escapes in strings.
13
+ Only `\"`, `\\`, `\b`, `\f`, `\n`, `\r`, `\t` and `\u` are valid JSON escapes.
14
+ * Fixed `JSON::Coder` to use the depth it was initialized with.
15
+ * On TruffleRuby, fix the generator to not call `to_json` on the return value of `as_json` for `Float::NAN`.
16
+ * Fixed handling of `state.depth`: when `to_json` changes `state.depth` but does not restore it, it is reset
17
+ automatically to its initial value.
18
+ In particular, when a `NestingError` is raised, `depth` is no longer equal to `max_nesting` after the call to
19
+ generate, and is reset to its initial value. Similarly when `to_json` raises an exception.
20
+
21
+ ### 2025-11-07 (2.16.0)
22
+
23
+ * Deprecate `JSON::State#[]` and `JSON::State#[]=`. Consider using `JSON::Coder` instead.
24
+ * `JSON::Coder` now also yields to the block when encountering strings with invalid encoding.
25
+ * Fix GeneratorError messages to be UTF-8 encoded.
26
+ * Fix memory leak when `Exception` is raised, or `throw` is used during JSON generation.
27
+ * Optimized floating point number parsing by integrating the ryu algorithm (thanks to Josef Šimánek).
28
+ * Optimized numbers parsing using SWAR (thanks to Scott Myron).
29
+ * Optimized parsing of pretty printed documents using SWAR (thanks to Scott Myron).
30
+
31
+ ### 2025-10-25 (2.15.2)
32
+
33
+ * Fix `JSON::Coder` to have one dedicated depth counter per invocation.
34
+ After encountering a circular reference in `JSON::Coder#dump`, any further `#dump` call would raise `JSON::NestingError`.
35
+
36
+ ### 2025-10-07 (2.15.1)
37
+
38
+ * Fix incorrect escaping in the JRuby extension when encoding shared strings.
39
+
40
+ ### 2025-09-22 (2.15.0)
41
+
42
+ * `JSON::Coder` callback now receive a second argument to convey whether the object is a hash key.
43
+ * Tuned the floating point number generator to not use scientific notation as aggressively.
44
+
45
+ ### 2025-09-18 (2.14.1)
46
+
47
+ * Fix `IndexOutOfBoundsException` in the JRuby extension when encoding shared strings.
48
+
49
+ ### 2025-09-18 (2.14.0)
50
+
51
+ * Add new `allow_duplicate_key` generator options. By default a warning is now emitted when a duplicated key is encountered.
52
+ In `json 3.0` an error will be raised.
53
+ ```ruby
54
+ >> Warning[:deprecated] = true
55
+ >> puts JSON.generate({ foo: 1, "foo" => 2 })
56
+ (irb):2: warning: detected duplicate key "foo" in {foo: 1, "foo" => 2}.
57
+ This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
58
+ {"foo":1,"foo":2}
59
+ >> JSON.generate({ foo: 1, "foo" => 2 }, allow_duplicate_key: false)
60
+ detected duplicate key "foo" in {foo: 1, "foo" => 2} (JSON::GeneratorError)
61
+ ```
62
+ * Fix `JSON.generate` `strict: true` mode to also restrict hash keys.
63
+ * Fix `JSON::Coder` to also invoke block for hash keys that aren't strings nor symbols.
64
+ * Fix `JSON.unsafe_load` usage with proc
65
+ * Fix the parser to more consistently reject invalid UTF-16 surogate pairs.
66
+ * Stop defining `String.json_create`, `String#to_json_raw`, `String#to_json_raw_object` when `json/add` isn't loaded.
67
+
5
68
  ### 2025-07-28 (2.13.2)
6
69
 
7
70
  * Improve duplicate key warning and errors to include the key name and point to the right caller.
@@ -44,7 +107,7 @@
44
107
  ### 2025-04-24 (2.11.1)
45
108
 
46
109
  * Add back `JSON.restore`, `JSON.unparse`, `JSON.fast_unparse` and `JSON.pretty_unparse`.
47
- These were deprecated 16 years ago, but never emited warnings, only undocumented, so are
110
+ These were deprecated 16 years ago, but never emitted warnings, only undocumented, so are
48
111
  still used by a few gems.
49
112
 
50
113
  ### 2025-04-24 (2.11.0)
@@ -71,7 +134,7 @@
71
134
  ### 2025-03-12 (2.10.2)
72
135
 
73
136
  * Fix a potential crash in the C extension parser.
74
- * Raise a ParserError on all incomplete unicode escape sequence. This was the behavior until `2.10.0` unadvertently changed it.
137
+ * Raise a ParserError on all incomplete unicode escape sequence. This was the behavior until `2.10.0` inadvertently changed it.
75
138
  * Ensure document snippets that are included in parser errors don't include truncated multibyte characters.
76
139
  * Ensure parser error snippets are valid UTF-8.
77
140
  * Fix `JSON::GeneratorError#detailed_message` on Ruby < 3.2
@@ -102,7 +165,7 @@
102
165
 
103
166
  ### 2024-11-14 (2.8.2)
104
167
 
105
- * `JSON.load_file` explictly read the file as UTF-8.
168
+ * `JSON.load_file` explicitly read the file as UTF-8.
106
169
 
107
170
  ### 2024-11-06 (2.8.1)
108
171
 
@@ -110,7 +173,7 @@
110
173
 
111
174
  ### 2024-11-06 (2.8.0)
112
175
 
113
- * Emit a deprecation warning when `JSON.load` create custom types without the `create_additions` option being explictly enabled.
176
+ * Emit a deprecation warning when `JSON.load` create custom types without the `create_additions` option being explicitly enabled.
114
177
  * Prefer to use `JSON.unsafe_load(string)` or `JSON.load(string, create_additions: true)`.
115
178
  * Emit a deprecation warning when serializing valid UTF-8 strings encoded in `ASCII_8BIT` aka `BINARY`.
116
179
  * Bump required Ruby version to 2.7.
@@ -118,7 +181,7 @@
118
181
  pre-existing support for comments, make it suitable to parse `jsonc` documents.
119
182
  * Many performance improvements to `JSON.parse` and `JSON.load`, up to `1.7x` faster on real world documents.
120
183
  * Some minor performance improvements to `JSON.dump` and `JSON.generate`.
121
- * `JSON.pretty_generate` no longer include newline inside empty object and arrays.
184
+ * `JSON.pretty_generate` no longer includes newlines inside empty object and arrays.
122
185
 
123
186
  ### 2024-11-04 (2.7.6)
124
187
 
@@ -135,13 +198,13 @@
135
198
  * Workaround a bug in 3.4.8 and older https://github.com/rubygems/rubygems/pull/6490.
136
199
  This bug would cause some gems with native extension to fail during compilation.
137
200
  * Workaround different versions of `json` and `json_pure` being loaded (not officially supported).
138
- * Make `json_pure` Ractor compatible.
201
+ * Make `json_pure` Ractor compatible.
139
202
 
140
203
  ### 2024-10-24 (2.7.3)
141
204
 
142
205
  * Numerous performance optimizations in `JSON.generate` and `JSON.dump` (up to 2 times faster).
143
- * Limit the size of ParserError exception messages, only include up to 32 bytes of the unparseable source.
144
- * Fix json-pure's `Object#to_json` to accept non state arguments
206
+ * Limit the size of ParserError exception messages, only include up to 32 bytes of the unparsable source.
207
+ * Fix json-pure's `Object#to_json` to accept non-state arguments.
145
208
  * Fix multiline comment support in `json-pure`.
146
209
  * Fix `JSON.parse` to no longer mutate the argument encoding when passed an ASCII-8BIT string.
147
210
  * Fix `String#to_json` to raise on invalid encoding in `json-pure`.
@@ -286,6 +349,7 @@
286
349
  ## 2015-09-11 (2.0.0)
287
350
  * Now complies to newest JSON RFC 7159.
288
351
  * Implements compatibility to ruby 2.4 integer unification.
352
+ * Removed support for `quirks_mode` option.
289
353
  * Drops support for old rubies whose life has ended, that is rubies < 2.0.
290
354
  Also see https://www.ruby-lang.org/en/news/2014/07/01/eol-for-1-8-7-and-1-9-2/
291
355
  * There were still some mentions of dual GPL licensing in the source, but JSON
data/LEGAL CHANGED
@@ -6,3 +6,15 @@
6
6
  All the files in this distribution are covered under either the Ruby's
7
7
  license (see the file COPYING) or public-domain except some files
8
8
  mentioned below.
9
+
10
+ ext/json/ext/vendor/fpconv.h::
11
+ This file is adapted from https://github.com/night-shift/fpconv
12
+ It is licensed under Boost Software License 1.0.
13
+
14
+ ext/json/ext/vendor/jeaiii-ltoa.h::
15
+ This file is adapted from https://github.com/jeaiii/itoa
16
+ It is licensed under the MIT License
17
+
18
+ ext/json/ext/vendor/ryu.h::
19
+ This file is adapted from the Ryu algorithm by Ulf Adams https://github.com/ulfjack/ryu.
20
+ It is dual-licensed under Apache License 2.0 OR Boost Software License 1.0.
data/README.md CHANGED
@@ -97,7 +97,7 @@ Instead it is recommended to use the newer `JSON::Coder` API:
97
97
 
98
98
  ```ruby
99
99
  module MyApp
100
- API_JSON_CODER = JSON::Coder.new do |object|
100
+ API_JSON_CODER = JSON::Coder.new do |object, is_object_key|
101
101
  case object
102
102
  when Time
103
103
  object.iso8601(3)
@@ -113,6 +113,24 @@ puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"
113
113
  The provided block is called for all objects that don't have a native JSON equivalent, and
114
114
  must return a Ruby object that has a native JSON equivalent.
115
115
 
116
+ It is also called for objects that do have a JSON equivalent, but are used as Hash keys, for instance `{ 1 => 2}`,
117
+ as well as for strings that aren't valid UTF-8:
118
+
119
+ ```ruby
120
+ coder = JSON::Combining.new do |object, is_object_key|
121
+ case object
122
+ when String
123
+ if !string.valid_encoding? || string.encoding != Encoding::UTF_8
124
+ Base64.encode64(string)
125
+ else
126
+ string
127
+ end
128
+ else
129
+ object
130
+ end
131
+ end
132
+ ```
133
+
116
134
  ## Combining JSON fragments
117
135
 
118
136
  To combine JSON fragments into a bigger JSON document, you can use `JSON::Fragment`:
@@ -1,47 +1,9 @@
1
1
  #ifndef _FBUFFER_H_
2
2
  #define _FBUFFER_H_
3
3
 
4
- #include "ruby.h"
5
- #include "ruby/encoding.h"
4
+ #include "../json.h"
6
5
  #include "../vendor/jeaiii-ltoa.h"
7
6
 
8
- /* shims */
9
- /* This is the fallback definition from Ruby 3.4 */
10
-
11
- #ifndef RBIMPL_STDBOOL_H
12
- #if defined(__cplusplus)
13
- # if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L)
14
- # include <cstdbool>
15
- # endif
16
- #elif defined(HAVE_STDBOOL_H)
17
- # include <stdbool.h>
18
- #elif !defined(HAVE__BOOL)
19
- typedef unsigned char _Bool;
20
- # define bool _Bool
21
- # define true ((_Bool)+1)
22
- # define false ((_Bool)+0)
23
- # define __bool_true_false_are_defined
24
- #endif
25
- #endif
26
-
27
- #ifndef RB_UNLIKELY
28
- #define RB_UNLIKELY(expr) expr
29
- #endif
30
-
31
- #ifndef RB_LIKELY
32
- #define RB_LIKELY(expr) expr
33
- #endif
34
-
35
- #ifndef MAYBE_UNUSED
36
- # define MAYBE_UNUSED(x) x
37
- #endif
38
-
39
- #ifdef RUBY_DEBUG
40
- #ifndef JSON_DEBUG
41
- #define JSON_DEBUG RUBY_DEBUG
42
- #endif
43
- #endif
44
-
45
7
  enum fbuffer_type {
46
8
  FBUFFER_HEAP_ALLOCATED = 0,
47
9
  FBUFFER_STACK_ALLOCATED = 1,
@@ -52,7 +14,7 @@ typedef struct FBufferStruct {
52
14
  unsigned long initial_length;
53
15
  unsigned long len;
54
16
  unsigned long capa;
55
- #ifdef JSON_DEBUG
17
+ #if JSON_DEBUG
56
18
  unsigned long requested;
57
19
  #endif
58
20
  char *ptr;
@@ -83,14 +45,14 @@ static void fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *
83
45
  fb->ptr = stack_buffer;
84
46
  fb->capa = stack_buffer_size;
85
47
  }
86
- #ifdef JSON_DEBUG
48
+ #if JSON_DEBUG
87
49
  fb->requested = 0;
88
50
  #endif
89
51
  }
90
52
 
91
53
  static inline void fbuffer_consumed(FBuffer *fb, unsigned long consumed)
92
54
  {
93
- #ifdef JSON_DEBUG
55
+ #if JSON_DEBUG
94
56
  if (consumed > fb->requested) {
95
57
  rb_bug("fbuffer: Out of bound write");
96
58
  }
@@ -160,7 +122,7 @@ static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested)
160
122
 
161
123
  static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
162
124
  {
163
- #ifdef JSON_DEBUG
125
+ #if JSON_DEBUG
164
126
  fb->requested = requested;
165
127
  #endif
166
128
 
@@ -169,19 +131,24 @@ static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
169
131
  }
170
132
  }
171
133
 
172
- static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
134
+ static inline void fbuffer_append_reserved(FBuffer *fb, const char *newstr, unsigned long len)
135
+ {
136
+ MEMCPY(fb->ptr + fb->len, newstr, char, len);
137
+ fbuffer_consumed(fb, len);
138
+ }
139
+
140
+ static inline void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
173
141
  {
174
142
  if (len > 0) {
175
143
  fbuffer_inc_capa(fb, len);
176
- MEMCPY(fb->ptr + fb->len, newstr, char, len);
177
- fbuffer_consumed(fb, len);
144
+ fbuffer_append_reserved(fb, newstr, len);
178
145
  }
179
146
  }
180
147
 
181
148
  /* Appends a character into a buffer. The buffer needs to have sufficient capacity, via fbuffer_inc_capa(...). */
182
149
  static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
183
150
  {
184
- #ifdef JSON_DEBUG
151
+ #if JSON_DEBUG
185
152
  if (fb->requested < 1) {
186
153
  rb_bug("fbuffer: unreserved write");
187
154
  }
@@ -197,11 +164,24 @@ static void fbuffer_append_str(FBuffer *fb, VALUE str)
197
164
  const char *newstr = StringValuePtr(str);
198
165
  unsigned long len = RSTRING_LEN(str);
199
166
 
200
- RB_GC_GUARD(str);
201
-
202
167
  fbuffer_append(fb, newstr, len);
203
168
  }
204
169
 
170
+ static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat)
171
+ {
172
+ const char *newstr = StringValuePtr(str);
173
+ unsigned long len = RSTRING_LEN(str);
174
+
175
+ fbuffer_inc_capa(fb, repeat * len);
176
+ while (repeat) {
177
+ #if JSON_DEBUG
178
+ fb->requested = len;
179
+ #endif
180
+ fbuffer_append_reserved(fb, newstr, len);
181
+ repeat--;
182
+ }
183
+ }
184
+
205
185
  static inline void fbuffer_append_char(FBuffer *fb, char newchr)
206
186
  {
207
187
  fbuffer_inc_capa(fb, 1);
@@ -257,14 +237,11 @@ static VALUE fbuffer_finalize(FBuffer *fb)
257
237
  {
258
238
  if (fb->io) {
259
239
  fbuffer_flush(fb);
260
- fbuffer_free(fb);
261
240
  rb_io_flush(fb->io);
262
241
  return fb->io;
263
242
  } else {
264
- VALUE result = rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
265
- fbuffer_free(fb);
266
- return result;
243
+ return rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
267
244
  }
268
245
  }
269
246
 
270
- #endif
247
+ #endif // _FBUFFER_H_
@@ -6,7 +6,7 @@ if RUBY_ENGINE == 'truffleruby'
6
6
  else
7
7
  append_cflags("-std=c99")
8
8
  $defs << "-DJSON_GENERATOR"
9
- $defs << "-DJSON_DEBUG" if ENV["JSON_DEBUG"]
9
+ $defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
10
10
 
11
11
  if enable_config('generator-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
12
12
  load __dir__ + "/../simd/conf.rb"