From 1d922e9bb7a6dd65c6e9b98501ad92102dfec2a9 Mon Sep 17 00:00:00 2001 From: Rustam Gamidov Date: Tue, 17 Mar 2026 15:29:56 +0200 Subject: [PATCH 1/3] Use Boost::json in olp-cpp-sdk-core Migrating from RapidJSON Json wrappers has been moved and not exposed anymore Relates-To: OCMAM-446 Signed-off-by: Rustam Gamidov --- olp-cpp-sdk-core/CMakeLists.txt | 17 ++- .../olp/core/generated/parser/ParserWrapper.h | 98 --------------- .../generated/serializer/SerializerWrapper.h | 114 ------------------ .../src/client/api/JsonResultParser.h | 4 +- .../src/client/parser/ApiParser.cpp | 9 +- .../src/client/parser/ApiParser.h | 6 +- .../generated/parser/JsonParser.h | 33 ++--- .../src/generated/parser/ParserWrapper.h | 102 ++++++++++++++++ .../generated/serializer/SerializerWrapper.h | 102 ++++++++++++++++ tests/common/ReadDefaultResponses.cpp | 98 ++++++--------- tests/common/WriteDefaultResponses.h | 10 +- 11 files changed, 283 insertions(+), 310 deletions(-) delete mode 100644 olp-cpp-sdk-core/include/olp/core/generated/parser/ParserWrapper.h delete mode 100644 olp-cpp-sdk-core/include/olp/core/generated/serializer/SerializerWrapper.h rename olp-cpp-sdk-core/{include/olp/core => src}/generated/parser/JsonParser.h (66%) create mode 100644 olp-cpp-sdk-core/src/generated/parser/ParserWrapper.h create mode 100644 olp-cpp-sdk-core/src/generated/serializer/SerializerWrapper.h diff --git a/olp-cpp-sdk-core/CMakeLists.txt b/olp-cpp-sdk-core/CMakeLists.txt index e694436ad..9bab6cedf 100644 --- a/olp-cpp-sdk-core/CMakeLists.txt +++ b/olp-cpp-sdk-core/CMakeLists.txt @@ -19,7 +19,6 @@ project(olp-cpp-sdk-core VERSION 1.24.0) set(DESCRIPTION "Core network and utility library for the HERE OLP SDK C++") -find_package(RapidJSON 1.1.0 REQUIRED) find_package(Boost REQUIRED) find_package(Threads REQUIRED) @@ -97,12 +96,6 @@ set(OLP_SDK_CLIENT_HEADERS ./include/olp/core/client/TaskContext.h ) -set(OLP_SDK_GENERATED_HEADERS - ./include/olp/core/generated/parser/JsonParser.h - ./include/olp/core/generated/parser/ParserWrapper.h - ./include/olp/core/generated/serializer/SerializerWrapper.h -) - set(OLP_SDK_HTTP_HEADERS ./include/olp/core/http/adapters/HarCaptureAdapter.h ./include/olp/core/http/CertificateSettings.h @@ -229,6 +222,12 @@ set(OLP_SDK_COREAPI_HEADERS ./include/olp/core/CoreApi.h ) +set(OLP_SDK_GENERATED_HEADERS + ./src/generated/parser/JsonParser.h + ./src/generated/parser/ParserWrapper.h + ./src/generated/serializer/SerializerWrapper.h +) + set(OLP_SDK_GEO_SOURCES ./src/geo/coordinates/GeoCoordinates.cpp ./src/geo/coordinates/GeoCoordinates3d.cpp @@ -390,7 +389,6 @@ set(OLP_SDK_THREAD_SOURCES set(OLP_SDK_CORE_HEADERS ${OLP_SDK_CACHE_HEADERS} ${OLP_SDK_CLIENT_HEADERS} - ${OLP_SDK_GENERATED_HEADERS} ${OLP_SDK_HTTP_HEADERS} ${OLP_SDK_MODEL_HEADERS} ${OLP_SDK_PLATFORM_HEADERS} @@ -408,6 +406,7 @@ set(OLP_SDK_CORE_HEADERS ) set(OLP_SDK_CORE_SOURCES + ${OLP_SDK_GENERATED_HEADERS} ${OLP_SDK_CLIENT_SOURCES} ${OLP_SDK_HTTP_SOURCES} ${OLP_SDK_PLATFORM_SOURCES} @@ -466,8 +465,6 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ - $ - $) if (ANDROID) diff --git a/olp-cpp-sdk-core/include/olp/core/generated/parser/ParserWrapper.h b/olp-cpp-sdk-core/include/olp/core/generated/parser/ParserWrapper.h deleted file mode 100644 index 3cdd5e1bd..000000000 --- a/olp-cpp-sdk-core/include/olp/core/generated/parser/ParserWrapper.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2019-2023 HERE Europe B.V. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * License-Filename: LICENSE - */ - -#pragma once - -#include -#include -#include -#include - -#include -#include - -namespace olp { -namespace parser { - -inline void from_json(const rapidjson::Value& value, std::string& x) { - x = value.GetString(); -} - -inline void from_json(const rapidjson::Value& value, int32_t& x) { - x = value.GetInt(); -} - -inline void from_json(const rapidjson::Value& value, int64_t& x) { - x = value.GetInt64(); -} - -inline void from_json(const rapidjson::Value& value, double& x) { - x = value.GetDouble(); -} - -inline void from_json(const rapidjson::Value& value, bool& x) { - x = value.GetBool(); -} - -inline void from_json(const rapidjson::Value& value, - std::shared_ptr>& x) { - std::string s = value.GetString(); - x = std::make_shared>(s.begin(), s.end()); -} - -template -inline void from_json(const rapidjson::Value& value, porting::optional& x) { - T result = T(); - from_json(value, result); - x = result; -} - -template -inline void from_json(const rapidjson::Value& value, - std::map& results) { - for (rapidjson::Value::ConstMemberIterator itr = value.MemberBegin(); - itr != value.MemberEnd(); ++itr) { - std::string key; - from_json(itr->name, key); - from_json(itr->value, results[key]); - } -} - -template -inline void from_json(const rapidjson::Value& value, std::vector& results) { - for (rapidjson::Value::ConstValueIterator itr = value.Begin(); - itr != value.End(); ++itr) { - T result; - from_json(*itr, result); - results.emplace_back(std::move(result)); - } -} - -template -inline T parse(const rapidjson::Value& value, const std::string& name) { - T result = T(); - rapidjson::Value::ConstMemberIterator itr = value.FindMember(name.c_str()); - if (itr != value.MemberEnd()) { - from_json(itr->value, result); - } - return result; -} - -} // namespace parser -} // namespace olp diff --git a/olp-cpp-sdk-core/include/olp/core/generated/serializer/SerializerWrapper.h b/olp-cpp-sdk-core/include/olp/core/generated/serializer/SerializerWrapper.h deleted file mode 100644 index 62250586d..000000000 --- a/olp-cpp-sdk-core/include/olp/core/generated/serializer/SerializerWrapper.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2019-2021 HERE Europe B.V. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * License-Filename: LICENSE - */ - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include - -namespace olp { -namespace serializer { - -inline void to_json(const std::string& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetString(rapidjson::StringRef(x.c_str(), x.size()), allocator); -} - -inline void to_json(int32_t x, rapidjson::Value& value, - rapidjson::Document::AllocatorType&) { - value.SetInt(x); -} - -inline void to_json(int64_t x, rapidjson::Value& value, - rapidjson::Document::AllocatorType&) { - value.SetInt64(x); -} - -inline void to_json(double x, rapidjson::Value& value, - rapidjson::Document::AllocatorType&) { - value.SetDouble(x); -} -inline void to_json(bool x, rapidjson::Value& value, - rapidjson::Document::AllocatorType&) { - value.SetBool(x); -} - -inline void to_json(const std::shared_ptr>& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetString(reinterpret_cast(x->data()), - static_cast(x->size()), allocator); -} - -template -inline void to_json(const porting::optional& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - if (x) { - to_json(*x, value, allocator); - } else { - value.SetNull(); - } -} - -template -inline void to_json(const std::map& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetObject(); - for (auto itr = x.begin(); itr != x.end(); ++itr) { - const auto& key = itr->first; - rapidjson::Value item_value; - to_json(itr->second, item_value, allocator); - value.AddMember(rapidjson::StringRef(key.c_str(), key.size()), - std::move(item_value), allocator); - } -} - -template -inline void to_json(const std::vector& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetArray(); - for (typename std::vector::const_iterator itr = x.begin(); itr != x.end(); - ++itr) { - rapidjson::Value item_value; - to_json(*itr, item_value, allocator); - value.PushBack(std::move(item_value), allocator); - } -} - -template -inline void serialize(const std::string& key, const T& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - rapidjson::Value key_value; - to_json(key, key_value, allocator); - rapidjson::Value item_value; - to_json(x, item_value, allocator); - if (!item_value.IsNull()) { - value.AddMember(std::move(key_value), std::move(item_value), allocator); - } -} - -} // namespace serializer -} // namespace olp diff --git a/olp-cpp-sdk-core/src/client/api/JsonResultParser.h b/olp-cpp-sdk-core/src/client/api/JsonResultParser.h index c60c812f5..296c3fa7a 100644 --- a/olp-cpp-sdk-core/src/client/api/JsonResultParser.h +++ b/olp-cpp-sdk-core/src/client/api/JsonResultParser.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 HERE Europe B.V. + * Copyright (C) 2020-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,8 +23,8 @@ #include #include +#include #include -#include #include namespace olp { diff --git a/olp-cpp-sdk-core/src/client/parser/ApiParser.cpp b/olp-cpp-sdk-core/src/client/parser/ApiParser.cpp index 2942198b4..2c62f960e 100644 --- a/olp-cpp-sdk-core/src/client/parser/ApiParser.cpp +++ b/olp-cpp-sdk-core/src/client/parser/ApiParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 HERE Europe B.V. + * Copyright (C) 2020-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,14 @@ #include "ApiParser.h" -#include +#include +#include + +#include namespace olp { namespace parser { -void from_json(const rapidjson::Value& value, olp::client::Api& x) { +void from_json(const boost::json::value& value, olp::client::Api& x) { x.SetApi(parse(value, "api")); x.SetVersion(parse(value, "version")); x.SetBaseUrl(parse(value, "baseURL")); diff --git a/olp-cpp-sdk-core/src/client/parser/ApiParser.h b/olp-cpp-sdk-core/src/client/parser/ApiParser.h index bbed3eac7..ab61f3c2f 100644 --- a/olp-cpp-sdk-core/src/client/parser/ApiParser.h +++ b/olp-cpp-sdk-core/src/client/parser/ApiParser.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 HERE Europe B.V. + * Copyright (C) 2020-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +20,11 @@ #pragma once #include -#include +#include namespace olp { namespace parser { -void from_json(const rapidjson::Value& value, olp::client::Api& x); +void from_json(const boost::json::value& value, olp::client::Api& x); } // namespace parser } // namespace olp diff --git a/olp-cpp-sdk-core/include/olp/core/generated/parser/JsonParser.h b/olp-cpp-sdk-core/src/generated/parser/JsonParser.h similarity index 66% rename from olp-cpp-sdk-core/include/olp/core/generated/parser/JsonParser.h rename to olp-cpp-sdk-core/src/generated/parser/JsonParser.h index d5127e61e..48f30401e 100644 --- a/olp-cpp-sdk-core/include/olp/core/generated/parser/JsonParser.h +++ b/olp-cpp-sdk-core/src/generated/parser/JsonParser.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2024 HERE Europe B.V. + * Copyright (C) 2019-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,20 +24,20 @@ #include #include -#include -#include +#include #include "ParserWrapper.h" namespace olp { namespace parser { + template inline T parse(const std::string& json) { - rapidjson::Document doc; - doc.Parse(json.c_str()); + boost::json::error_code ec; + auto value = boost::json::parse(json, ec); T result{}; - if (doc.IsObject() || doc.IsArray()) { - from_json(doc, result); + if (value.is_object() || value.is_array()) { + from_json(value, result); } return result; } @@ -45,12 +45,11 @@ inline T parse(const std::string& json) { template inline T parse(std::stringstream& json_stream, bool& res) { res = false; - rapidjson::Document doc; - rapidjson::IStreamWrapper stream(json_stream); - doc.ParseStream(stream); + boost::json::error_code ec; + auto value = boost::json::parse(json_stream, ec); T result{}; - if (doc.IsObject() || doc.IsArray()) { - from_json(doc, result); + if (value.is_object() || value.is_array()) { + from_json(value, result); res = true; } return result; @@ -64,11 +63,13 @@ inline T parse(std::stringstream& json_stream) { template inline T parse(const std::shared_ptr>& json_bytes) { - rapidjson::Document doc; - doc.Parse(reinterpret_cast(json_bytes->data()), json_bytes->size()); + boost::json::string_view json(reinterpret_cast(json_bytes->data()), + json_bytes->size()); + boost::json::error_code ec; + auto value = boost::json::parse(json, ec); T result{}; - if (doc.IsObject() || doc.IsArray()) { - from_json(doc, result); + if (value.is_object() || value.is_array()) { + from_json(value, result); } return result; } diff --git a/olp-cpp-sdk-core/src/generated/parser/ParserWrapper.h b/olp-cpp-sdk-core/src/generated/parser/ParserWrapper.h new file mode 100644 index 000000000..284238474 --- /dev/null +++ b/olp-cpp-sdk-core/src/generated/parser/ParserWrapper.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019-2026 HERE Europe B.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * License-Filename: LICENSE + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace olp { +namespace parser { + +inline void from_json(const boost::json::value& value, std::string& x) { + const auto& str = value.get_string(); + x.assign(str.begin(), str.end()); +} + +inline void from_json(const boost::json::value& value, int32_t& x) { + x = static_cast(value.to_number()); +} + +inline void from_json(const boost::json::value& value, int64_t& x) { + x = value.to_number(); +} + +inline void from_json(const boost::json::value& value, double& x) { + x = value.to_number(); +} + +inline void from_json(const boost::json::value& value, bool& x) { + x = value.get_bool(); +} + +inline void from_json(const boost::json::value& value, + std::shared_ptr>& x) { + const auto& s = value.get_string(); + x = std::make_shared>(s.begin(), s.end()); +} + +template +inline void from_json(const boost::json::value& value, + porting::optional& x) { + T result = T(); + from_json(value, result); + x = result; +} + +template +inline void from_json(const boost::json::value& value, + std::map& results) { + const auto& object = value.get_object(); + for (const auto& object_value : object) { + std::string key = object_value.key(); + from_json(object_value.value(), results[key]); + } +} + +template +inline void from_json(const boost::json::value& value, + std::vector& results) { + const auto& array = value.get_array(); + for (const auto& array_value : array) { + T result; + from_json(array_value, result); + results.emplace_back(std::move(result)); + } +} + +template +inline T parse(const boost::json::value& value, const std::string& name) { + T result = T(); + const auto& object = value.get_object(); + auto itr = object.find(name); + if (itr != object.end()) { + from_json(itr->value(), result); + } + return result; +} + +} // namespace parser +} // namespace olp diff --git a/olp-cpp-sdk-core/src/generated/serializer/SerializerWrapper.h b/olp-cpp-sdk-core/src/generated/serializer/SerializerWrapper.h new file mode 100644 index 000000000..7005b9cec --- /dev/null +++ b/olp-cpp-sdk-core/src/generated/serializer/SerializerWrapper.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019-2026 HERE Europe B.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * License-Filename: LICENSE + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace olp { +namespace serializer { + +inline void to_json(const std::string& x, boost::json::value& value) { + value.emplace_string() = x; +} + +inline void to_json(int32_t x, boost::json::value& value) { + value.emplace_int64() = x; +} + +inline void to_json(int64_t x, boost::json::value& value) { + value.emplace_int64() = x; +} + +inline void to_json(double x, boost::json::value& value) { + value.emplace_double() = x; +} +inline void to_json(bool x, boost::json::value& value) { + value.emplace_bool() = x; +} + +inline void to_json(const std::shared_ptr>& x, + boost::json::value& value) { + value.emplace_string().assign(x->begin(), x->end()); +} + +template +inline void to_json(const porting::optional& x, boost::json::value& value) { + if (x) { + to_json(*x, value); + } else { + value.emplace_null(); + } +} + +template +inline void to_json(const std::map& x, + boost::json::value& value) { + auto& object = value.emplace_object(); + for (auto itr = x.begin(); itr != x.end(); ++itr) { + const auto& key = itr->first; + boost::json::value item_value; + to_json(itr->second, item_value); + object.emplace(key, std::move(item_value)); + } +} + +template +inline void to_json(const std::vector& x, boost::json::value& value) { + auto& array = value.emplace_array(); + array.reserve(x.size()); + for (typename std::vector::const_iterator itr = x.begin(); itr != x.end(); + ++itr) { + boost::json::value item_value; + to_json(*itr, item_value); + array.emplace_back(std::move(item_value)); + } +} + +template +inline void serialize(const std::string& key, const T& x, + boost::json::object& value) { + boost::json::value item_value; + to_json(x, item_value); + if (!item_value.is_null()) { + value.emplace(key, std::move(item_value)); + } +} + +} // namespace serializer +} // namespace olp diff --git a/tests/common/ReadDefaultResponses.cpp b/tests/common/ReadDefaultResponses.cpp index 39b664a09..9c6330148 100644 --- a/tests/common/ReadDefaultResponses.cpp +++ b/tests/common/ReadDefaultResponses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2024 HERE Europe B.V. + * Copyright (C) 2020-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,66 +24,58 @@ #include #include -#include -#include -#include +#include + +#include +#include namespace { void WriteSubquadsToJson( - rapidjson::Document& doc, const olp::geo::TileKey& root_tile, - const std::map& sub_quads, - rapidjson::Document::AllocatorType& allocator) { - rapidjson::Value sub_quads_value; - sub_quads_value.SetArray(); + boost::json::object& doc, const olp::geo::TileKey& root_tile, + const std::map& sub_quads) { + boost::json::array sub_quads_value; for (const auto& quad : sub_quads) { const mockserver::TileMetadata& metadata = quad.second; const auto partition = root_tile.AddedSubkey64(quad.first).ToHereTile(); - rapidjson::Value item; - item.SetObject(); - olp::serializer::serialize("subQuadKey", std::to_string(quad.first), item, - allocator); - olp::serializer::serialize("version", metadata.version, item, allocator); - olp::serializer::serialize("dataHandle", metadata.data_handle, item, - allocator); - olp::serializer::serialize("crc", metadata.crc, item, allocator); - olp::serializer::serialize("checksum", metadata.checksum, item, allocator); - olp::serializer::serialize("dataSize", metadata.data_size, item, allocator); + boost::json::object item; + olp::serializer::serialize("subQuadKey", std::to_string(quad.first), item); + olp::serializer::serialize("version", metadata.version, item); + olp::serializer::serialize("dataHandle", metadata.data_handle, item); + olp::serializer::serialize("crc", metadata.crc, item); + olp::serializer::serialize("checksum", metadata.checksum, item); + olp::serializer::serialize("dataSize", metadata.data_size, item); olp::serializer::serialize("compressedDataSize", - metadata.compressed_data_size, item, allocator); + metadata.compressed_data_size, item); - sub_quads_value.PushBack(std::move(item), allocator); + sub_quads_value.emplace_back(std::move(item)); } - doc.AddMember("subQuads", std::move(sub_quads_value), allocator); + doc.emplace("subQuads", std::move(sub_quads_value)); } void WriteParentquadsToJson( - rapidjson::Document& doc, - const std::map& parent_quads, - rapidjson::Document::AllocatorType& allocator) { - rapidjson::Value parent_quads_value; - parent_quads_value.SetArray(); + boost::json::object& doc, + const std::map& parent_quads) { + boost::json::array parent_quads_value; for (const auto& parent : parent_quads) { const auto partition = std::to_string(parent.first); const mockserver::TileMetadata& metadata = parent.second; - rapidjson::Value item; - item.SetObject(); - olp::serializer::serialize("partition", partition, item, allocator); - olp::serializer::serialize("version", metadata.version, item, allocator); - olp::serializer::serialize("dataHandle", metadata.data_handle, item, - allocator); - olp::serializer::serialize("crc", metadata.crc, item, allocator); - olp::serializer::serialize("checksum", metadata.checksum, item, allocator); - olp::serializer::serialize("dataSize", metadata.data_size, item, allocator); + boost::json::object item; + olp::serializer::serialize("partition", partition, item); + olp::serializer::serialize("version", metadata.version, item); + olp::serializer::serialize("dataHandle", metadata.data_handle, item); + olp::serializer::serialize("crc", metadata.crc, item); + olp::serializer::serialize("checksum", metadata.checksum, item); + olp::serializer::serialize("dataSize", metadata.data_size, item); olp::serializer::serialize("compressedDataSize", - metadata.compressed_data_size, item, allocator); - parent_quads_value.PushBack(std::move(item), allocator); + metadata.compressed_data_size, item); + parent_quads_value.emplace_back(std::move(item)); } - doc.AddMember("parentQuads", std::move(parent_quads_value), allocator); + doc.emplace("parentQuads", std::move(parent_quads_value)); } std::string GenerateRandomString(size_t length) { @@ -160,16 +152,11 @@ std::string ReadDefaultResponses::GenerateQuadTreeResponse( } } - rapidjson::Document doc; - auto& allocator = doc.GetAllocator(); - doc.SetObject(); - WriteSubquadsToJson(doc, root_tile, sub_quads, allocator); - WriteParentquadsToJson(doc, parent_quads, allocator); + boost::json::object doc; + WriteSubquadsToJson(doc, root_tile, sub_quads); + WriteParentquadsToJson(doc, parent_quads); - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); - doc.Accept(writer); - return buffer.GetString(); + return boost::json::serialize(doc); } QuadTreeBuilder::QuadTreeBuilder(olp::geo::TileKey root_tile, @@ -228,16 +215,11 @@ QuadTreeBuilder& QuadTreeBuilder::WithSubQuad( } std::string QuadTreeBuilder::BuildJson() const { - rapidjson::Document doc; - auto& allocator = doc.GetAllocator(); - doc.SetObject(); - WriteSubquadsToJson(doc, root_tile_, sub_quads_, allocator); - WriteParentquadsToJson(doc, parent_quads_, allocator); - - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); - doc.Accept(writer); - return buffer.GetString(); + boost::json::object doc; + WriteSubquadsToJson(doc, root_tile_, sub_quads_); + WriteParentquadsToJson(doc, parent_quads_); + + return boost::json::serialize(doc); } olp::geo::TileKey QuadTreeBuilder::Root() const { return root_tile_; } diff --git a/tests/common/WriteDefaultResponses.h b/tests/common/WriteDefaultResponses.h index 93d151389..a3bfc1b35 100644 --- a/tests/common/WriteDefaultResponses.h +++ b/tests/common/WriteDefaultResponses.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 HERE Europe B.V. + * Copyright (C) 2020-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,11 +24,8 @@ #include #include +#include #include -#include -#include -#include -#include #include "generated/model/Api.h" @@ -87,7 +84,8 @@ class DefaultResponses { static olp::dataservice::write::model::Publication GeneratePublicationResponse( const std::vector& layer_ids, - const std::vector dependencies) { + const std::vector + dependencies) { olp::dataservice::write::model::Publication publication; std::string id = "abcdefghijklmnopqrstuvwxyz0123456789-"; From 2d3e76a8a0546b477d56003c6c30d1cf0a065a39 Mon Sep 17 00:00:00 2001 From: Rustam Gamidov Date: Tue, 17 Mar 2026 14:14:02 +0200 Subject: [PATCH 2/3] Use Boost::json in mock-server-client Migrating from RapidJSON Relates-To: OCMAM-446 Signed-off-by: Rustam Gamidov --- tests/utils/mock-server-client/Client.h | 38 +++--- tests/utils/mock-server-client/Expectation.h | 113 +++++++---------- tests/utils/mock-server-client/JsonHelpers.h | 124 +++++++++---------- tests/utils/mock-server-client/Status.h | 6 +- 4 files changed, 121 insertions(+), 160 deletions(-) diff --git a/tests/utils/mock-server-client/Client.h b/tests/utils/mock-server-client/Client.h index 1787e5da1..97dae914d 100644 --- a/tests/utils/mock-server-client/Client.h +++ b/tests/utils/mock-server-client/Client.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2024 HERE Europe B.V. + * Copyright (C) 2020-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -150,17 +151,11 @@ inline void Client::Reset() { inline bool Client::RemoveMockResponse(const std::string& method_matcher, const std::string& path_matcher) { - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); + boost::json::object object; + object.emplace("method", method_matcher); + object.emplace("path", path_matcher); - writer.StartObject(); - writer.Key("method"); - writer.String(method_matcher.c_str()); - writer.Key("path"); - writer.String(path_matcher.c_str()); - writer.EndObject(); - - const auto data = std::string{buffer.GetString()}; + const auto data = boost::json::serialize(object); const auto request_body = std::make_shared>(data.begin(), data.end()); @@ -187,21 +182,16 @@ inline void Client::CreateExpectation(const Expectation& expectation) { inline bool Client::VerifySequence( const std::vector& pathes) const { - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); - - writer.StartObject(); - writer.Key("httpRequests"); - writer.StartArray(); + boost::json::array array; for (const auto& str : pathes) { - writer.StartObject(); - writer.Key("path"); - writer.String(str.c_str()); - writer.EndObject(); + boost::json::object array_value; + array_value.emplace("path", str); + array.emplace_back(std::move(array_value)); } - writer.EndArray(); - writer.EndObject(); - const auto data = std::string{buffer.GetString()}; + boost::json::object object; + object.emplace("httpRequests", std::move(array)); + + const auto data = boost::json::serialize(object); const auto request_body = std::make_shared>(data.begin(), data.end()); diff --git a/tests/utils/mock-server-client/Expectation.h b/tests/utils/mock-server-client/Expectation.h index 1df46e12e..908fe0a35 100644 --- a/tests/utils/mock-server-client/Expectation.h +++ b/tests/utils/mock-server-client/Expectation.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2024 HERE Europe B.V. + * Copyright (C) 2020-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +20,13 @@ #pragma once #include +#include #include #include +#include +#include + #include "JsonHelpers.h" namespace mockserver { @@ -67,110 +71,89 @@ struct Expectation { olp::porting::optional times = olp::porting::none; }; -void to_json(const Expectation& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator); +void to_json(const Expectation& x, boost::json::value& value); void to_json(const Expectation::QueryStringParameter& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator); -void to_json(const Expectation::RequestMatcher& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator); -void to_json(const Expectation::BinaryResponse& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator); -void to_json(const Expectation::ResponseDelay& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator); -void to_json(const Expectation::ResponseAction& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator); -void to_json(const Expectation::ResponseTimes& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator); + boost::json::value& value); +void to_json(const Expectation::RequestMatcher& x, boost::json::value& value); +void to_json(const Expectation::BinaryResponse& x, boost::json::value& value); +void to_json(const Expectation::ResponseDelay& x, boost::json::value& value); +void to_json(const Expectation::ResponseAction& x, boost::json::value& value); +void to_json(const Expectation::ResponseTimes& x, boost::json::value& value); std::string serialize(const Expectation& object); -inline void to_json(const Expectation& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetObject(); - serialize("httpRequest", x.request, value, allocator); +inline void to_json(const Expectation& x, boost::json::value& value) { + value.emplace_object(); + serialize("httpRequest", x.request, value); if (x.action != olp::porting::none) { - serialize("httpResponse", x.action, value, allocator); + serialize("httpResponse", x.action, value); } if (x.times != olp::porting::none) { - serialize("times", x.times, value, allocator); + serialize("times", x.times, value); } } inline void to_json(const Expectation::QueryStringParameter& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetObject(); - serialize("name", x.name, value, allocator); - serialize("values", x.values, value, allocator); + boost::json::value& value) { + value.emplace_object(); + serialize("name", x.name, value); + serialize("values", x.values, value); } inline void to_json(const Expectation::RequestMatcher& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetObject(); - serialize("path", x.path, value, allocator); - serialize("method", x.method, value, allocator); - serialize("queryStringParameters", x.query_string_parameters, value, - allocator); + boost::json::value& value) { + value.emplace_object(); + serialize("path", x.path, value); + serialize("method", x.method, value); + serialize("queryStringParameters", x.query_string_parameters, value); } inline void to_json(const Expectation::BinaryResponse& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetObject(); - serialize("type", x.type, value, allocator); - serialize("base64Bytes", x.base64_string, value, allocator); + boost::json::value& value) { + value.emplace_object(); + serialize("type", x.type, value); + serialize("base64Bytes", x.base64_string, value); } inline void to_json(const Expectation::ResponseDelay& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetObject(); - serialize("timeUnit", x.time_unit, value, allocator); - serialize("value", x.value, value, allocator); + boost::json::value& value) { + value.emplace_object(); + serialize("timeUnit", x.time_unit, value); + serialize("value", x.value, value); } inline void to_json(const Expectation::ResponseAction& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetObject(); - serialize("statusCode", x.status_code, value, allocator); + boost::json::value& value) { + value.emplace_object(); + serialize("statusCode", x.status_code, value); if (x.body.type() == typeid(std::string)) { - serialize("body", olp::porting::any_cast(x.body), value, - allocator); + serialize("body", olp::porting::any_cast(x.body), value); } else if (x.body.type() == typeid(Expectation::BinaryResponse)) { serialize("body", olp::porting::any_cast(x.body), - value, allocator); + value); } if (x.delay) { - serialize("delay", *x.delay, value, allocator); + serialize("delay", *x.delay, value); } } inline void to_json(const Expectation::ResponseTimes& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetObject(); - serialize("remainingTimes", x.remaining_times, value, allocator); - serialize("unlimited", x.unlimited, value, allocator); + boost::json::value& value) { + value.emplace_object(); + serialize("remainingTimes", x.remaining_times, value); + serialize("unlimited", x.unlimited, value); } inline std::string serialize(const Expectation& object) { - rapidjson::Document doc; - auto& allocator = doc.GetAllocator(); - - doc.SetObject(); - to_json(object, doc, allocator); + boost::json::value doc; + doc.emplace_object(); + to_json(object, doc); - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); - doc.Accept(writer); - return buffer.GetString(); + return boost::json::serialize(doc); }; } // namespace mockserver diff --git a/tests/utils/mock-server-client/JsonHelpers.h b/tests/utils/mock-server-client/JsonHelpers.h index fe529f536..587d0552d 100644 --- a/tests/utils/mock-server-client/JsonHelpers.h +++ b/tests/utils/mock-server-client/JsonHelpers.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 HERE Europe B.V. + * Copyright (C) 2020-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,126 +19,114 @@ #pragma once +#include +#include #include +#include +#include -#include -#include -#include -#include +#include +#include namespace mockserver { -inline void to_json(const std::string& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetString(rapidjson::StringRef(x.c_str(), x.size()), allocator); +inline void to_json(const std::string& x, boost::json::value& value) { + value.emplace_string() = x; } -inline void to_json(int32_t x, rapidjson::Value& value, - rapidjson::Document::AllocatorType&) { - value.SetInt(x); +inline void to_json(int32_t x, boost::json::value& value) { + value.emplace_int64() = x; } -inline void to_json(int64_t x, rapidjson::Value& value, - rapidjson::Document::AllocatorType&) { - value.SetInt64(x); +inline void to_json(int64_t x, boost::json::value& value) { + value.emplace_int64() = x; } -inline void to_json(double x, rapidjson::Value& value, - rapidjson::Document::AllocatorType&) { - value.SetDouble(x); +inline void to_json(double x, boost::json::value& value) { + value.emplace_double() = x; } -inline void to_json(bool x, rapidjson::Value& value, - rapidjson::Document::AllocatorType&) { - value.SetBool(x); +inline void to_json(bool x, boost::json::value& value) { + value.emplace_bool() = x; } inline void to_json(const std::shared_ptr>& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetString(reinterpret_cast(x->data()), - static_cast(x->size()), allocator); + boost::json::value& value) { + value.emplace_string() = + boost::json::string_view{reinterpret_cast(x->data()), x->size()}; } template -inline void to_json(const olp::porting::optional& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { +inline void to_json(const olp::porting::optional& x, + boost::json::value& value) { if (x) { - to_json(*x, value, allocator); + to_json(*x, value); } else { - value.SetNull(); + value.emplace_null(); } } template -inline void to_json(const std::map& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetObject(); - for (auto itr = x.begin(); itr != x.end(); ++itr) { - const auto& key = itr->first; - rapidjson::Value item_value; - to_json(itr->second, item_value, allocator); - value.AddMember(rapidjson::StringRef(key.c_str(), key.size()), - std::move(item_value), allocator); +inline void to_json(const std::map& x, + boost::json::value& value) { + auto& object = value.emplace_object(); + for (const auto& entry : x) { + boost::json::value item_value; + to_json(entry.second, item_value); + object.emplace(entry.first, std::move(item_value)); } } template -inline void to_json(const std::vector& x, rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - value.SetArray(); - for (typename std::vector::const_iterator itr = x.begin(); itr != x.end(); - ++itr) { - rapidjson::Value item_value; - to_json(*itr, item_value, allocator); - value.PushBack(std::move(item_value), allocator); +inline void to_json(const std::vector& x, boost::json::value& value) { + auto& array = value.emplace_array(); + for (const auto& entry : x) { + boost::json::value item_value; + to_json(entry, item_value); + array.emplace_back(std::move(item_value)); } } template inline void serialize(const std::string& key, const T& x, - rapidjson::Value& value, - rapidjson::Document::AllocatorType& allocator) { - rapidjson::Value key_value; - to_json(key, key_value, allocator); - rapidjson::Value item_value; - to_json(x, item_value, allocator); - if (!item_value.IsNull()) { - value.AddMember(std::move(key_value), std::move(item_value), allocator); + boost::json::value& value) { + boost::json::value item_value; + to_json(x, item_value); + if (!item_value.is_null()) { + value.emplace_object().emplace(key, std::move(item_value)); } } -inline void from_json(const rapidjson::Value& value, int32_t& x) { - x = value.GetInt(); +inline void from_json(const boost::json::value& value, int32_t& x) { + x = static_cast(value.to_number()); } template -inline void from_json(const rapidjson::Value& value, std::vector& results) { - for (rapidjson::Value::ConstValueIterator itr = value.Begin(); - itr != value.End(); ++itr) { +inline void from_json(const boost::json::value& value, + std::vector& results) { + const auto& array = value.get_array(); + for (const auto& array_value : array) { T result; - from_json(*itr, result); - results.push_back(result); + from_json(array_value, result); + results.emplace_back(std::move(result)); } } template -inline T parse(const rapidjson::Value& value, const std::string& name) { +inline T parse(const boost::json::value& value, const std::string& name) { T result = T(); - rapidjson::Value::ConstMemberIterator itr = value.FindMember(name.c_str()); - if (itr != value.MemberEnd()) { - from_json(itr->value, result); + if (auto* found_value = value.as_object().if_contains(name)) { + from_json(*found_value, result); } return result; } template inline T parse(std::stringstream& json_stream) { - rapidjson::Document doc; - rapidjson::IStreamWrapper stream(json_stream); - doc.ParseStream(stream); + boost::json::error_code ec; + auto doc = boost::json::parse(json_stream, ec); T result{}; - if (doc.IsObject() || doc.IsArray()) { + if (doc.is_object() || doc.is_array()) { from_json(doc, result); } return result; diff --git a/tests/utils/mock-server-client/Status.h b/tests/utils/mock-server-client/Status.h index 9ed0a0cf4..1715969e7 100644 --- a/tests/utils/mock-server-client/Status.h +++ b/tests/utils/mock-server-client/Status.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 HERE Europe B.V. + * Copyright (C) 2020-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,9 +31,9 @@ struct Status { Ports ports; }; -void from_json(const rapidjson::Value& value, Status& x); +void from_json(const boost::json::value& value, Status& x); -inline void from_json(const rapidjson::Value& value, Status& x) { +inline void from_json(const boost::json::value& value, Status& x) { x.ports = parse(value, "ports"); } From fe21927eff166f3b376f345f983db809119d7acb Mon Sep 17 00:00:00 2001 From: Rustam Gamidov Date: Wed, 18 Mar 2026 11:14:11 +0200 Subject: [PATCH 3/3] Use boost::json in HarCaptureAdapter Migrating from RapidJSON Relates-To: OCMAM-446 Signed-off-by: Rustam Gamidov --- .../src/http/adapters/HarCaptureAdapter.cpp | 340 ++++++++++-------- 1 file changed, 191 insertions(+), 149 deletions(-) diff --git a/olp-cpp-sdk-core/src/http/adapters/HarCaptureAdapter.cpp b/olp-cpp-sdk-core/src/http/adapters/HarCaptureAdapter.cpp index fe1939e9c..7df4d7439 100644 --- a/olp-cpp-sdk-core/src/http/adapters/HarCaptureAdapter.cpp +++ b/olp-cpp-sdk-core/src/http/adapters/HarCaptureAdapter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2025 HERE Europe B.V. + * Copyright (C) 2025-2026 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,8 +19,10 @@ #include -#include -#include +#include +#include + +#include #include #include @@ -68,56 +70,96 @@ std::string FormatTime(const std::chrono::system_clock::time_point timestamp) { return ss.str(); } -class JsonFileSerializer { - public: - explicit JsonFileSerializer(std::ofstream& file) - : out_stream_(file), writer_(out_stream_) {} +// In addition to making result easier to read formats floating point numbers +// from `1.00281E2` to `100.281` and from `0` to `0.000` +void PrettyPrint(std::ostream& os, boost::json::value const& jv, + std::string* indent = nullptr) { + const auto initial_precision{os.precision()}; + const auto initial_floatfield{os.floatfield}; + os.precision(3); + os.setf(std::ios_base::fixed, std::ios_base::floatfield); + + std::string indent_; + if (!indent) + indent = &indent_; + switch (jv.kind()) { + case boost::json::kind::object: { + os << "{\n"; + indent->append(4, ' '); + auto const& obj = jv.get_object(); + if (!obj.empty()) { + auto it = obj.begin(); + for (;;) { + os << *indent << boost::json::serialize(it->key()) << ": "; + PrettyPrint(os, it->value(), indent); + if (++it == obj.end()) + break; + os << ",\n"; + } + } + os << "\n"; + indent->resize(indent->size() - 4); + os << *indent << "}"; + break; + } - void Object(const std::function& body) { - writer_.StartObject(); - body(); - writer_.EndObject(); - } + case boost::json::kind::array: { + auto const& arr = jv.get_array(); + if (arr.empty()) { + os << "[]"; + } else { + os << "[\n"; + indent->append(4, ' '); + auto it = arr.begin(); + for (;;) { + os << *indent; + PrettyPrint(os, *it, indent); + if (++it == arr.end()) + break; + os << ",\n"; + } + os << "\n"; + indent->resize(indent->size() - 4); + os << *indent << "]"; + } + break; + } - void Object(const char* key, const std::function& body) { - writer_.Key(key); - writer_.StartObject(); - body(); - writer_.EndObject(); - } + case boost::json::kind::string: { + os << boost::json::serialize(jv.get_string()); + break; + } - void Array(const char* key, const std::function& body) { - writer_.Key(key); - writer_.StartArray(); - body(); - writer_.EndArray(); - } + case boost::json::kind::uint64: + os << jv.get_uint64(); + break; - void String(const char* key, const std::string& value) { - writer_.Key(key); - writer_.String(value.c_str(), value.size()); - } + case boost::json::kind::int64: + os << jv.get_int64(); + break; - void Int(const char* key, const int value) { - writer_.Key(key); - writer_.Int(value); - } + case boost::json::kind::double_: + os << jv.get_double(); + break; - void Double(const char* key, const double value) { - writer_.Key(key); - writer_.Double(value); - } + case boost::json::kind::bool_: + if (jv.get_bool()) + os << "true"; + else + os << "false"; + break; - void EmptyArray(const char* key) { - writer_.Key(key); - writer_.StartArray(); - writer_.EndArray(); + case boost::json::kind::null: + os << "null"; + break; } - private: - rapidjson::OStreamWrapper out_stream_; - rapidjson::PrettyWriter writer_{}; -}; + if (indent->empty()) + os << "\n"; + + os.precision(initial_precision); + os.setf(std::ios_base::fixed, initial_floatfield); +} } // namespace @@ -229,6 +271,110 @@ class HarCaptureAdapter::HarCaptureAdapterImpl final : public Network { } void SaveSessionToFile() const { + boost::json::object log; + log["version"] = "1.2"; + log["creator"] = boost::json::object( + {{"name", "DataSDK"}, {"version", OLP_SDK_VERSION_STRING}}); + + log["entries"] = [&]() { + boost::json::array entries; + entries.reserve(requests_.size()); + for (auto request_index = 0u; request_index < requests_.size(); + ++request_index) { + const auto& request = requests_[request_index]; + const auto diagnostics = diagnostics_.size() > request_index + ? diagnostics_[request_index] + : Diagnostics{}; + + // return duration in milliseconds as float + auto duration = [&](const Diagnostics::Timings timing, + const double default_value = -1.0) { + return diagnostics.available_timings[timing] + ? diagnostics.timings[timing].count() / 1000.0 + : default_value; + }; + + const double total_time = + duration(Diagnostics::Total, + static_cast( + std::chrono::duration_cast( + request.end_time - request.start_time) + .count()) / + 1000.0); + + auto output_headers = [&](const uint16_t headers_offset, + const uint16_t headers_count) { + boost::json::array headers; + headers.reserve(headers_count); + for (auto i = 0u; i < headers_count; ++i) { + const auto& header = headers_[headers_offset + i]; + headers.emplace_back( + boost::json::object({{"name", cache_.at(header.first)}, + {"value", cache_.at(header.second)}})); + } + return headers; + }; + + boost::json::object entry; + entry["startedDateTime"] = FormatTime(request.start_time); + entry["time"] = total_time; + + entry.emplace("request", [&]() { + boost::json::object value; + + value["method"] = VerbToString( + static_cast(request.method)); + value["url"] = cache_.at(request.url); + value["httpVersion"] = "UNSPECIFIED"; + value["cookies"] = boost::json::array{}; + value["headers"] = output_headers(request.request_headers_offset, + request.request_headers_count); + value["queryString"] = boost::json::array{}; + value["headersSize"] = -1; + value["bodySize"] = -1; + + return value; + }()); + + entry.emplace("response", [&]() { + boost::json::object value; + value["status"] = request.status_code; + value["statusText"] = ""; + value["httpVersion"] = "UNSPECIFIED"; + value["cookies"] = boost::json::array{}; + value["headers"] = output_headers(request.response_headers_offset, + request.response_headers_count); + value["content"] = + boost::json::object({{"size", 0}, {"mimeType", ""}}); + value["redirectURL"] = ""; + value["headersSize"] = -1; + value["bodySize"] = -1; + value["_transferSize"] = static_cast(request.transfer_size); + return value; + }()); + + entry.emplace("timings", [&]() { + using Timings = Diagnostics::Timings; + boost::json::object value; + value["blocked"] = duration(Timings::Queue); + value["dns"] = duration(Timings::NameLookup); + value["connect"] = duration(Timings::Connect); + value["ssl"] = duration(Timings::SSL_Handshake); + value["send"] = duration(Timings::Send, 0.0); + value["wait"] = duration(Timings::Wait, 0.0); + value["receive"] = duration(Timings::Receive, total_time); + return value; + }()); + + entries.emplace_back(std::move(entry)); + } + + return entries; + }(); + + boost::json::object doc; + doc.emplace("log", std::move(log)); + std::ofstream file(har_out_path_); if (!file.is_open()) { OLP_SDK_LOG_ERROR("HarCaptureAdapter::SaveSession", @@ -236,111 +382,7 @@ class HarCaptureAdapter::HarCaptureAdapterImpl final : public Network { return; } - JsonFileSerializer serializer{file}; - - serializer.Object([&] { - serializer.Object("log", [&] { - serializer.String("version", "1.2"); - - serializer.Object("creator", [&] { - serializer.String("name", "DataSDK"); - serializer.String("version", OLP_SDK_VERSION_STRING); - }); - - serializer.Array("entries", [&] { - for (auto request_index = 0u; request_index < requests_.size(); - ++request_index) { - const auto& request = requests_[request_index]; - const auto diagnostics = diagnostics_.size() > request_index - ? diagnostics_[request_index] - : Diagnostics{}; - - // return duration in milliseconds as float - auto duration = [&](const Diagnostics::Timings timing, - const double default_value = -1.0) { - return diagnostics.available_timings[timing] - ? diagnostics.timings[timing].count() / 1000.0 - : default_value; - }; - - const double total_time = duration( - Diagnostics::Total, - static_cast( - std::chrono::duration_cast( - request.end_time - request.start_time) - .count()) / - 1000.0); - - auto output_headers = [&](const uint16_t headers_offset, - const uint16_t headers_count) { - serializer.Array("headers", [&] { - for (auto i = 0u; i < headers_count; ++i) { - serializer.Object([&] { - auto header = headers_[headers_offset + i]; - serializer.String("name", cache_.at(header.first)); - serializer.String("value", cache_.at(header.second)); - }); - } - }); - }; - - serializer.Object([&] { - serializer.String("startedDateTime", - FormatTime(request.start_time)); - serializer.Double("time", total_time); - - serializer.Object("request", [&] { - serializer.String( - "method", - VerbToString( - static_cast(request.method))); - serializer.String("url", cache_.at(request.url)); - serializer.String("httpVersion", "UNSPECIFIED"); - serializer.EmptyArray("cookies"); - output_headers(request.request_headers_offset, - request.request_headers_count); - serializer.EmptyArray("queryString"); - serializer.Int("headersSize", -1); - serializer.Int("bodySize", -1); - }); - - // response - serializer.Object("response", [&] { - serializer.Int("status", request.status_code); - serializer.String("statusText", ""); - serializer.String("httpVersion", "UNSPECIFIED"); - serializer.EmptyArray("cookies"); - output_headers(request.response_headers_offset, - request.response_headers_count); - serializer.Object("content", [&] { - serializer.Int("size", 0); - serializer.String("mimeType", ""); - }); - serializer.String("redirectURL", ""); - serializer.Int("headersSize", -1); - serializer.Int("bodySize", -1); - serializer.Int("_transferSize", - static_cast(request.transfer_size)); - }); - - // timings - serializer.Object("timings", [&] { - using Timings = Diagnostics::Timings; - serializer.Double("blocked", duration(Timings::Queue)); - serializer.Double("dns", duration(Timings::NameLookup)); - serializer.Double("connect", duration(Timings::Connect)); - serializer.Double("ssl", duration(Timings::SSL_Handshake)); - serializer.Double("send", duration(Timings::Send, 0.0)); - serializer.Double("wait", duration(Timings::Wait, 0.0)); - serializer.Double("receive", - duration(Timings::Receive, total_time)); - }); - }); - } - }); - }); - }); - + PrettyPrint(file, doc); file.close(); OLP_SDK_LOG_INFO("HarCaptureAdapter::SaveSession",