diff --git a/contract-tests/client-contract-tests/src/client_entity.cpp b/contract-tests/client-contract-tests/src/client_entity.cpp index 15446bbfd..56313fc64 100644 --- a/contract-tests/client-contract-tests/src/client_entity.cpp +++ b/contract-tests/client-contract-tests/src/client_entity.cpp @@ -6,8 +6,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/contract-tests/server-contract-tests/src/client_entity.cpp b/contract-tests/server-contract-tests/src/client_entity.cpp index c8fdb40ca..4fc220307 100644 --- a/contract-tests/server-contract-tests/src/client_entity.cpp +++ b/contract-tests/server-contract-tests/src/client_entity.cpp @@ -6,8 +6,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/libs/client-sdk/src/data_sources/data_source_event_handler.cpp b/libs/client-sdk/src/data_sources/data_source_event_handler.cpp index 48283c6b2..80838cf4d 100644 --- a/libs/client-sdk/src/data_sources/data_source_event_handler.cpp +++ b/libs/client-sdk/src/data_sources/data_source_event_handler.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include diff --git a/libs/client-sdk/src/flag_manager/flag_persistence.cpp b/libs/client-sdk/src/flag_manager/flag_persistence.cpp index fe01a8929..2aa8143e1 100644 --- a/libs/client-sdk/src/flag_manager/flag_persistence.cpp +++ b/libs/client-sdk/src/flag_manager/flag_persistence.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include diff --git a/libs/common/include/launchdarkly/bindings/c/value.h b/libs/common/include/launchdarkly/bindings/c/value.h index 77459fee6..b93569836 100644 --- a/libs/common/include/launchdarkly/bindings/c/value.h +++ b/libs/common/include/launchdarkly/bindings/c/value.h @@ -191,6 +191,21 @@ LDValue_GetString(LDValue val); LD_EXPORT(unsigned int) LDValue_Count(LDValue val); +/** + * Serializes the LDValue to a JSON value. The returning string should be + * freed with @ref LDMemory_FreeString. + * + * Please note that numbers are serialized using scientific notation; + * for example the number 17 would be serialized as '1.7E1'. + * + * @param val Target LDValue. Must not be NULL. + * @return A string containing the JSON representation of the LDValue. The + * string should be freed with @ref LDMemory_FreeString. + * + */ +LD_EXPORT(char*) +LDValue_SerializeJSON(LDValue val); + /** * Obtain iterator over an array-type @ref LDValue, otherwise NULL. * diff --git a/libs/internal/include/launchdarkly/serialization/json_errors.hpp b/libs/common/include/launchdarkly/detail/serialization/json_errors.hpp similarity index 100% rename from libs/internal/include/launchdarkly/serialization/json_errors.hpp rename to libs/common/include/launchdarkly/detail/serialization/json_errors.hpp diff --git a/libs/internal/include/launchdarkly/serialization/json_primitives.hpp b/libs/common/include/launchdarkly/detail/serialization/json_primitives.hpp similarity index 98% rename from libs/internal/include/launchdarkly/serialization/json_primitives.hpp rename to libs/common/include/launchdarkly/detail/serialization/json_primitives.hpp index 268b9596a..c9d41d660 100644 --- a/libs/internal/include/launchdarkly/serialization/json_primitives.hpp +++ b/libs/common/include/launchdarkly/detail/serialization/json_primitives.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_value.hpp b/libs/common/include/launchdarkly/detail/serialization/json_value.hpp similarity index 93% rename from libs/internal/include/launchdarkly/serialization/json_value.hpp rename to libs/common/include/launchdarkly/detail/serialization/json_value.hpp index c99b1f5bb..7e9c1add7 100644 --- a/libs/internal/include/launchdarkly/serialization/json_value.hpp +++ b/libs/common/include/launchdarkly/detail/serialization/json_value.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/libs/common/src/CMakeLists.txt b/libs/common/src/CMakeLists.txt index cc5c17c98..b9a7ad287 100644 --- a/libs/common/src/CMakeLists.txt +++ b/libs/common/src/CMakeLists.txt @@ -14,6 +14,7 @@ file(GLOB HEADER_LIST CONFIGURE_DEPENDS "${LaunchDarklyCommonSdk_SOURCE_DIR}/include/launchdarkly/data/*.hpp" "${LaunchDarklyCommonSdk_SOURCE_DIR}/include/launchdarkly/logging/*.hpp" "${LaunchDarklyCommonSdk_SOURCE_DIR}/include/launchdarkly/data_sources/*.hpp" + "${LaunchDarklyCommonSdk_SOURCE_DIR}/include/launchdarkly/data_sources/persistence/*.hpp" ) # Automatic library: static or dynamic based on user config. @@ -53,6 +54,8 @@ add_library(${LIBNAME} OBJECT bindings/c/memory_routines.cpp bindings/c/data_source/error_info.cpp bindings/c/logging/log_level.cpp + serialization/json_errors.cpp + serialization/json_value.cpp log_level.cpp config/persistence_builder.cpp config/logging_builder.cpp diff --git a/libs/common/src/bindings/c/value.cpp b/libs/common/src/bindings/c/value.cpp index 484d9897f..a0373e188 100644 --- a/libs/common/src/bindings/c/value.cpp +++ b/libs/common/src/bindings/c/value.cpp @@ -7,6 +7,10 @@ #include #include +#include + +#include + using launchdarkly::Value; #define AS_VALUE(x) reinterpret_cast(x) @@ -95,6 +99,18 @@ LD_EXPORT(unsigned int) LDValue_Count(LDValue val) { } } +LD_EXPORT(char*) LDValue_SerializeJSON(LDValue val) { + LD_ASSERT_NOT_NULL(val); + + auto const value = AS_VALUE(val); + + auto boost_value = boost::json::value_from(*value); + + std::string json = boost::json::serialize(boost_value); + + return strdup(json.c_str()); +} + LD_EXPORT(LDValue_ArrayIter) LDValue_ArrayIter_New(LDValue val) { LD_ASSERT_NOT_NULL(val); diff --git a/libs/internal/src/serialization/json_errors.cpp b/libs/common/src/serialization/json_errors.cpp similarity index 96% rename from libs/internal/src/serialization/json_errors.cpp rename to libs/common/src/serialization/json_errors.cpp index c2ec4b2d3..d416dfe8c 100644 --- a/libs/internal/src/serialization/json_errors.cpp +++ b/libs/common/src/serialization/json_errors.cpp @@ -1,4 +1,4 @@ -#include +#include namespace launchdarkly { diff --git a/libs/internal/src/serialization/json_value.cpp b/libs/common/src/serialization/json_value.cpp similarity index 97% rename from libs/internal/src/serialization/json_value.cpp rename to libs/common/src/serialization/json_value.cpp index 2e0b76ca0..f0a1bb87b 100644 --- a/libs/internal/src/serialization/json_value.cpp +++ b/libs/common/src/serialization/json_value.cpp @@ -1,7 +1,8 @@ -#include #include -#include -#include +#include +#include + +#include namespace launchdarkly { // NOLINTBEGIN modernize-return-braced-init-list diff --git a/libs/common/tests/bindings/value_test.cpp b/libs/common/tests/bindings/value_test.cpp index 4deb4b065..dacb3477e 100644 --- a/libs/common/tests/bindings/value_test.cpp +++ b/libs/common/tests/bindings/value_test.cpp @@ -4,6 +4,8 @@ #include "launchdarkly/bindings/c/object_builder.h" #include "launchdarkly/bindings/c/value.h" +#include "launchdarkly/bindings/c/memory_routines.h" + TEST(ValueCBindingTests, CanCreateNull) { auto* ptr = LDValue_NewNull(); @@ -168,3 +170,56 @@ TEST(ValueCBindingTests, CanCreateObject) { LDValue_Free(val_ptr); } + +// Helper to serialize an LDValue, automatically converts to +// std::string and frees the result using LDMemory_FreeString. +std::string serialize(LDValue const val) { + char* serialized = LDValue_SerializeJSON(val); + std::string result(serialized); + LDMemory_FreeString(serialized); + return result; +} + +TEST(ValueCBindingTests, CanSerializeToJSON) { + auto* null_val = LDValue_NewNull(); + auto* bool_val_true = LDValue_NewBool(true); + auto* bool_val_false = LDValue_NewBool(false); + + auto* num_val = LDValue_NewNumber(17); + auto* float_val = LDValue_NewNumber(3.141); + auto* str_val = LDValue_NewString("Potato"); + + EXPECT_EQ("null", serialize(null_val)); + EXPECT_EQ("true", serialize(bool_val_true)); + EXPECT_EQ("false", serialize(bool_val_false)); + EXPECT_EQ("1.7E1", serialize(num_val)); + EXPECT_EQ("3.141E0", serialize(float_val)); + EXPECT_EQ("\"Potato\"", serialize(str_val)); + + // Object builder is going to take care of freeing all the primitives + // (except for bool_val_false.) + auto* object_builder = LDObjectBuilder_New(); + LDObjectBuilder_Add(object_builder, "null", null_val); + LDObjectBuilder_Add(object_builder, "bool", bool_val_true); + LDObjectBuilder_Add(object_builder, "num", num_val); + LDObjectBuilder_Add(object_builder, "float", float_val); + LDObjectBuilder_Add(object_builder, "str", str_val); + + auto* obj_ptr = LDObjectBuilder_Build(object_builder); + + EXPECT_EQ( + "{\"bool\":true,\"float\":3.141E0,\"null\":null,\"num\":1.7E1,\"str\":" + "\"Potato\"}", + serialize(obj_ptr)); + + LDValue_Free(obj_ptr); + + // Array builder is going to take care of freeing bool_val_false. + auto* array_builder = LDArrayBuilder_New(); + LDArrayBuilder_Add(array_builder, bool_val_false); + auto* array_ptr = LDArrayBuilder_Build(array_builder); + + EXPECT_EQ("[false]", serialize(array_ptr)); + + LDValue_Free(array_ptr); +} diff --git a/libs/common/tests/value_test.cpp b/libs/common/tests/value_test.cpp index f9ad35fb9..2424c8198 100644 --- a/libs/common/tests/value_test.cpp +++ b/libs/common/tests/value_test.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_context.hpp b/libs/internal/include/launchdarkly/serialization/json_context.hpp index 28c03b51c..b330a92ed 100644 --- a/libs/internal/include/launchdarkly/serialization/json_context.hpp +++ b/libs/internal/include/launchdarkly/serialization/json_context.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_context_aware_reference.hpp b/libs/internal/include/launchdarkly/serialization/json_context_aware_reference.hpp index c9eac9038..43ae3f86b 100644 --- a/libs/internal/include/launchdarkly/serialization/json_context_aware_reference.hpp +++ b/libs/internal/include/launchdarkly/serialization/json_context_aware_reference.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_context_kind.hpp b/libs/internal/include/launchdarkly/serialization/json_context_kind.hpp index 2551a65c9..c3f54a8b9 100644 --- a/libs/internal/include/launchdarkly/serialization/json_context_kind.hpp +++ b/libs/internal/include/launchdarkly/serialization/json_context_kind.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_evaluation_reason.hpp b/libs/internal/include/launchdarkly/serialization/json_evaluation_reason.hpp index deb3d9dfe..19788f17f 100644 --- a/libs/internal/include/launchdarkly/serialization/json_evaluation_reason.hpp +++ b/libs/internal/include/launchdarkly/serialization/json_evaluation_reason.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_evaluation_result.hpp b/libs/internal/include/launchdarkly/serialization/json_evaluation_result.hpp index 71f3f37c2..b88912073 100644 --- a/libs/internal/include/launchdarkly/serialization/json_evaluation_result.hpp +++ b/libs/internal/include/launchdarkly/serialization/json_evaluation_result.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_flag.hpp b/libs/internal/include/launchdarkly/serialization/json_flag.hpp index 775e2cb15..ec5a5604c 100644 --- a/libs/internal/include/launchdarkly/serialization/json_flag.hpp +++ b/libs/internal/include/launchdarkly/serialization/json_flag.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_item_descriptor.hpp b/libs/internal/include/launchdarkly/serialization/json_item_descriptor.hpp index b91eb98d5..add313b82 100644 --- a/libs/internal/include/launchdarkly/serialization/json_item_descriptor.hpp +++ b/libs/internal/include/launchdarkly/serialization/json_item_descriptor.hpp @@ -1,8 +1,8 @@ #pragma once #include -#include -#include +#include +#include #include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_rule_clause.hpp b/libs/internal/include/launchdarkly/serialization/json_rule_clause.hpp index a66d85606..cd3573653 100644 --- a/libs/internal/include/launchdarkly/serialization/json_rule_clause.hpp +++ b/libs/internal/include/launchdarkly/serialization/json_rule_clause.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_sdk_data_set.hpp b/libs/internal/include/launchdarkly/serialization/json_sdk_data_set.hpp index f2501bfa3..6e9b73c89 100644 --- a/libs/internal/include/launchdarkly/serialization/json_sdk_data_set.hpp +++ b/libs/internal/include/launchdarkly/serialization/json_sdk_data_set.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include diff --git a/libs/internal/include/launchdarkly/serialization/json_segment.hpp b/libs/internal/include/launchdarkly/serialization/json_segment.hpp index 83987903e..17695b89c 100644 --- a/libs/internal/include/launchdarkly/serialization/json_segment.hpp +++ b/libs/internal/include/launchdarkly/serialization/json_segment.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include diff --git a/libs/internal/include/launchdarkly/serialization/value_mapping.hpp b/libs/internal/include/launchdarkly/serialization/value_mapping.hpp index 9f26369b6..8bc68a5af 100644 --- a/libs/internal/include/launchdarkly/serialization/value_mapping.hpp +++ b/libs/internal/include/launchdarkly/serialization/value_mapping.hpp @@ -1,7 +1,6 @@ #pragma once -#include -#include +#include #include #include diff --git a/libs/internal/src/CMakeLists.txt b/libs/internal/src/CMakeLists.txt index af1bd209e..136f6450a 100644 --- a/libs/internal/src/CMakeLists.txt +++ b/libs/internal/src/CMakeLists.txt @@ -30,9 +30,7 @@ add_library(${LIBNAME} OBJECT serialization/events/json_events.cpp serialization/json_attributes.cpp serialization/json_context.cpp - serialization/json_errors.cpp serialization/json_evaluation_reason.cpp - serialization/json_value.cpp serialization/value_mapping.cpp serialization/json_evaluation_result.cpp serialization/json_sdk_data_set.cpp diff --git a/libs/internal/src/serialization/events/json_events.cpp b/libs/internal/src/serialization/events/json_events.cpp index 0e52228bc..1269a0bf2 100644 --- a/libs/internal/src/serialization/events/json_events.cpp +++ b/libs/internal/src/serialization/events/json_events.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include namespace launchdarkly::events { void tag_invoke(boost::json::value_from_tag const& tag, diff --git a/libs/internal/src/serialization/json_attributes.cpp b/libs/internal/src/serialization/json_attributes.cpp index f9ba610a3..cf7fb36fd 100644 --- a/libs/internal/src/serialization/json_attributes.cpp +++ b/libs/internal/src/serialization/json_attributes.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/libs/internal/src/serialization/json_context.cpp b/libs/internal/src/serialization/json_context.cpp index f61810196..c11d06d97 100644 --- a/libs/internal/src/serialization/json_context.cpp +++ b/libs/internal/src/serialization/json_context.cpp @@ -1,8 +1,8 @@ #include +#include +#include #include #include -#include -#include #include #include diff --git a/libs/internal/src/serialization/json_evaluation_reason.cpp b/libs/internal/src/serialization/json_evaluation_reason.cpp index 1ae824144..e8173e725 100644 --- a/libs/internal/src/serialization/json_evaluation_reason.cpp +++ b/libs/internal/src/serialization/json_evaluation_reason.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/libs/internal/src/serialization/json_evaluation_result.cpp b/libs/internal/src/serialization/json_evaluation_result.cpp index 6583cc70f..72fdff2bd 100644 --- a/libs/internal/src/serialization/json_evaluation_result.cpp +++ b/libs/internal/src/serialization/json_evaluation_result.cpp @@ -1,7 +1,7 @@ -#include +#include #include #include -#include +#include #include #include diff --git a/libs/internal/src/serialization/json_flag.cpp b/libs/internal/src/serialization/json_flag.cpp index f654abdbf..404ee1def 100644 --- a/libs/internal/src/serialization/json_flag.cpp +++ b/libs/internal/src/serialization/json_flag.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include namespace launchdarkly { diff --git a/libs/internal/src/serialization/json_primitives.cpp b/libs/internal/src/serialization/json_primitives.cpp index 3513ab0fc..2a882b87f 100644 --- a/libs/internal/src/serialization/json_primitives.cpp +++ b/libs/internal/src/serialization/json_primitives.cpp @@ -1,4 +1,4 @@ -#include +#include namespace launchdarkly { tl::expected, JsonError> tag_invoke( diff --git a/libs/internal/src/serialization/json_rule_clause.cpp b/libs/internal/src/serialization/json_rule_clause.cpp index febc96f28..b65e28350 100644 --- a/libs/internal/src/serialization/json_rule_clause.cpp +++ b/libs/internal/src/serialization/json_rule_clause.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include namespace launchdarkly { diff --git a/libs/internal/src/serialization/json_segment.cpp b/libs/internal/src/serialization/json_segment.cpp index 89e2de150..d62cd4b60 100644 --- a/libs/internal/src/serialization/json_segment.cpp +++ b/libs/internal/src/serialization/json_segment.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libs/internal/tests/data_model_serialization_test.cpp b/libs/internal/tests/data_model_serialization_test.cpp index 416786409..709af98f6 100644 --- a/libs/internal/tests/data_model_serialization_test.cpp +++ b/libs/internal/tests/data_model_serialization_test.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/libs/server-sdk/src/all_flags_state/json_all_flags_state.cpp b/libs/server-sdk/src/all_flags_state/json_all_flags_state.cpp index 25a095fdd..101b55bfb 100644 --- a/libs/server-sdk/src/all_flags_state/json_all_flags_state.cpp +++ b/libs/server-sdk/src/all_flags_state/json_all_flags_state.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/libs/server-sdk/src/data_systems/background_sync/sources/polling/polling_data_source.cpp b/libs/server-sdk/src/data_systems/background_sync/sources/polling/polling_data_source.cpp index 5b2b2db96..abb2a5478 100644 --- a/libs/server-sdk/src/data_systems/background_sync/sources/polling/polling_data_source.cpp +++ b/libs/server-sdk/src/data_systems/background_sync/sources/polling/polling_data_source.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include diff --git a/libs/server-sdk/src/integrations/data_reader/kinds.cpp b/libs/server-sdk/src/integrations/data_reader/kinds.cpp index 8549b63d2..f25179984 100644 --- a/libs/server-sdk/src/integrations/data_reader/kinds.cpp +++ b/libs/server-sdk/src/integrations/data_reader/kinds.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include #include