Skip to content

fix(migrate): accept trailing commas in jsonc input (#276)#280

Merged
BartWaardenburg merged 2 commits intofallow-rs:mainfrom
ChrisJr404:fix/jsonc-trailing-commas-276
May 5, 2026
Merged

fix(migrate): accept trailing commas in jsonc input (#276)#280
BartWaardenburg merged 2 commits intofallow-rs:mainfrom
ChrisJr404:fix/jsonc-trailing-commas-276

Conversation

@ChrisJr404
Copy link
Copy Markdown
Contributor

Closes #276.

Summary

Real-world JSONC files (knip.jsonc, tsconfig.json, .vscode/settings.json, etc.) routinely use trailing commas. load_json_or_jsonc ran the input through json_comments::StripComments and then handed the result to serde_json, which rejects trailing commas with trailing comma at line N column M — exactly the symptom in the issue.

Fix

Add a final pass that drops , immediately before } or ] while leaving commas inside string literals untouched. The pass runs only when the comment-stripped parse fails, so already-valid input pays zero cost on the happy path:

  1. Try plain serde_json::from_str — works for normal JSON.
  2. Strip comments via json_comments::StripComments, retry parse.
  3. If that still fails, run strip_trailing_commas on the comment-stripped text and retry.

strip_trailing_commas is a small byte-level state machine (no new deps) that walks the input, tracks in-string + escaped state, and emits the original text minus any , that's followed only by whitespace before } or ]. Multi-byte UTF-8 chars are preserved verbatim because their continuation bytes never collide with the , / \" / \\ / } / ] markers we look at.

Tests

crates/cli/src/migrate/tests.rs adds:

  • load_json_or_jsonc_accepts_trailing_commas — reproduces the issue exactly: a knip.jsonc shaped file with trailing commas after "src/main.ts" and "dist/**" and the outermost object closer. Was failing before, parses correctly now.
  • load_json_or_jsonc_handles_comments_and_trailing_commas_together// line comment, /* block comment */, and trailing commas all in the same file.
  • Six unit tests on the helper itself: simple object/array trailing comma, separator-comma preservation, comma-in-string preservation ("hello, world,"), escaped quotes ("he said \"hi,\","), and pretty-printed-with-newlines input.

cargo test -p fallow-cli — 1745 passed, 0 failed.

Backwards compatibility

Strict JSON inputs hit branch 1 and bypass the new pass entirely, so anything that worked before still works. The new pass only runs when both branch 1 and branch 2 already failed, so it's a strictly additive fallback.

Closes fallow-rs#276.

real-world JSONC files (knip.jsonc, tsconfig.json, .vscode/settings.json,
etc.) routinely use trailing commas. `load_json_or_jsonc` ran the input
through `json_comments::StripComments` and then handed the result to
serde_json, which rejects trailing commas with "trailing comma at line N
column M". Add a final pass that drops `,` immediately before `}` or
`]` while leaving commas inside string literals untouched. The pass runs
only when the comment-stripped parse fails, so already-valid input has
zero overhead.

The new `strip_trailing_commas` helper is a small byte-level state
machine (no extra deps) that tracks in-string + escaped state, so
strings like "hello, world," survive verbatim.
@BartWaardenburg BartWaardenburg merged commit 47306d3 into fallow-rs:main May 5, 2026
1 check passed
@BartWaardenburg
Copy link
Copy Markdown
Collaborator

Merged in 47306d3. Thanks @ChrisJr404. fallow migrate --from knip now handles trailing-comma knip.jsonc files (and JSONC in general) while still rejecting genuinely malformed input like {,}. The byte-level state machine keeps commas inside string literals untouched and only fires when the comment-stripped parse fails, so already-valid input has zero overhead.

@BartWaardenburg
Copy link
Copy Markdown
Collaborator

Released in v2.65.0. Thanks @ChrisJr404.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate fails with jsonc and trailing commas

2 participants