This is an automated email from the ASF dual-hosted git repository.
kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new df824c10a7 GH-50904: [C++] Replace RapidJSON with simdjson in
OpaqueType (#50905)
df824c10a7 is described below
commit df824c10a7429bbed6de04715d8e008e28674074
Author: Aaditya Srinivasan <[email protected]>
AuthorDate: Thu Aug 20 02:45:25 2026 +0530
GH-50904: [C++] Replace RapidJSON with simdjson in OpaqueType (#50905)
### Rationale for this change
This PR continues the simdjson migration by replacing the remaining
RapidJSON usage in `OpaqueType` under `cpp/src/arrow/extension` with the
existing simdjson helpers and On-Demand API.
The existing deserialization validation and behavior are preserved, with
tests updated for parser-specific error messages.
### Changes
- Replace RapidJSON parsing in `OpaqueType::Deserialize()` with simdjson.
- Use the existing `ResolveSimdjsonResult()` helper.
- Remove the RapidJSON dependency from `opaque.cc`.
- Update OpaqueType deserialization tests for simdjson parsing errors.
* GitHub Issue: #50904
Authored-by: Aaditya Srinivasan <[email protected]>
Signed-off-by: Sutou Kouhei <[email protected]>
---
cpp/src/arrow/extension/opaque.cc | 90 +++++++++++++++++++++++++---------
cpp/src/arrow/extension/opaque_test.cc | 7 +--
2 files changed, 71 insertions(+), 26 deletions(-)
diff --git a/cpp/src/arrow/extension/opaque.cc
b/cpp/src/arrow/extension/opaque.cc
index b1ad48fdba..c6068babdb 100644
--- a/cpp/src/arrow/extension/opaque.cc
+++ b/cpp/src/arrow/extension/opaque.cc
@@ -20,11 +20,10 @@
#include <sstream>
#include "arrow/json/json_writer_internal.h"
-#include "arrow/json/rapidjson_defs.h" // IWYU pragma: keep
#include "arrow/util/logging_internal.h"
+#include "arrow/util/simdjson_internal.h"
-#include <rapidjson/document.h>
-#include <rapidjson/error/en.h>
+#include <simdjson.h>
using ::arrow::json::JsonWriter;
@@ -65,34 +64,79 @@ std::string OpaqueType::Serialize() const {
Result<std::shared_ptr<DataType>> OpaqueType::Deserialize(
std::shared_ptr<DataType> storage_type, const std::string&
serialized_data) const {
- rapidjson::Document document;
- const auto& parsed = document.Parse(serialized_data.data(),
serialized_data.length());
- if (parsed.HasParseError()) {
- return Status::Invalid("Invalid serialized JSON data for OpaqueType: ",
-
rapidjson::GetParseError_En(parsed.GetParseError()), ": ",
- serialized_data);
- } else if (!document.IsObject()) {
- return Status::Invalid("Invalid serialized JSON data for OpaqueType: not
an object");
+ simdjson::padded_string padded_json(serialized_data);
+ simdjson::ondemand::parser parser;
+
+ ARROW_ASSIGN_OR_RAISE(auto document,
+
internal::ResolveSimdjsonResult(parser.iterate(padded_json),
+ "Failed to parse
JSON"));
+
+ ARROW_ASSIGN_OR_RAISE(auto object,
+ internal::ResolveSimdjsonResult(document.get_object(),
+ "Failed to get JSON
object"));
+
+ std::string type_name;
+ std::string vendor_name;
+ bool has_type_name = false;
+ bool has_vendor_name = false;
+
+ for (auto field_result : object) {
+ ARROW_ASSIGN_OR_RAISE(auto field, internal::ResolveSimdjsonResult(
+ field_result, "Failed to iterate
JSON object"));
+
+ ARROW_ASSIGN_OR_RAISE(
+ auto key, internal::ResolveSimdjsonResult(field.unescaped_key(),
+ "Failed to get JSON object
key"));
+
+ auto value = field.value();
+
+ if (key == "type_name") {
+ has_type_name = true;
+
+ ARROW_ASSIGN_OR_RAISE(auto type,
+ internal::ResolveSimdjsonResult(
+ value.type(), "Failed to determine type_name
JSON type"));
+
+ if (type != simdjson::ondemand::json_type::string) {
+ return Status::Invalid(
+ "Invalid serialized JSON data for OpaqueType: type_name is not a
string");
+ }
+
+ ARROW_ASSIGN_OR_RAISE(
+ auto name,
+ internal::ResolveSimdjsonResult(value.get_string(), "Failed to get
type_name"));
+ type_name = std::string(name);
+
+ } else if (key == "vendor_name") {
+ has_vendor_name = true;
+
+ ARROW_ASSIGN_OR_RAISE(
+ auto type, internal::ResolveSimdjsonResult(
+ value.type(), "Failed to determine vendor_name JSON
type"));
+
+ if (type != simdjson::ondemand::json_type::string) {
+ return Status::Invalid(
+ "Invalid serialized JSON data for OpaqueType: vendor_name is not a
string");
+ }
+
+ ARROW_ASSIGN_OR_RAISE(auto name,
+ internal::ResolveSimdjsonResult(value.get_string(),
+ "Failed to get
vendor_name"));
+ vendor_name = std::string(name);
+ }
}
- if (!document.HasMember("type_name")) {
+
+ if (!has_type_name) {
return Status::Invalid(
"Invalid serialized JSON data for OpaqueType: missing type_name");
- } else if (!document.HasMember("vendor_name")) {
- return Status::Invalid(
- "Invalid serialized JSON data for OpaqueType: missing vendor_name");
}
- const auto& type_name = document["type_name"];
- const auto& vendor_name = document["vendor_name"];
- if (!type_name.IsString()) {
+ if (!has_vendor_name) {
return Status::Invalid(
- "Invalid serialized JSON data for OpaqueType: type_name is not a
string");
- } else if (!vendor_name.IsString()) {
- return Status::Invalid(
- "Invalid serialized JSON data for OpaqueType: vendor_name is not a
string");
+ "Invalid serialized JSON data for OpaqueType: missing vendor_name");
}
- return opaque(std::move(storage_type), type_name.GetString(),
vendor_name.GetString());
+ return opaque(std::move(storage_type), std::move(type_name),
std::move(vendor_name));
}
std::shared_ptr<Array> OpaqueType::MakeArray(std::shared_ptr<ArrayData> data)
const {
diff --git a/cpp/src/arrow/extension/opaque_test.cc
b/cpp/src/arrow/extension/opaque_test.cc
index 16fcba3fa6..ac093ddfe0 100644
--- a/cpp/src/arrow/extension/opaque_test.cc
+++ b/cpp/src/arrow/extension/opaque_test.cc
@@ -127,12 +127,13 @@ TEST(OpaqueType, Deserialize) {
auto type = internal::checked_pointer_cast<extension::OpaqueType>(
extension::opaque(null(), "type", "vendor"));
- EXPECT_RAISES_WITH_MESSAGE_THAT(Invalid, testing::HasSubstr("The document is
empty"),
+ EXPECT_RAISES_WITH_MESSAGE_THAT(Invalid, testing::HasSubstr("Failed to parse
JSON"),
type->Deserialize(null(), R"()"));
EXPECT_RAISES_WITH_MESSAGE_THAT(Invalid,
- testing::HasSubstr("Missing a name for
object member"),
+ testing::HasSubstr("Failed to get JSON
object"),
type->Deserialize(null(), R"({)"));
- EXPECT_RAISES_WITH_MESSAGE_THAT(Invalid, testing::HasSubstr("not an object"),
+ EXPECT_RAISES_WITH_MESSAGE_THAT(Invalid,
+ testing::HasSubstr("Failed to get JSON
object"),
type->Deserialize(null(), R"([])"));
EXPECT_RAISES_WITH_MESSAGE_THAT(Invalid, testing::HasSubstr("missing
type_name"),
type->Deserialize(null(), R"({})"));