Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
### 2026-09-07 (3.0.0)

* Add `JSON::ParserError#json_path` to locate parse errors in the document as a JSONPath-style string (e.g. `$.foo[0].bar`). For duplicate key errors it points at the duplicated key itself.
* JRuby: parser errors now include the position (`line`, `column` and the message suffix) as well as `json_path`, matching the C extension.
* Fix the parser to also reject lone trailing UTF-16 surrogates (`\uDCxx` with no leading partner), symmetric to the leading-surrogate case. The Java parser already rejected these; this closes the CRuby/JRuby parity gap.

### 2026-08-11 (3.0.0.rc1)
Expand Down
83 changes: 72 additions & 11 deletions java/src/json/ext/Parser.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 10 additions & 8 deletions test/json/json_parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -852,8 +852,6 @@ def test_parse_error_snippet
end

def test_parse_error_json_path
omit "JRuby errors don't contain positions" if RUBY_ENGINE == "jruby"

assert_parse_error_at "$", "xyz"
assert_parse_error_at "$.a", '{"a": xyz}'
assert_parse_error_at "$[3]", '[1, 2, "hi", xyz]'
Expand All @@ -870,9 +868,17 @@ def test_parse_error_json_path
assert_parse_error_at "$[5]", '[1,2,3,4,5,]'
end

def test_parse_error_json_path_on_load
omit "JRuby errors don't contain positions" if RUBY_ENGINE == "jruby"
def test_parse_error_position
error = assert_raise(JSON::ParserError) { JSON.parse("[1,\n@") }
assert_equal 2, error.line
assert_equal 1, error.column

error = assert_raise(JSON::ParserError) { JSON.parse('{"a": {"b": [1, {"c": 1, "c": 2}]}}') }
assert_equal 1, error.line
assert_equal 17, error.column
end

def test_parse_error_json_path_on_load
assert_parse_error_at "$" do
JSON.load('{"a": {"b": {"c":', -> (obj) {
if String === obj
Expand All @@ -895,8 +901,6 @@ def test_parse_error_json_path_on_load
end

def test_parse_error_json_path_key_escaping
omit "JRuby errors don't contain positions" if RUBY_ENGINE == "jruby"

assert_parse_error_at '$["hello world"]', '{"hello world": xyz}'
assert_parse_error_at '$["a\"b"]', '{"a\"b": xyz}'
assert_parse_error_at '$[""]', '{"": xyz}'
Expand All @@ -905,8 +909,6 @@ def test_parse_error_json_path_key_escaping
end

def test_parse_error_json_path_duplicate_key
omit "JRuby errors don't contain positions" if RUBY_ENGINE == "jruby"

assert_parse_error_at "$.a", '{"a": 1, "a": 2}'
assert_parse_error_at "$.x.a", '{"x": {"a": 1, "b": 2, "a": 3}}'
assert_parse_error_at "$.arr[0].a", '{"arr": [{"a": 1, "a": 2}]}'
Expand Down