diff --git a/CHANGELOG.md b/CHANGELOG.md index e0f44148..fdd96c2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ HEAD * Added `JsonVariant::as()` as a synonym for `JsonVariant::as()` (issue #257) * Added example `JsonHttpClient` (issue #256) * Added `JsonArray::copyTo()` and `JsonArray::copyFrom()` (issue #254) +* Added `RawJson()` to insert pregenerated JSON portions (issue #259) v5.1.1 ------ diff --git a/include/ArduinoJson/JsonObject.hpp b/include/ArduinoJson/JsonObject.hpp index 9742269a..d72f5f94 100644 --- a/include/ArduinoJson/JsonObject.hpp +++ b/include/ArduinoJson/JsonObject.hpp @@ -71,6 +71,7 @@ class JsonObject : public Internals::JsonPrintable, // bool set(TKey key, float value); // bool set(TKey key, double value); // bool set(TKey key, const char* value); + // bool set(TKey key, RawJson value); template FORCE_INLINE bool set( JsonObjectKey key, T value, diff --git a/include/ArduinoJson/JsonVariant.hpp b/include/ArduinoJson/JsonVariant.hpp index dfffe3f8..512c6108 100644 --- a/include/ArduinoJson/JsonVariant.hpp +++ b/include/ArduinoJson/JsonVariant.hpp @@ -13,8 +13,8 @@ #include "Internals/JsonPrintable.hpp" #include "Internals/JsonVariantContent.hpp" #include "Internals/JsonVariantType.hpp" -#include "Internals/Unparsed.hpp" #include "JsonVariantBase.hpp" +#include "RawJson.hpp" #include "TypeTraits/EnableIf.hpp" #include "TypeTraits/IsFloatingPoint.hpp" #include "TypeTraits/IsIntegral.hpp" @@ -80,7 +80,7 @@ class JsonVariant : public JsonVariantBase { FORCE_INLINE JsonVariant(const char *value); // Create a JsonVariant containing an unparsed string - FORCE_INLINE JsonVariant(Internals::Unparsed value); + FORCE_INLINE JsonVariant(RawJson value); // Create a JsonVariant containing a reference to an array. FORCE_INLINE JsonVariant(JsonArray &array); @@ -89,6 +89,7 @@ class JsonVariant : public JsonVariantBase { FORCE_INLINE JsonVariant(JsonObject &object); // Get the variant as the specified type. + // // short as() const; // int as() const; // long as() const; @@ -97,6 +98,7 @@ class JsonVariant : public JsonVariantBase { as() const { return static_cast(asInteger()); } + // // double as() const; // float as() const; template @@ -105,6 +107,7 @@ class JsonVariant : public JsonVariantBase { as() const { return static_cast(asFloat()); } + // // const String as() const; template const typename TypeTraits::EnableIf::value, @@ -112,6 +115,7 @@ class JsonVariant : public JsonVariantBase { as() const { return toString(); } + // // const char* as() const; // const char* as() const; template @@ -121,6 +125,7 @@ class JsonVariant : public JsonVariantBase { as() const { return asString(); } + // // const bool as() const template const typename TypeTraits::EnableIf::value, @@ -128,6 +133,7 @@ class JsonVariant : public JsonVariantBase { as() const { return asInteger() != 0; } + // // JsonArray& as const; // JsonArray& as const; // JsonArray& as const; @@ -141,6 +147,7 @@ class JsonVariant : public JsonVariantBase { as() const { return asArray(); } + // // JsonObject& as const; // JsonObject& as const; // JsonObject& as const; @@ -157,8 +164,71 @@ class JsonVariant : public JsonVariantBase { // Tells weither the variant has the specified type. // Returns true if the variant has type type T, false otherwise. + // + // short as() const; + // int as() const; + // long as() const; template - bool is() const; + const typename TypeTraits::EnableIf::value, + bool>::type + is() const { + return isInteger(); + } + // + // double is() const; + // float is() const; + template + const typename TypeTraits::EnableIf::value, + bool>::type + is() const { + return isFloat(); + } + // + // const bool is() const + template + const typename TypeTraits::EnableIf::value, + bool>::type + is() const { + return isBoolean(); + } + // + // bool is() const; + // bool is() const; + template + typename TypeTraits::EnableIf::value || + TypeTraits::IsSame::value, + bool>::type + is() const { + return isString(); + } + // + // bool is const; + // bool is const; + // bool is const; + template + typename TypeTraits::EnableIf< + TypeTraits::IsSame< + typename TypeTraits::RemoveConst< + typename TypeTraits::RemoveReference::type>::type, + JsonArray>::value, + bool>::type + is() const { + return isArray(); + } + // + // JsonObject& as const; + // JsonObject& as const; + // JsonObject& as const; + template + typename TypeTraits::EnableIf< + TypeTraits::IsSame< + typename TypeTraits::RemoveConst< + typename TypeTraits::RemoveReference::type>::type, + JsonObject>::value, + bool>::type + is() const { + return isObject(); + } // Serialize the variant to a JsonWriter void writeTo(Internals::JsonWriter &writer) const; @@ -175,6 +245,12 @@ class JsonVariant : public JsonVariantBase { String toString() const; Internals::JsonFloat asFloat() const; Internals::JsonInteger asInteger() const; + bool isBoolean() const; + bool isFloat() const; + bool isInteger() const; + bool isArray() const { return _type == Internals::JSON_ARRAY; } + bool isObject() const { return _type == Internals::JSON_OBJECT; } + bool isString() const { return _type == Internals::JSON_STRING; } // The current type of the variant Internals::JsonVariantType _type; @@ -199,6 +275,7 @@ struct JsonVariant::IsConstructibleFrom { TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || + TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || diff --git a/include/ArduinoJson/JsonVariant.ipp b/include/ArduinoJson/JsonVariant.ipp index e8582007..32f9b7b9 100644 --- a/include/ArduinoJson/JsonVariant.ipp +++ b/include/ArduinoJson/JsonVariant.ipp @@ -26,7 +26,7 @@ inline JsonVariant::JsonVariant(const char *value) { _content.asString = value; } -inline JsonVariant::JsonVariant(Internals::Unparsed value) { +inline JsonVariant::JsonVariant(RawJson value) { _type = Internals::JSON_UNPARSED; _content.asString = value; } @@ -46,85 +46,6 @@ inline T JsonVariant::invalid() { return T(); } -template -inline bool JsonVariant::is() const { - return false; -} - -template <> // in .cpp -bool JsonVariant::is() const; - -template <> // in .cpp -bool JsonVariant::is() const; - -template <> // int .cpp -bool JsonVariant::is() const; - -template <> -inline bool JsonVariant::is() const { - return _type == Internals::JSON_STRING; -} - -template <> -inline bool JsonVariant::is() const { - return is(); -} - -template <> -inline bool JsonVariant::is() const { - return _type == Internals::JSON_ARRAY; -} - -template <> -inline bool JsonVariant::is() const { - return _type == Internals::JSON_ARRAY; -} - -template <> -inline bool JsonVariant::is() const { - return _type == Internals::JSON_OBJECT; -} - -template <> -inline bool JsonVariant::is() const { - return _type == Internals::JSON_OBJECT; -} - -template <> -inline bool JsonVariant::is() const { - return is(); -} - -template <> -inline bool JsonVariant::is() const { - return is(); -} - -template <> -inline bool JsonVariant::is() const { - return is(); -} - -template <> -inline bool JsonVariant::is() const { - return is(); -} - -template <> -inline bool JsonVariant::is() const { - return is(); -} - -template <> -inline bool JsonVariant::is() const { - return is(); -} - -template <> -inline bool JsonVariant::is() const { - return is(); -} - inline Internals::JsonInteger JsonVariant::asInteger() const { if (_type == Internals::JSON_INTEGER || _type == Internals::JSON_BOOLEAN) return _content.asInteger; diff --git a/include/ArduinoJson/Internals/Unparsed.hpp b/include/ArduinoJson/RawJson.hpp similarity index 67% rename from include/ArduinoJson/Internals/Unparsed.hpp rename to include/ArduinoJson/RawJson.hpp index 1063d6f0..40eae2ce 100644 --- a/include/ArduinoJson/Internals/Unparsed.hpp +++ b/include/ArduinoJson/RawJson.hpp @@ -8,14 +8,14 @@ #pragma once namespace ArduinoJson { -namespace Internals { -class Unparsed { + +// A special type of data that can be used to insert pregenerated JSON portions. +class RawJson { public: - explicit Unparsed(const char* str) : _str(str) {} + explicit RawJson(const char* str) : _str(str) {} operator const char*() const { return _str; } private: const char* _str; }; } -} diff --git a/src/Internals/JsonParser.cpp b/src/Internals/JsonParser.cpp index 32a187f9..0420d07d 100644 --- a/src/Internals/JsonParser.cpp +++ b/src/Internals/JsonParser.cpp @@ -195,7 +195,7 @@ bool JsonParser::parseStringTo(JsonVariant *destination) { if (hasQuotes) { *destination = value; } else { - *destination = Unparsed(value); + *destination = RawJson(value); } return true; } diff --git a/src/JsonVariant.cpp b/src/JsonVariant.cpp index 26f23bb7..949a0b08 100644 --- a/src/JsonVariant.cpp +++ b/src/JsonVariant.cpp @@ -47,8 +47,7 @@ String JsonVariant::toString() const { return s; } -template <> -bool JsonVariant::is() const { +bool JsonVariant::isBoolean() const { if (_type == JSON_BOOLEAN) return true; if (_type != JSON_UNPARSED || _content.asString == NULL) return false; @@ -57,8 +56,7 @@ bool JsonVariant::is() const { !strcmp(_content.asString, "false"); } -template <> -bool JsonVariant::is() const { +bool JsonVariant::isInteger() const { if (_type == JSON_INTEGER) return true; if (_type != JSON_UNPARSED || _content.asString == NULL) return false; @@ -70,8 +68,7 @@ bool JsonVariant::is() const { return *end == '\0' && errno == 0; } -template <> -bool JsonVariant::is() const { +bool JsonVariant::isFloat() const { if (_type >= JSON_FLOAT_0_DECIMALS) return true; if (_type != JSON_UNPARSED || _content.asString == NULL) return false; diff --git a/test/Issue90.cpp b/test/Issue90.cpp index a6e255e4..51845dd7 100644 --- a/test/Issue90.cpp +++ b/test/Issue90.cpp @@ -14,13 +14,11 @@ #define SUITE Issue90 -using namespace ArduinoJson::Internals; - static const char* superLong = "12345678901234567890123456789012345678901234567890123456789012345678901234" "5678901234567890123456789012345678901234567890123456789012345678901234567"; -static const JsonVariant variant = Unparsed(superLong); +static const JsonVariant variant = RawJson(superLong); TEST(SUITE, IsNotALong) { ASSERT_FALSE(variant.is()); } diff --git a/test/JsonArray_PrintTo_Tests.cpp b/test/JsonArray_PrintTo_Tests.cpp index 39cc431e..bd8e4732 100644 --- a/test/JsonArray_PrintTo_Tests.cpp +++ b/test/JsonArray_PrintTo_Tests.cpp @@ -96,6 +96,12 @@ TEST_F(JsonArray_PrintTo_Tests, TwoIntegers) { outputMustBe("[1,2]"); } +TEST_F(JsonArray_PrintTo_Tests, RawJson) { + array.add(RawJson("{\"key\":\"value\"}")); + + outputMustBe("[{\"key\":\"value\"}]"); +} + TEST_F(JsonArray_PrintTo_Tests, OneIntegerOverCapacity) { array.add(1); array.add(2); diff --git a/test/JsonObject_PrintTo_Tests.cpp b/test/JsonObject_PrintTo_Tests.cpp index f1188f51..90878982 100644 --- a/test/JsonObject_PrintTo_Tests.cpp +++ b/test/JsonObject_PrintTo_Tests.cpp @@ -8,8 +8,6 @@ #include #include -using namespace ArduinoJson::Internals; - class JsonObject_PrintTo_Tests : public testing::Test { public: JsonObject_PrintTo_Tests() : _object(_jsonBuffer.createObject()) {} @@ -75,6 +73,12 @@ TEST_F(JsonObject_PrintTo_Tests, TwoIntegers) { outputMustBe("{\"a\":1,\"b\":2}"); } +TEST_F(JsonObject_PrintTo_Tests, RawJson) { + _object["a"] = RawJson("[1,2]"); + _object.set("b", RawJson("[4,5]")); + outputMustBe("{\"a\":[1,2],\"b\":[4,5]}"); +} + TEST_F(JsonObject_PrintTo_Tests, TwoDoublesFourDigits) { _object["a"] = double_with_n_digits(3.14159265358979323846, 4); _object.set("b", 2.71828182845904523536, 4); diff --git a/test/JsonVariant_Is_Tests.cpp b/test/JsonVariant_Is_Tests.cpp index 8f9e2b91..df00b97d 100644 --- a/test/JsonVariant_Is_Tests.cpp +++ b/test/JsonVariant_Is_Tests.cpp @@ -10,8 +10,6 @@ #define SUITE JsonVariant_Is_Tests -using namespace ArduinoJson::Internals; - template void assertIsNot(TFrom value) { JsonVariant variant = value; @@ -76,37 +74,35 @@ TEST(SUITE, StringIsInt) { assertIsNot("42"); } TEST(SUITE, StringIsLong) { assertIsNot("42"); } TEST(SUITE, StringIsString) { assertIs("42"); } -TEST(SUITE, UnparsedTrueIsArra) { assertIsNot(Unparsed("true")); } -TEST(SUITE, UnparsedTrueIsBool) { assertIs(Unparsed("true")); } -TEST(SUITE, UnparsedTrueIsDouble) { assertIsNot(Unparsed("true")); } -TEST(SUITE, UnparsedTrueIsFloat) { assertIsNot(Unparsed("true")); } -TEST(SUITE, UnparsedTrueIsInt) { assertIsNot(Unparsed("true")); } -TEST(SUITE, UnparsedTrueIsLong) { assertIsNot(Unparsed("true")); } -TEST(SUITE, UnparsedTrueIsString) { - assertIsNot(Unparsed("true")); -} +TEST(SUITE, UnparsedTrueIsArra) { assertIsNot(RawJson("true")); } +TEST(SUITE, UnparsedTrueIsBool) { assertIs(RawJson("true")); } +TEST(SUITE, UnparsedTrueIsDouble) { assertIsNot(RawJson("true")); } +TEST(SUITE, UnparsedTrueIsFloat) { assertIsNot(RawJson("true")); } +TEST(SUITE, UnparsedTrueIsInt) { assertIsNot(RawJson("true")); } +TEST(SUITE, UnparsedTrueIsLong) { assertIsNot(RawJson("true")); } +TEST(SUITE, UnparsedTrueIsString) { assertIsNot(RawJson("true")); } -TEST(SUITE, UnparsedFalseIsArra) { assertIsNot(Unparsed("false")); } -TEST(SUITE, UnparsedFalseIsBool) { assertIs(Unparsed("false")); } -TEST(SUITE, UnparsedFalseIsDouble) { assertIsNot(Unparsed("false")); } -TEST(SUITE, UnparsedFalseIsFloat) { assertIsNot(Unparsed("false")); } -TEST(SUITE, UnparsedFalseIsInt) { assertIsNot(Unparsed("false")); } -TEST(SUITE, UnparsedFalseIsLong) { assertIsNot(Unparsed("false")); } +TEST(SUITE, UnparsedFalseIsArra) { assertIsNot(RawJson("false")); } +TEST(SUITE, UnparsedFalseIsBool) { assertIs(RawJson("false")); } +TEST(SUITE, UnparsedFalseIsDouble) { assertIsNot(RawJson("false")); } +TEST(SUITE, UnparsedFalseIsFloat) { assertIsNot(RawJson("false")); } +TEST(SUITE, UnparsedFalseIsInt) { assertIsNot(RawJson("false")); } +TEST(SUITE, UnparsedFalseIsLong) { assertIsNot(RawJson("false")); } TEST(SUITE, UnparsedFalseIsString) { - assertIsNot(Unparsed("false")); + assertIsNot(RawJson("false")); } -TEST(SUITE, UnparsedIntIsArra) { assertIsNot(Unparsed("42")); } -TEST(SUITE, UnparsedIntIsBool) { assertIsNot(Unparsed("42")); } -TEST(SUITE, UnparsedIntIsDouble) { assertIsNot(Unparsed("42")); } -TEST(SUITE, UnparsedIntIsFloat) { assertIsNot(Unparsed("42")); } -TEST(SUITE, UnparsedIntIsInt) { assertIs(Unparsed("42")); } -TEST(SUITE, UnparsedIntIsLong) { assertIs(Unparsed("42")); } -TEST(SUITE, UnparsedIntIsString) { assertIsNot(Unparsed("42")); } +TEST(SUITE, UnparsedIntIsArra) { assertIsNot(RawJson("42")); } +TEST(SUITE, UnparsedIntIsBool) { assertIsNot(RawJson("42")); } +TEST(SUITE, UnparsedIntIsDouble) { assertIsNot(RawJson("42")); } +TEST(SUITE, UnparsedIntIsFloat) { assertIsNot(RawJson("42")); } +TEST(SUITE, UnparsedIntIsInt) { assertIs(RawJson("42")); } +TEST(SUITE, UnparsedIntIsLong) { assertIs(RawJson("42")); } +TEST(SUITE, UnparsedIntIsString) { assertIsNot(RawJson("42")); } -TEST(SUITE, UnparsedFloatIsBool) { assertIsNot(Unparsed("4.2e-10")); } -TEST(SUITE, UnparsedFloatIsDouble) { assertIs(Unparsed("4.2e-10")); } -TEST(SUITE, UnparsedFloatIsFloat) { assertIs(Unparsed("4.2e-10")); } -TEST(SUITE, UnparsedFloatIsInt) { assertIsNot(Unparsed("4.2e-10")); } -TEST(SUITE, UnparsedFloatIsLong) { assertIsNot(Unparsed("4.2e-10")); } -TEST(SUITE, UnparsedFloatIsStr) { assertIsNot(Unparsed("4.2")); } +TEST(SUITE, UnparsedFloatIsBool) { assertIsNot(RawJson("4.2e-10")); } +TEST(SUITE, UnparsedFloatIsDouble) { assertIs(RawJson("4.2e-10")); } +TEST(SUITE, UnparsedFloatIsFloat) { assertIs(RawJson("4.2e-10")); } +TEST(SUITE, UnparsedFloatIsInt) { assertIsNot(RawJson("4.2e-10")); } +TEST(SUITE, UnparsedFloatIsLong) { assertIsNot(RawJson("4.2e-10")); } +TEST(SUITE, UnparsedFloatIsStr) { assertIsNot(RawJson("4.2")); }