From 4cc2f3ffe111e3e762294eb25084688ef3eed890 Mon Sep 17 00:00:00 2001 From: Sebastian Turner Date: Mon, 19 Oct 2026 08:47:29 -0700 Subject: [PATCH] Fix ParserError#json_path with symbolize_names: true Signed-off-by: Sebastian Turner --- CHANGES.md | 2 ++ lib/json/common.rb | 3 ++- test/json/json_parser_test.rb | 12 ++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index d7c7ad118..1e1b5a9ed 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,8 @@ ### Unreleased +* Fix `JSON::ParserError#json_path` raising `NoMethodError` when the document was parsed with `symbolize_names: true`. + ### 2026-10-13 (3.1.0) * Added `rfc8785` generator option to canonicalize the output. Replaces the `json-canonicalization` with numerous correctness fixes. diff --git a/lib/json/common.rb b/lib/json/common.rb index 4b2d6d87f..bf96f4137 100644 --- a/lib/json/common.rb +++ b/lib/json/common.rb @@ -171,13 +171,14 @@ def build_json_path(segments) when Integer "[#{segment}]" when String, Symbol + segment = segment.to_s if !segment.valid_encoding? segment = segment.b.gsub(/["\\]/n, { '"' => '\\"', '\\' => '\\\\' }).force_encoding(Encoding::UTF_8) %{["#{segment}"]} elsif segment.match?(/\A[a-zA-Z\$\_][a-zA-Z\$\_0-9]*\z/) ".#{segment}" else - segment = segment.to_s.gsub(/["\\]/, { '"' => '\\"', '\\' => '\\\\' }) + segment = segment.gsub(/["\\]/, { '"' => '\\"', '\\' => '\\\\' }) %{["#{segment}"]} end else diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb index 3607be33a..3f8575c8a 100644 --- a/test/json/json_parser_test.rb +++ b/test/json/json_parser_test.rb @@ -1004,6 +1004,18 @@ def test_parse_error_json_path_key_escaping assert_parse_error_at '$.foo["1x"]', '{"foo": {"1x": xyz}}' end + def test_parse_error_json_path_symbolize_names + assert_parse_error_at "$.a[1].b" do + JSON.parse('{"a": [1, {"b": xyz}]}', symbolize_names: true) + end + assert_parse_error_at '$["hello world"]' do + JSON.parse('{"hello world": xyz}', symbolize_names: true) + end + assert_parse_error_at "$.x.a" do + JSON.parse('{"x": {"a": 1, "a": 2}}', symbolize_names: true) + end + end + def test_parse_error_json_path_duplicate_key assert_parse_error_at "$.a", '{"a": 1, "a": 2}' assert_parse_error_at "$.x.a", '{"x": {"a": 1, "b": 2, "a": 3}}'