| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you 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. | |
| */ | |
| #include "paimon/common/utils/rapidjson_util.h" | |
| #include <algorithm> | |
| #include <map> | |
| #include <string> | |
| #include <vector> | |
| #include "gtest/gtest.h" | |
| #include "paimon/testing/utils/testharness.h" | |
| #include "rapidjson/allocators.h" | |
| #include "rapidjson/document.h" | |
| #include "rapidjson/rapidjson.h" | |
| namespace paimon::test { | |
| TEST(RapidJsonUtilTest, TestSerializeAndDeserialize) { | |
| // serialize | |
| rapidjson::Document doc; | |
| doc.SetObject(); | |
| rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); | |
| // string | |
| std::string str_value = "John"; | |
| doc.AddMember("name", RapidJsonUtil::SerializeValue(str_value, &allocator).Move(), allocator); | |
| // int | |
| int32_t int_value = 30; | |
| doc.AddMember("age", RapidJsonUtil::SerializeValue(int_value, &allocator).Move(), allocator); | |
| // vector | |
| std::vector<int> vector_value = {7, 12}; | |
| doc.AddMember("vector_value", RapidJsonUtil::SerializeValue(vector_value, &allocator).Move(), | |
| allocator); | |
| // map | |
| std::map<std::string, double> map_value = {{"a", 0.2}, {"b", 1.2}}; | |
| doc.AddMember("map_value", RapidJsonUtil::SerializeValue(map_value, &allocator).Move(), | |
| allocator); | |
| // vector of vector | |
| std::vector<std::vector<int>> vector_of_vector = {{7, 12}, {27, 45}}; | |
| doc.AddMember("vector_of_vector", | |
| RapidJsonUtil::SerializeValue(vector_of_vector, &allocator).Move(), allocator); | |
| // vector of map | |
| std::vector<std::map<std::string, double>> vector_of_map = {{{{"a", 0.2}, {"b", 1.2}}}, | |
| {{"c", 2.2}, {"d", 3.2}}}; | |
| doc.AddMember("vector_of_map", RapidJsonUtil::SerializeValue(vector_of_map, &allocator).Move(), | |
| allocator); | |
| // map of vector | |
| std::map<std::string, std::vector<int>> map_of_vector = {{"aa", {7, 12}}, {"bb", {27, 45}}}; | |
| doc.AddMember("map_of_vector", RapidJsonUtil::SerializeValue(map_of_vector, &allocator).Move(), | |
| allocator); | |
| std::optional<int64_t> null_value; | |
| doc.AddMember("null_value", RapidJsonUtil::SerializeValue(null_value, &allocator).Move(), | |
| allocator); | |
| std::optional<std::string> optional_value("abcd"); | |
| doc.AddMember("optional_value", | |
| RapidJsonUtil::SerializeValue(optional_value, &allocator).Move(), allocator); | |
| // map with int key (not string key, will convert in util) | |
| std::map<int32_t, int64_t> map_with_int_key = {{100, 1000}, {200, 2000}}; | |
| doc.AddMember("map_with_int_key", | |
| RapidJsonUtil::SerializeValue(map_with_int_key, &allocator).Move(), allocator); | |
| std::string jsonStr; | |
| ASSERT_TRUE(RapidJsonUtil::ToJson(doc, &jsonStr)); | |
| // deserialize | |
| rapidjson::Document doc2; | |
| ASSERT_TRUE(RapidJsonUtil::FromJson(jsonStr, &doc2)); | |
| ASSERT_EQ(str_value, RapidJsonUtil::DeserializeKeyValue<std::string>(doc2, "name", "")); | |
| ASSERT_EQ(int_value, RapidJsonUtil::DeserializeKeyValue<int32_t>(doc2, "age", -1)); | |
| ASSERT_EQ(vector_value, | |
| RapidJsonUtil::DeserializeKeyValue<std::vector<int>>(doc2, "vector_value", {})); | |
| auto de_map_value = | |
| RapidJsonUtil::DeserializeKeyValue<std::map<std::string, double>>(doc2, "map_value", {}); | |
| ASSERT_EQ(map_value, de_map_value); | |
| auto de_vector_of_vector = RapidJsonUtil::DeserializeKeyValue<std::vector<std::vector<int>>>( | |
| doc2, "vector_of_vector", {}); | |
| ASSERT_EQ(vector_of_vector, de_vector_of_vector); | |
| auto de_vector_of_map = | |
| RapidJsonUtil::DeserializeKeyValue<std::vector<std::map<std::string, double>>>( | |
| doc2, "vector_of_map", {}); | |
| ASSERT_EQ(vector_of_map, de_vector_of_map); | |
| auto de_map_of_vector = | |
| RapidJsonUtil::DeserializeKeyValue<std::map<std::string, std::vector<int>>>( | |
| doc2, "map_of_vector", {}); | |
| ASSERT_EQ(map_of_vector, de_map_of_vector); | |
| auto de_null_value = | |
| RapidJsonUtil::DeserializeKeyValue<std::optional<int64_t>>(doc2, "null_value"); | |
| ASSERT_EQ(null_value, de_null_value); | |
| auto de_null_value_with_default = RapidJsonUtil::DeserializeKeyValue<std::optional<int64_t>>( | |
| doc2, "null_value", /*default_value=*/std::optional<int64_t>(2333)); | |
| ASSERT_EQ(2333, de_null_value_with_default.value()); | |
| auto de_optional_value = | |
| RapidJsonUtil::DeserializeKeyValue<std::optional<std::string>>(doc2, "optional_value"); | |
| ASSERT_EQ(optional_value, de_optional_value); | |
| auto de_map_with_int_key = RapidJsonUtil::DeserializeKeyValue<std::map<int32_t, int64_t>>( | |
| doc2, "map_with_int_key", {}); | |
| ASSERT_EQ(map_with_int_key, de_map_with_int_key); | |
| // test non exist key, will use default value | |
| double non_exist_value = 0.0; | |
| non_exist_value = RapidJsonUtil::DeserializeKeyValue<double>(doc2, "non_exist_key", 2.333); | |
| ASSERT_EQ(2.333, non_exist_value); | |
| } | |
| TEST(RapidJsonUtilTest, TestMapJsonString) { | |
| std::map<std::string, std::string> m1 = {{"key1", "value1"}, {"key2", "value2"}}; | |
| std::string result; | |
| ASSERT_OK(RapidJsonUtil::ToJsonString(m1, &result)); | |
| ASSERT_EQ(result, "{\"key1\":\"value1\",\"key2\":\"value2\"}"); | |
| std::map<std::string, std::string> m2; | |
| ASSERT_OK(RapidJsonUtil::FromJsonString(result, &m2)); | |
| ASSERT_EQ(m1, m2); | |
| } | |
| } // namespace paimon::test |