| Age | Commit message (Collapse) | Author |
|
https://github.com/ruby/json/commit/f745ec145e
Notes:
Merged: https://github.com/ruby/ruby/pull/12394
|
|
https://github.com/ruby/json/commit/e1f6456499
Notes:
Merged: https://github.com/ruby/ruby/pull/12267
|
|
Fix: https://github.com/ruby/json/issues/710
Makes it easier to debug why a given tree of objects can't
be dumped as JSON.
Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
|
|
Ref: https://github.com/ruby/json/issues/524
Rather than to buffer everything in memory.
Unfortunately Ruby doesn't provide an API to write into
and IO without first allocating a string, which is a bit
wasteful.
https://github.com/ruby/json/commit/f017af6c0a
|
|
https://github.com/ruby/json/commit/2d62ec449f
Notes:
Merged: https://github.com/ruby/ruby/pull/12103
|
|
https://github.com/ruby/json/commit/d5e4a6e3fd
Notes:
Merged: https://github.com/ruby/ruby/pull/12103
|
|
https://github.com/ruby/json/commit/61f022dfbd
Notes:
Merged: https://github.com/ruby/ruby/pull/12103
|
|
Fix: https://github.com/ruby/json/issues/697
This way even if `Encoding.default_external` is set to a weird value
the document will be parsed just fine.
https://github.com/ruby/json/commit/3a8505a8fa
|
|
https://github.com/ruby/json/commit/49650f7312
|
|
https://github.com/ruby/json/commit/8071cc6f09
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12003
|
|
Because of it's Ruby 1.8 heritage, the C extension doesn't care
much about strings encoding. We should get stricter over time.
https://github.com/ruby/json/commit/42402fc13f
|
|
[Feature #19528]
Ref: https://bugs.ruby-lang.org/issues/19528
`load` is understood as the default method for serializer kind of libraries, and
the default options of `JSON.load` has caused many security vulnerabilities over the
years.
The plan is to do like YAML/Psych, deprecate these default options and direct
users toward using `JSON.unsafe_load` so at least it's obvious it should be
used against untrusted data.
|
|
Fix: https://github.com/ruby/json/issues/655
For very small documents, the biggest performance gap with alternatives is
that the API impose that we allocate the `State` object. In a real world app
this doesn't make much of a difference, but when running in a micro-benchmark
this doubles the allocations, causing twice the amount of GC runs, making us
look bad.
However, unless we have to call a `to_json` method, the `State` object isn't
visible, so with some refactoring, we can elude that allocation entirely.
Instead we allocate the State internal struct on the stack, and if we need
to call a `to_json` method, we allocate the `State` and spill the struct on
the heap.
As a result, `JSON.generate` is now as fast as re-using a `State` instance,
as long as only primitives are generated.
Before:
```
== Encoding small mixed (34 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 598.654k i/100ms
json 400.542k i/100ms
oj 533.353k i/100ms
Calculating -------------------------------------
json (reuse) 6.371M (± 8.6%) i/s (156.96 ns/i) - 31.729M in 5.059195s
json 4.120M (± 6.6%) i/s (242.72 ns/i) - 20.828M in 5.090549s
oj 5.622M (± 6.4%) i/s (177.86 ns/i) - 28.268M in 5.061473s
Comparison:
json (reuse): 6371126.6 i/s
oj: 5622452.0 i/s - same-ish: difference falls within error
json: 4119991.1 i/s - 1.55x slower
== Encoding small nested array (121 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 248.125k i/100ms
json 215.255k i/100ms
oj 217.531k i/100ms
Calculating -------------------------------------
json (reuse) 2.628M (± 6.1%) i/s (380.55 ns/i) - 13.151M in 5.030281s
json 2.185M (± 6.7%) i/s (457.74 ns/i) - 10.978M in 5.057655s
oj 2.217M (± 6.7%) i/s (451.10 ns/i) - 11.094M in 5.044844s
Comparison:
json (reuse): 2627799.4 i/s
oj: 2216824.8 i/s - 1.19x slower
json: 2184669.5 i/s - 1.20x slower
== Encoding small hash (65 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 641.334k i/100ms
json 322.745k i/100ms
oj 642.450k i/100ms
Calculating -------------------------------------
json (reuse) 7.133M (± 6.5%) i/s (140.19 ns/i) - 35.915M in 5.068201s
json 4.615M (± 7.0%) i/s (216.70 ns/i) - 22.915M in 5.003718s
oj 6.912M (± 6.4%) i/s (144.68 ns/i) - 34.692M in 5.047690s
Comparison:
json (reuse): 7133123.3 i/s
oj: 6911977.1 i/s - same-ish: difference falls within error
json: 4614696.6 i/s - 1.55x slower
```
After:
```
== Encoding small mixed (34 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 572.751k i/100ms
json 457.741k i/100ms
oj 512.247k i/100ms
Calculating -------------------------------------
json (reuse) 6.324M (± 6.9%) i/s (158.12 ns/i) - 31.501M in 5.023093s
json 6.263M (± 6.9%) i/s (159.66 ns/i) - 31.126M in 5.017086s
oj 5.569M (± 6.6%) i/s (179.56 ns/i) - 27.661M in 5.003739s
Comparison:
json (reuse): 6324183.5 i/s
json: 6263204.9 i/s - same-ish: difference falls within error
oj: 5569049.2 i/s - same-ish: difference falls within error
== Encoding small nested array (121 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 258.505k i/100ms
json 242.335k i/100ms
oj 220.678k i/100ms
Calculating -------------------------------------
json (reuse) 2.589M (± 9.6%) i/s (386.17 ns/i) - 12.925M in 5.071853s
json 2.594M (± 6.6%) i/s (385.46 ns/i) - 13.086M in 5.083035s
oj 2.250M (± 2.3%) i/s (444.43 ns/i) - 11.255M in 5.004707s
Comparison:
json (reuse): 2589499.6 i/s
json: 2594321.0 i/s - same-ish: difference falls within error
oj: 2250064.0 i/s - 1.15x slower
== Encoding small hash (65 bytes)
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
Warming up --------------------------------------
json (reuse) 656.373k i/100ms
json 644.135k i/100ms
oj 650.283k i/100ms
Calculating -------------------------------------
json (reuse) 7.202M (± 7.1%) i/s (138.84 ns/i) - 36.101M in 5.051438s
json 7.278M (± 1.7%) i/s (137.40 ns/i) - 36.716M in 5.046300s
oj 7.036M (± 1.7%) i/s (142.12 ns/i) - 35.766M in 5.084729s
Comparison:
json (reuse): 7202447.9 i/s
json: 7277883.0 i/s - same-ish: difference falls within error
oj: 7036115.2 i/s - same-ish: difference falls within error
```
|
|
Prior to 2.7.3, `JSON::Ext::Parser` would only take kwargs.
So if json_pure 2.7.4 is loaded with `json <= 2.7.2` (or stdlib)
it blows up.
Ref: https://github.com/ruby/json/issues/650
Fix: https://github.com/ruby/json/issues/651
https://github.com/ruby/json/commit/4d9dc98817
|
|
Fix: https://github.com/ruby/json/issues/646
Since both `json` and `json_pure` expose the same files, if the
versions don't match, the native extension may be loaded with Ruby
code that don't match and is incompatible.
By doing the `require json/ext/generator/state` from C we ensure
we're at least loading that.
But this is a dirty workaround for the 2.7.x branch, we should
find a better way to fully isolate the two gems.
https://github.com/ruby/json/commit/dfdd4acf36
|
|
https://github.com/ruby/json/commit/fb25e94aea
|
|
https://github.com/ruby/json/commit/937c8d2e65
|
|
https://github.com/ruby/json/commit/7a3b482013
|
|
https://github.com/ruby/json/commit/a48be35825
|
|
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
|
|
https://github.com/ruby/json/commit/b240bde402
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
|
|
Avoid needless hash allocations and such that degrade performance
significantly on micro-benchmarks.
|
|
https://github.com/ruby/json/commit/e2e9936047
|
|
If we assume that most of the time the `opts` hash is small
it's faster to go over the provided keys with a `case` than
to test all possible keys one by one.
Before:
```
== Encoding small nested array (121 bytes)
ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
json 156.832k i/100ms
oj 209.769k i/100ms
rapidjson 162.922k i/100ms
Calculating -------------------------------------
json 1.599M (± 2.5%) i/s (625.34 ns/i) - 7.998M in 5.005110s
oj 2.137M (± 1.5%) i/s (467.99 ns/i) - 10.698M in 5.007806s
rapidjson 1.677M (± 3.5%) i/s (596.31 ns/i) - 8.472M in 5.059515s
Comparison:
json: 1599141.2 i/s
oj: 2136785.3 i/s - 1.34x faster
rapidjson: 1676977.2 i/s - same-ish: difference falls within error
== Encoding small hash (65 bytes)
ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
json 216.464k i/100ms
oj 661.328k i/100ms
rapidjson 324.434k i/100ms
Calculating -------------------------------------
json 2.301M (± 1.7%) i/s (434.57 ns/i) - 11.689M in 5.081278s
oj 7.244M (± 1.2%) i/s (138.05 ns/i) - 36.373M in 5.021985s
rapidjson 3.323M (± 2.9%) i/s (300.96 ns/i) - 16.871M in 5.081696s
Comparison:
json: 2301142.2 i/s
oj: 7243770.3 i/s - 3.15x faster
rapidjson: 3322673.0 i/s - 1.44x faster
```
After:
```
== Encoding small nested array (121 bytes)
ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
json 168.087k i/100ms
oj 208.872k i/100ms
rapidjson 149.909k i/100ms
Calculating -------------------------------------
json 1.761M (± 1.1%) i/s (567.90 ns/i) - 8.909M in 5.059794s
oj 2.144M (± 0.9%) i/s (466.37 ns/i) - 10.861M in 5.065903s
rapidjson 1.692M (± 1.7%) i/s (591.04 ns/i) - 8.545M in 5.051808s
Comparison:
json: 1760868.2 i/s
oj: 2144205.9 i/s - 1.22x faster
rapidjson: 1691941.1 i/s - 1.04x slower
== Encoding small hash (65 bytes)
ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
json 242.957k i/100ms
oj 675.217k i/100ms
rapidjson 355.040k i/100ms
Calculating -------------------------------------
json 2.569M (± 1.5%) i/s (389.22 ns/i) - 12.877M in 5.013095s
oj 7.128M (± 2.3%) i/s (140.30 ns/i) - 35.787M in 5.023594s
rapidjson 3.656M (± 3.1%) i/s (273.50 ns/i) - 18.462M in 5.054558s
Comparison:
json: 2569217.5 i/s
oj: 7127705.6 i/s - 2.77x faster
rapidjson: 3656285.0 i/s - 1.42x faster
```
|
|
This helps very marginally with allocation speed.
https://github.com/ruby/json/commit/25db79dfaa
|
|
`JSON.dump` looks terrible on micro-benchmarks because the way it
handles arguments is quite allocation heavy compared to the actual
JSON generation work.
Profiling the `small hash` benchmarked show 14% of time spent in `Array#compact`
and `34%` time spent in `JSON::Ext::GeneratorState.new`. Only `41%` in the
actual `generate` function.
By micro-optimizing `JSON.dump`, it can look much better:
Before:
```
== Encoding small nested array (121 bytes)
ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
json 91.687k i/100ms
oj 205.309k i/100ms
rapidjson 161.648k i/100ms
Calculating -------------------------------------
json 941.965k (± 1.4%) i/s (1.06 μs/i) - 4.768M in 5.062573s
oj 2.138M (± 1.2%) i/s (467.82 ns/i) - 10.881M in 5.091254s
rapidjson 1.678M (± 1.9%) i/s (596.04 ns/i) - 8.406M in 5.011931s
Comparison:
json: 941964.8 i/s
oj: 2137586.5 i/s - 2.27x faster
rapidjson: 1677737.1 i/s - 1.78x faster
== Encoding small hash (65 bytes)
ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
json 141.737k i/100ms
oj 676.871k i/100ms
rapidjson 373.266k i/100ms
Calculating -------------------------------------
json 1.491M (± 1.0%) i/s (670.78 ns/i) - 7.512M in 5.039463s
oj 7.226M (± 1.4%) i/s (138.39 ns/i) - 36.551M in 5.059475s
rapidjson 3.729M (± 2.2%) i/s (268.15 ns/i) - 18.663M in 5.007182s
Comparison:
json: 1490798.2 i/s
oj: 7225766.2 i/s - 4.85x faster
rapidjson: 3729192.2 i/s - 2.50x faster
```
After:
```
== Encoding small nested array (121 bytes)
ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
json 156.832k i/100ms
oj 209.769k i/100ms
rapidjson 162.922k i/100ms
Calculating -------------------------------------
json 1.599M (± 2.5%) i/s (625.34 ns/i) - 7.998M in 5.005110s
oj 2.137M (± 1.5%) i/s (467.99 ns/i) - 10.698M in 5.007806s
rapidjson 1.677M (± 3.5%) i/s (596.31 ns/i) - 8.472M in 5.059515s
Comparison:
json: 1599141.2 i/s
oj: 2136785.3 i/s - 1.34x faster
rapidjson: 1676977.2 i/s - same-ish: difference falls within error
== Encoding small hash (65 bytes)
ruby 3.4.0preview2 (2024-10-07 master 32c733f57b) +YJIT +PRISM [arm64-darwin23]
Warming up --------------------------------------
json 216.464k i/100ms
oj 661.328k i/100ms
rapidjson 324.434k i/100ms
Calculating -------------------------------------
json 2.301M (± 1.7%) i/s (434.57 ns/i) - 11.689M in 5.081278s
oj 7.244M (± 1.2%) i/s (138.05 ns/i) - 36.373M in 5.021985s
rapidjson 3.323M (± 2.9%) i/s (300.96 ns/i) - 16.871M in 5.081696s
Comparison:
json: 2301142.2 i/s
oj: 7243770.3 i/s - 3.15x faster
rapidjson: 3322673.0 i/s - 1.44x faster
```
Now profiles of the `small hash` benchmark show 44% in `generate` and
`45%` in `GeneratorState` allocation.
|
|
* Using the benchmark from https://github.com/flori/json/pull/580
$ ruby benchmarks/bench.rb dump pure
JSON::Pure::Generator
truffleruby 24.0.0, like ruby 3.2.2, Oracle GraalVM Native [x86_64-linux]
Warming up --------------------------------------
JSON.dump(obj) 116.000 i/100ms
JSON.dump(obj) 235.000 i/100ms
JSON.dump(obj) 317.000 i/100ms
JSON.dump(obj) 372.000 i/100ms
JSON.dump(obj) 374.000 i/100ms
Calculating -------------------------------------
JSON.dump(obj) 3.735k (± 0.9%) i/s (267.76 μs/i) - 18.700k in 5.007526s
JSON.dump(obj) 3.738k (± 0.7%) i/s (267.49 μs/i) - 18.700k in 5.002252s
JSON.dump(obj) 3.743k (± 0.7%) i/s (267.18 μs/i) - 19.074k in 5.096375s
JSON.dump(obj) 3.747k (± 0.5%) i/s (266.87 μs/i) - 19.074k in 5.090463s
JSON.dump(obj) 3.746k (± 0.5%) i/s (266.96 μs/i) - 19.074k in 5.092069s
$ ruby benchmarks/bench.rb dump ext
JSON::Ext::Generator
truffleruby 24.0.0, like ruby 3.2.2, Oracle GraalVM Native [x86_64-linux]
Warming up --------------------------------------
JSON.dump(obj) 19.000 i/100ms
JSON.dump(obj) 18.000 i/100ms
JSON.dump(obj) 18.000 i/100ms
JSON.dump(obj) 18.000 i/100ms
JSON.dump(obj) 21.000 i/100ms
Calculating -------------------------------------
JSON.dump(obj) 221.260 (±10.8%) i/s (4.52 ms/i) - 1.092k in 5.004381s
JSON.dump(obj) 221.983 (± 8.1%) i/s (4.50 ms/i) - 1.113k in 5.055574s
JSON.dump(obj) 221.446 (± 8.6%) i/s (4.52 ms/i) - 1.113k in 5.073167s
JSON.dump(obj) 226.452 (± 7.9%) i/s (4.42 ms/i) - 1.134k in 5.048568s
JSON.dump(obj) 227.795 (± 8.3%) i/s (4.39 ms/i) - 1.134k in 5.025187s
https://github.com/flori/json/commit/8256455cdc
|
|
https://github.com/flori/json/commit/036944acc6
|
|
https://github.com/flori/json/commit/fff285968d
|
|
https://github.com/flori/json/commit/b507f9e404
|
|
https://github.com/flori/json/commit/202ffe2335
|
|
https://github.com/flori/json/commit/a1af7a308c
|
|
(https://github.com/flori/json/pull/557)
* RDoc for additions
* Update lib/json/add/time.rb
Co-authored-by: Hiroshi SHIBATA <hsbt@ruby-lang.org>
---------
https://github.com/flori/json/commit/3f2efd60f7
Co-authored-by: Hiroshi SHIBATA <hsbt@ruby-lang.org>
|
|
https://github.com/flori/json/commit/41c2712a3b
|
|
https://github.com/flori/json/commit/936f280f9f
|
|
Fix: https://github.com/flori/json/issues/553
We can never add keyword arguments to `dump` otherwise
existing code using unenclosed hash will break.
https://github.com/flori/json/commit/8e0076a3f2
|
|
> https://github.com/flori/json/pull/525
> Rename escape_slash in script_safe and also escape E+2028 and E+2029
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
> https://github.com/flori/json/pull/454
> Remove unnecessary initialization of create_id in JSON.parse()
Co-authored-by: Watson <watson1978@gmail.com>
|
|
It is rather common to directly interpolate JSON string inside
<script> tags in HTML as to provide configuration or parameters to a
script.
However this may lead to XSS vulnerabilities, to prevent that 3
characters need to be escaped:
- `/` (forward slash)
- `U+2028` (LINE SEPARATOR)
- `U+2029` (PARAGRAPH SEPARATOR)
The forward slash need to be escaped to prevent closing the script
tag early, and the other two are valid JSON but invalid Javascript
and can be used to break JS parsing.
Given that the intent of escaping forward slash is the same than escaping
U+2028 and U+2029, I chos to rename and repurpose the existing `escape_slash`
option.
|
|
https://github.com/flori/json/commit/ca546128f2
|
|
https://github.com/flori/json/commit/ec47749b53
|
|
In `JSON#generate` and `JSON#fast_generate`:
- When the given `opts` is a `JSON::State` the variable is set to
`nil`.
- But it will be never used as the next `if` blocks will not be
executed.
- `JSON::State#configure` does the conversion to `Hash`, the
conversions in the `if` block are just duplication.
- `JSON::State.new` does the same thing with `configure` when an
argument is given.
https://github.com/flori/json/commit/5d9ab87f8e
Notes:
Merged: https://github.com/ruby/ruby/pull/8091
|
|
https://github.com/flori/json/commit/3dd36c6077
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/6890
|
|
https://github.com/flori/json/commit/5de358f655
|
|
https://github.com/flori/json/commit/2db5894cfa
|
|
https://github.com/flori/json/commit/da94d9f059
|
|
This change fixes an incorrect `#` position in the API documentation of the `JSON` module.
https://github.com/flori/json/commit/dc4b62424f
|
|
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/3975
|