diff --git a/srcs/EscapedString.cpp b/srcs/EscapedString.cpp new file mode 100644 index 00000000..4253d323 --- /dev/null +++ b/srcs/EscapedString.cpp @@ -0,0 +1,45 @@ +/* + * Arduino JSON library + * Benoit Blanchon 2014 - MIT License + */ + +#include "EscapedString.h" + +using namespace ArduinoJson::Internals; + +static inline char getSpecialChar(char c) +{ + // Optimized for code size on a 8-bit AVR + + const char* p = "\"\"\\\\\bb\ff\nn\rr\tt\0"; + + while (p[0] && p[0] != c) + { + p += 2; + } + + return p[1]; +} + +static inline size_t printCharTo(char c, Print& p) +{ + char specialChar = getSpecialChar(c); + + return specialChar != 0 + ? p.write('\\') + p.write(specialChar) + : p.write(c); +} + +size_t EscapedString::printTo(const char* s, Print& p) +{ + if (!s) return p.print("null"); + + size_t n = p.write('\"'); + + while (*s) + { + n += printCharTo(*s++, p); + } + + return n + p.write('\"'); +} \ No newline at end of file diff --git a/srcs/EscapedString.h b/srcs/EscapedString.h new file mode 100644 index 00000000..22db62c7 --- /dev/null +++ b/srcs/EscapedString.h @@ -0,0 +1,20 @@ +/* + * Arduino JSON library + * Benoit Blanchon 2014 - MIT License + */ + +#pragma once + +#include "Print.h" + +namespace ArduinoJson +{ + namespace Internals + { + class EscapedString + { + public: + static size_t printTo(const char*, Print&); + }; + } +} \ No newline at end of file diff --git a/srcs/JsonObject.cpp b/srcs/JsonObject.cpp index cb319791..ee323c70 100644 --- a/srcs/JsonObject.cpp +++ b/srcs/JsonObject.cpp @@ -2,6 +2,7 @@ #include // for strcmp +#include "EscapedString.h" #include "JsonBuffer.h" #include "JsonValue.h" #include "JsonNode.h" @@ -75,5 +76,28 @@ size_t JsonObject::printTo(char* buffer, size_t bufferSize) const size_t JsonObject::printTo(Print& p) const { - return p.print("{}"); + size_t n = 0; + + n += p.write('{'); + + JsonNode* firstChild = _node->content.asObject.child; + + for (JsonNode* child = firstChild; child; child = child->next) + { + const char* childKey = child->content.asKey.key; + const char* childValue = child->content.asKey.value->content.asString; + + n += EscapedString::printTo(childKey, p); + n += p.write(':'); + n += EscapedString::printTo(childValue, p); + + if (child->next) + { + n += p.write(','); + } + } + + n += p.write('}'); + + return n; } \ No newline at end of file diff --git a/srcs/srcs.vcxproj b/srcs/srcs.vcxproj index ce0737ca..b1ef050a 100644 --- a/srcs/srcs.vcxproj +++ b/srcs/srcs.vcxproj @@ -67,6 +67,7 @@ + @@ -77,6 +78,7 @@ + diff --git a/srcs/srcs.vcxproj.filters b/srcs/srcs.vcxproj.filters index 79073f13..0940e460 100644 --- a/srcs/srcs.vcxproj.filters +++ b/srcs/srcs.vcxproj.filters @@ -39,6 +39,9 @@ Header Files + + Header Files + @@ -56,5 +59,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/tests/JsonObjectSerializationTests.cpp b/tests/JsonObjectSerializationTests.cpp index 4c7bcdec..000029fd 100644 --- a/tests/JsonObjectSerializationTests.cpp +++ b/tests/JsonObjectSerializationTests.cpp @@ -1,5 +1,6 @@ #include #include +#include #include class JsonObjectSerializationTests : public testing::Test @@ -10,7 +11,7 @@ protected: object = json.createObject(); } - void jsonMustBe(const char* expected) + void outputMustBe(const char* expected) { char actual[256]; int result = object.printTo(actual, sizeof(actual)); @@ -27,5 +28,118 @@ private: TEST_F(JsonObjectSerializationTests, EmptyObject) { - jsonMustBe("{}"); -} \ No newline at end of file + outputMustBe("{}"); +} + +TEST_F(JsonObjectSerializationTests, OneString) +{ + object["key"] = "value"; + + outputMustBe("{\"key\":\"value\"}"); +} + +TEST_F(JsonObjectSerializationTests, TwoStrings) +{ + object["key1"] = "value1"; + object["key2"] = "value2"; + + outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}"); +} +/* +TEST_F(JsonObjectSerializationTests, RemoveFirst) +{ + object["key1"] = "value1"; + object["key2"] = "value2"; + object.remove("key1"); + + outputMustBe("{\"key2\":\"value2\"}"); +} + +TEST_F(JsonObjectSerializationTests, RemoveLast) +{ + object["key1"] = "value1"; + object["key2"] = "value2"; + object.remove("key2"); + + outputMustBe("{\"key1\":\"value1\"}"); +} + +TEST_F(JsonObjectSerializationTests, RemoveUnexistingKey) +{ + object["key1"] = "value1"; + object["key2"] = "value2"; + object.remove("key3"); + + outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}"); +} + +TEST_F(JsonObjectSerializationTests, ReplaceExistingKey) +{ + object["key"] = "value1"; + object["key"] = "value2"; + + outputMustBe("{\"key\":\"value2\"}"); +} + +TEST_F(JsonObjectSerializationTests, OneStringOverCapacity) +{ + object["key1"] = "value1"; + object["key2"] = "value2"; + object["key3"] = "value3"; + + outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}"); +} + +TEST_F(JsonObjectSerializationTests, OneInteger) +{ + object["key"] = 1; + outputMustBe("{\"key\":1}"); +} + +TEST_F(JsonObjectSerializationTests, OneDoubleFourDigits) +{ + object["key"].set<4>(3.14159265358979323846); + outputMustBe("{\"key\":3.1416}"); +} + +TEST_F(JsonObjectSerializationTests, OneDoubleDefaultDigits) +{ + object["key"] = 3.14159265358979323846; + outputMustBe("{\"key\":3.14}"); +} + +TEST_F(JsonObjectSerializationTests, OneNull) +{ + object["key"] = (char*) 0; + outputMustBe("{\"key\":null}"); +} + +TEST_F(JsonObjectSerializationTests, OneTrue) +{ + object["key"] = true; + outputMustBe("{\"key\":true}"); +} + +TEST_F(JsonObjectSerializationTests, OneFalse) +{ + object["key"] = false; + outputMustBe("{\"key\":false}"); +} + +TEST_F(JsonObjectSerializationTests, OneEmptyNestedArray) +{ + auto nestedArray = JsonArray<1>(); + + object["key"] = nestedArray; + + outputMustBe("{\"key\":[]}"); +} + +TEST_F(JsonObjectSerializationTests, OneEmptyNestedObject) +{ + auto nestedObject = JsonObject<1>(); + + object["key"] = nestedObject; + + outputMustBe("{\"key\":{}}"); +}*/ \ No newline at end of file