diff --git a/include/aws/crt/JsonObject.h b/include/aws/crt/JsonObject.h index 87e30090c..f6be81b47 100644 --- a/include/aws/crt/JsonObject.h +++ b/include/aws/crt/JsonObject.h @@ -154,6 +154,11 @@ namespace Aws */ JsonObject &AsArray(Vector &&array); + /** + * Sets the current JSON node as null. + */ + JsonObject &AsNull(); + /** * Adds a JSON object to the top level of this node at key. * The object parameter is deep-copied. diff --git a/source/JsonObject.cpp b/source/JsonObject.cpp index e691a3adb..36c793f42 100644 --- a/source/JsonObject.cpp +++ b/source/JsonObject.cpp @@ -281,6 +281,12 @@ namespace Aws return *this; } + JsonObject &JsonObject::AsNull() + { + m_value = cJSON_CreateNull(); + return *this; + } + JsonObject &JsonObject::WithObject(const char *key, const JsonObject &value) { if (m_value == nullptr) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 13f5841bc..c8503f477 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,6 +14,9 @@ add_test_case(ClientBootstrapResourceSafety) add_test_case(TLSContextResourceSafety) add_test_case(DateTimeBinding) add_test_case(BasicJsonParsing) +add_test_case(JsonNullParsing) +add_test_case(JsonNullNestedObject) +add_test_case(JsonExplicitNull) add_test_case(SHA256ResourceSafety) add_test_case(MD5ResourceSafety) add_test_case(SHA256HMACResourceSafety) diff --git a/tests/JsonParserTest.cpp b/tests/JsonParserTest.cpp index 5989d26ef..d0923d38c 100644 --- a/tests/JsonParserTest.cpp +++ b/tests/JsonParserTest.cpp @@ -42,3 +42,75 @@ static int s_BasicJsonParsing(struct aws_allocator *allocator, void *ctx) } AWS_TEST_CASE(BasicJsonParsing, s_BasicJsonParsing) + +static int s_JsonNullParseTest(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + Aws::Crt::ApiHandle apiHandle(allocator); + + const Aws::Crt::String jsonValue = "{\"testStringKey\":null,\"testIntKey\":10," + "\"array\":[null,\"stringArrayEntry\"]," + "\"object\":{\"testObjectStringKey\":null}}"; + + Aws::Crt::JsonObject value(jsonValue); + ASSERT_TRUE(value.WasParseSuccessful()); + + auto str = value.View().WriteCompact(true); + ASSERT_STR_EQUALS(jsonValue.c_str(), str.c_str()); + str = value.View().WriteCompact(false); + ASSERT_STR_EQUALS(jsonValue.c_str(), str.c_str()); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(JsonNullParsing, s_JsonNullParseTest) + +static int s_JsonNullNestedObjectTest(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + Aws::Crt::ApiHandle apiHandle(allocator); + + const Aws::Crt::String jsonValue = "{\"testStringKey\":null,\"testIntKey\":10," + "\"array\":[null,\"stringArrayEntry\"]," + "\"object\":{\"testObjectStringKey\":null}}"; + + Aws::Crt::JsonObject value(jsonValue); + ASSERT_TRUE(value.WasParseSuccessful()); + + Aws::Crt::JsonObject doc; + doc.WithObject("null_members", jsonValue); + + const Aws::Crt::String expectedValue = "{\"null_members\":{\"testStringKey\":null,\"testIntKey\":10," + "\"array\":[null,\"stringArrayEntry\"]," + "\"object\":{\"testObjectStringKey\":null}}}"; + auto str = doc.View().WriteCompact(true); + ASSERT_STR_EQUALS(expectedValue.c_str(), str.c_str()); + str = doc.View().WriteCompact(false); + ASSERT_STR_EQUALS(expectedValue.c_str(), str.c_str()); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(JsonNullNestedObject, s_JsonNullNestedObjectTest) + +static int s_JsonExplicitNullTest(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + Aws::Crt::ApiHandle apiHandle(allocator); + + const Aws::Crt::String expectedValue = "{\"testKey\":null}"; + + Aws::Crt::JsonObject doc; + Aws::Crt::JsonObject nullObject; + nullObject.AsNull(); + doc.WithObject("testKey", nullObject); + + auto str = doc.View().WriteCompact(true); + ASSERT_STR_EQUALS(expectedValue.c_str(), str.c_str()); + str = doc.View().WriteCompact(false); + ASSERT_STR_EQUALS(expectedValue.c_str(), str.c_str()); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(JsonExplicitNull, s_JsonExplicitNullTest)