json-repair 0.6.0 → 0.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/.rubocop.yml +1 -0
- data/CHANGELOG.md +27 -0
- data/README.md +18 -1
- data/Rakefile +5 -0
- data/lib/json/repair/cli.rb +1 -2
- data/lib/json/repair/version.rb +1 -1
- data/lib/json/repair.rb +15 -3
- data/sig/json/repair.rbs +9 -3
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fdf2958528b936eba0faf6c724a20d10a3a3e0b95329bc1866740c99432f6fe3
|
|
4
|
+
data.tar.gz: 33fa97d2c7689ea594723e5d0d412646cf57a2ebdbf79f3b62947d4928963f32
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 587323c57caac3e53af1da24cfeee47df18ff738516d8fd2862d37a547c6e864cf5653c8b43427ec58aa47be3f2e958c991208b36de098c5ffc9503f2c64a0a2
|
|
7
|
+
data.tar.gz: f5380cfdca6a4f60833ab57fc8465715b546415fa4f6ed5781b6bb24653ce324d2b6d928f9a5ff87b4deead145391303c1e805bf0fbff238b9ef1c7024a1f4aa
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
### 2026-05-12 (0.7.0)
|
|
4
|
+
|
|
5
|
+
* `JSON.repair` now always returns canonical JSON via
|
|
6
|
+
`JSON.generate`. When the input is already valid JSON, stdlib
|
|
7
|
+
`JSON.parse` handles it directly; when it isn't, the repairer
|
|
8
|
+
produces an intermediate string that's then re-parsed and serialized
|
|
9
|
+
the same way. Both paths converge on the same output for any given
|
|
10
|
+
input, so `JSON.repair(json)` and
|
|
11
|
+
`JSON.repair(json, skip_json_loads: true)` agree on result and only
|
|
12
|
+
differ in how they got there.
|
|
13
|
+
* **Breaking:** outputs are now canonical instead of preserving the
|
|
14
|
+
input's exact formatting. Whitespace is collapsed
|
|
15
|
+
(`'{"a": 1}'` → `'{"a":1}'`), numbers are normalized
|
|
16
|
+
(`2300e3` → `2300000.0`, `-0` → `0`), `\uXXXX` escapes are decoded
|
|
17
|
+
to their literal characters, `\/` is unescaped to `/`, and objects
|
|
18
|
+
with duplicate keys are collapsed to the last-write-wins form
|
|
19
|
+
(`{"a":1,"a":2}` → `{"a":2}`). Callers that need a parsed Ruby
|
|
20
|
+
value can opt out of the final `JSON.generate` step with
|
|
21
|
+
`return_objects: true`.
|
|
22
|
+
* `skip_json_loads:` keyword argument added (default `false`,
|
|
23
|
+
mirroring Python's
|
|
24
|
+
[`json_repair`](https://github.com/mangiucugna/json_repair)
|
|
25
|
+
option). Passing `true` skips the stdlib `JSON.parse` fast attempt
|
|
26
|
+
and routes the input through the repairer first; the final output
|
|
27
|
+
is identical, so the option is purely a performance knob for
|
|
28
|
+
callers who know their input will need repair.
|
|
29
|
+
|
|
3
30
|
### 2026-05-12 (0.6.0)
|
|
4
31
|
|
|
5
32
|
* `JSON.repair` accepts a `return_objects:` keyword argument. Pass
|
data/README.md
CHANGED
|
@@ -26,7 +26,7 @@ require 'json/repair'
|
|
|
26
26
|
# Example of repairing a JSON string
|
|
27
27
|
broken_json = '{name: Alice, "age": 25,}'
|
|
28
28
|
repaired_json = JSON.repair(broken_json)
|
|
29
|
-
puts repaired_json # Outputs: {"name":
|
|
29
|
+
puts repaired_json # Outputs: {"name":"Alice","age":25}
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
The `repair` method takes a string containing JSON data and returns a corrected version of this string, ensuring it is valid JSON.
|
|
@@ -38,6 +38,21 @@ JSON.repair('{a: 1, b: [2, 3,]}', return_objects: true)
|
|
|
38
38
|
# => {"a" => 1, "b" => [2, 3]}
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
### Canonical output
|
|
42
|
+
|
|
43
|
+
`JSON.repair` returns canonical JSON via `JSON.generate`. When the input is already valid, stdlib `JSON.parse` handles it; otherwise the repairer fixes it up and the result is re-serialized the same way. Either way, the output is the canonical form of the parsed value — whitespace is collapsed, numbers are normalized, `\uXXXX` escapes are decoded to literal characters, and objects with duplicate keys collapse to last-write-wins.
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
JSON.repair('{"a": 1}') # => '{"a":1}'
|
|
47
|
+
JSON.repair('{a:1}') # => '{"a":1}'
|
|
48
|
+
JSON.repair('2300e3') # => '2300000.0'
|
|
49
|
+
JSON.repair('{"a":1,"a":2}') # => '{"a":2}'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
If you need the parsed Ruby value instead of a string, pass `return_objects: true` (covered above).
|
|
53
|
+
|
|
54
|
+
`skip_json_loads: true` skips the stdlib `JSON.parse` attempt and routes the input straight through the repairer. The output is the same; the option is purely a performance knob for callers who know their input will need repair.
|
|
55
|
+
|
|
41
56
|
## Command line
|
|
42
57
|
|
|
43
58
|
The gem ships a `json-repair` executable. It reads from stdin or a file and writes to stdout, `--output FILE`, or back over the input file with `--overwrite`.
|
|
@@ -57,6 +72,8 @@ Run `json-repair --help` for the full list of options.
|
|
|
57
72
|
|
|
58
73
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
59
74
|
|
|
75
|
+
Run `bundle exec rake bench` for a `benchmark-ips` regression baseline across four canned scenarios (valid mixed JSON, broken LLM-style output, a large array, deeply nested objects). The harness lives under `benchmark/` and is not shipped in the published gem.
|
|
76
|
+
|
|
60
77
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
61
78
|
|
|
62
79
|
## Contributing
|
data/Rakefile
CHANGED
data/lib/json/repair/cli.rb
CHANGED
data/lib/json/repair/version.rb
CHANGED
data/lib/json/repair.rb
CHANGED
|
@@ -15,8 +15,20 @@ module JSON
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def self.repair(json, return_objects: false)
|
|
19
|
-
|
|
20
|
-
return_objects ? JSON.
|
|
18
|
+
def self.repair(json, return_objects: false, skip_json_loads: false)
|
|
19
|
+
parsed = skip_json_loads ? repaired_parse(json) : tolerant_parse(json)
|
|
20
|
+
return_objects ? parsed : JSON.generate(parsed)
|
|
21
21
|
end
|
|
22
|
+
|
|
23
|
+
def self.tolerant_parse(json)
|
|
24
|
+
JSON.parse(json)
|
|
25
|
+
rescue JSON::ParserError
|
|
26
|
+
repaired_parse(json)
|
|
27
|
+
end
|
|
28
|
+
private_class_method :tolerant_parse
|
|
29
|
+
|
|
30
|
+
def self.repaired_parse(json)
|
|
31
|
+
JSON.parse(Repairer.new(json).repair)
|
|
32
|
+
end
|
|
33
|
+
private_class_method :repaired_parse
|
|
22
34
|
end
|
data/sig/json/repair.rbs
CHANGED
|
@@ -9,7 +9,13 @@ module JSON
|
|
|
9
9
|
VERSION: ::String
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def self.repair: (::String json) -> ::String
|
|
13
|
-
| (::String json, return_objects:
|
|
14
|
-
| (::String json,
|
|
12
|
+
def self.repair: (::String json, return_objects: false, ?skip_json_loads: bool) -> ::String
|
|
13
|
+
| (::String json, return_objects: true, ?skip_json_loads: bool) -> untyped
|
|
14
|
+
| (::String json, ?skip_json_loads: bool) -> ::String
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def self.tolerant_parse: (::String json) -> untyped
|
|
19
|
+
|
|
20
|
+
def self.repaired_parse: (::String json) -> untyped
|
|
15
21
|
end
|