diff --git a/cpp/src/json/json_path.cu b/cpp/src/json/json_path.cu index ff74c2167dde..0931724dfd41 100644 --- a/cpp/src/json/json_path.cu +++ b/cpp/src/json/json_path.cu @@ -355,7 +355,8 @@ class json_state : private parser { * The user can specify whether or not the name string must be present via * the `can_be_empty` flag. * - * When a name is present, it must be followed by a colon `:` + * When a name is present, it must be followed by a colon `:`. A present but zero-length + * name (the `""` key of `{"":1}`) is not an absent name. * * @param[out] name The resulting name. * @param can_be_empty Parameter indicating whether it is valid for the name @@ -366,17 +367,16 @@ class json_state : private parser { { char const quote = options.get_allow_single_quotes() ? 0 : '\"'; - if (parse_string(name, can_be_empty, quote) == parse_result::ERROR) { - return parse_result::ERROR; + if (auto const result = parse_string(name, can_be_empty, quote); + result != parse_result::SUCCESS) { + return result; } - // if we got a real string, the next char must be a : - if (name.size_bytes() > 0) { - if (!parse_whitespace()) { return parse_result::ERROR; } - if (*pos == ':') { - pos++; - return parse_result::SUCCESS; - } + // a name is present, so the next char must be a : + if (!parse_whitespace()) { return parse_result::ERROR; } + if (*pos == ':') { + pos++; + return parse_result::SUCCESS; } return parse_result::EMPTY; } diff --git a/cpp/tests/json/json_tests.cpp b/cpp/tests/json/json_tests.cpp index 1d201844a963..ab22dc1f4a93 100644 --- a/cpp/tests/json/json_tests.cpp +++ b/cpp/tests/json/json_tests.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -1044,6 +1044,21 @@ TEST_F(JsonPathTests, QueriesContainingQuotes) do_test(R"($.'A)", R"({"B'": 3})"); } +TEST_F(JsonPathTests, ObjectWithEmptyKey) +{ + auto const input = cudf::test::strings_column_wrapper{R"({"":0,"a":1})", + R"({"a":1,"":0})", + R"({"" : 0, "a" : 1})", + R"({"":{"a":9},"a":1})", + R"({"":[1,2],"a":1})", + R"({"":"s","a":1})"}; + + auto const result = + cudf::get_json_object(cudf::strings_column_view(input), std::string_view{"$.a"}); + auto const expected = cudf::test::strings_column_wrapper{"1", "1", "1", "1", "1", "1"}; + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(*result, expected); +} + // Test that get_json_object creates valid string columns for empty/whitespace JSONPath queries TEST_F(JsonPathTests, EmptyPathCreatesValidColumn) {