json-repair 0.13.0 → 0.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf5d06053ce264da6b60de4beef4a5718fd3482c81d295deea6dbf90fc63c098
4
- data.tar.gz: 9d343f549cf34414e0de45618cb19bd4a9b58b12e53c2f52da0380fc73b4d95a
3
+ metadata.gz: 3e0898f751c91f7c3a026ccb107c319b983212296090031ba6b7a80713de18eb
4
+ data.tar.gz: 21028aa56a685b77ea42506333753deb1a903108b860843a877181b6af66b1a2
5
5
  SHA512:
6
- metadata.gz: 269f7de75ec6cadde857d2f7c10186b1d0c63a19aa3e863744957c95b98db8d0cef790deef8814d532ca62c0405d97cfc5f441c37be9f1c4e6c7f5cfe07eaa67
7
- data.tar.gz: 9cbc099462defe41b8bf96f590833d61de90f79c8e5b0f2d8a7d0ae04ee72dcc7e512c6f3886f67cb0e700dfb1046abd143b2adbde560c502d25700035e69834
6
+ metadata.gz: 05752fda1b0ff27c2dcde8b217099460bdecb57efa4a3ab73ce534f27dfecf51673f68683f3009c8d159079bfb7fee3f0892f2c86e3f15d0e86a58d4c497c8f0
7
+ data.tar.gz: 46a8a689d2a969c3c7ca1395dbd4a5555e191e304c0cfffd3bbaec44d22066b2a8527efc7323267c62c21738364c2dddf917d20af3388ae87cf993d872d014a0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changes
2
2
 
3
+ ### 2026-06-17 (0.14.0)
4
+
5
+ * Repair a leading `+` on numbers, like in JSON5: `+1.23` → `1.23`,
6
+ `[+1]` → `[1]`, `{"a": +5}` → `{"a":5}`, `+.5` → `0.5`. The `+` is
7
+ consumed and dropped (JSON has no explicit plus), so a leading-zero
8
+ number is quoted exactly like its unsigned form (`+05` → `"05"`),
9
+ while a `+` inside an exponent is left untouched (`2e+5` →
10
+ `200000.0`). The `+` must be followed by a digit or a leading dot, so
11
+ a bare `+` (and `+abc`, `++1`, `+e5`) still raises — and requiring a
12
+ digit/dot keeps the 0.12.0 empty-mantissa exponent guard intact.
13
+ Divergence from upstream
14
+ [jsonrepair](https://github.com/josdejong/jsonrepair) (v3.14.0 leaves
15
+ `+1.23` unrepaired, raising "Unexpected end of json string"),
16
+ commented at the site. Mirrors the leading-dot number repair (0.9.0).
17
+
3
18
  ### 2026-06-12 (0.13.0)
4
19
 
5
20
  * Repair `#` hash line comments, like in Python, YAML, or Hjson:
data/CLAUDE.md CHANGED
@@ -24,7 +24,7 @@ A few repair heuristics deliberately go **beyond** upstream (leading-dot numbers
24
24
 
25
25
  ### Entry point
26
26
 
27
- `JSON.repair(str)` in `lib/json/repair.rb` first tries stdlib `JSON.parse` (fast path; opt out with `skip_json_loads: true`), and falls back to `JSON::Repairer.new(str).repair` when that raises. Either way the result is re-serialized with `JSON.generate`, so **output is canonical** — whitespace collapsed, numbers normalized, duplicate keys last-write-wins — and both paths agree on it. A `REPAIR_REQUIRED_PATTERN` regex routes inputs containing comments or invalid escapes straight to the Repairer even though the bundled `json` gem would accept them. `return_objects: true` returns the parsed Ruby value instead of a string; `JSON.repair_file(path)` / `JSON.repair_io(io)` are convenience wrappers forwarding both options.
27
+ `JSON.repair(str)` in `lib/json/repair.rb` first tries stdlib `JSON.parse` (fast path; opt out with `skip_json_loads: true`), and falls back to `JSON::Repairer.new(str).repair` when that raises. Either way the result is re-serialized with `JSON.generate`, so **output is canonical** — whitespace collapsed, numbers normalized, duplicate keys last-write-wins — and both paths agree on it. There is no pre-filter regex: the fast path simply runs `JSON.parse` and falls back to the Repairer on any `JSON::ParserError`. Comments are handled either way — the bundled `json` gem currently accepts `//` and `/*` comments (an implementation detail, not part of the `JSON.parse` contract) and `JSON.generate` drops them (`{} // c` → `{}`); were a future `json` release to reject them, they would simply raise and route to the Repairer, which strips comments too. Invalid escapes, NDJSON, Markdown fences, and trailing prose already make `JSON.parse` raise and so route to the Repairer. `return_objects: true` returns the parsed Ruby value instead of a string; `JSON.repair_file(path)` / `JSON.repair_io(io)` are convenience wrappers forwarding both options.
28
28
 
29
29
  `JSON::JSONRepairError` is the only error raised for unrecoverable inputs; it exposes the failure `#position`. If the Repairer ever emits a string stdlib cannot parse (a Repairer bug), the `JSON::ParserError` is wrapped in `JSONRepairError` rather than leaked.
30
30
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module JSON
4
4
  module Repair
5
- VERSION = '0.13.0'
5
+ VERSION = '0.14.0'
6
6
  end
7
7
  end
data/lib/json/repairer.rb CHANGED
@@ -741,6 +741,24 @@ module JSON
741
741
  # Parse a number like 2.4 or 2.4e6
742
742
  def parse_number
743
743
  start = @index
744
+
745
+ # Divergence from upstream: accept and discard a leading "+". JSON5
746
+ # permits an explicit plus; JSON does not, so "+1.23" -> "1.23" and
747
+ # "{"a": +5}" -> {"a":5}. The "+" must be followed by a digit or a
748
+ # leading dot (mirroring the "-" branch below); otherwise this is not
749
+ # a number and we backtrack to the "+" so a bare "+" still raises.
750
+ # `start` stays on the "+", so the reset paths restore @index cleanly
751
+ # and the @index > start exponent guard below still implies a digit
752
+ # was consumed; the two emission sites drop the leading "+" before
753
+ # quoting. Upstream leaves "+1.23" unrepaired.
754
+ if @json[@index] == PLUS
755
+ @index += 1
756
+ unless digit?(@json[@index]) || @json[@index] == DOT
757
+ @index = start
758
+ return false
759
+ end
760
+ end
761
+
744
762
  if @json[@index] == '-'
745
763
  @index += 1
746
764
  if at_end_of_number?
@@ -802,7 +820,9 @@ module JSON
802
820
 
803
821
  if @index > start
804
822
  # repair a number with leading zeros like "00789"
805
- num = @json[start...@index]
823
+ # drop a leading "+" first (see the PLUS branch above), so "+05"
824
+ # quotes like "05" and "+1.23" emits as "1.23"
825
+ num = @json[start...@index].delete_prefix(PLUS)
806
826
  # the optional sign quotes "-05" like "05" (divergence from
807
827
  # upstream, whose unsigned check lets "-05" through unrepaired)
808
828
  has_invalid_leading_zero = num.match?(/^-?0\d/)
@@ -908,7 +928,8 @@ module JSON
908
928
  # repair numbers cut off at the end
909
929
  # this will only be called when we end after a '.', '-', or 'e' and does not
910
930
  # change the number more than it needs to make it valid JSON
911
- num = "#{@json[start...@index]}0"
931
+ # delete_prefix drops a leading "+" (see the PLUS branch in parse_number)
932
+ num = "#{@json[start...@index]}0".delete_prefix(PLUS)
912
933
  # quote a padded token that has an invalid leading zero, like "05e" ->
913
934
  # "05e0", applying the same rule as the end of parse_number (divergence
914
935
  # from upstream, which emits the invalid number raw)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-repair
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksandr Zykov