From e86c6acf2e7a8b82fef75b3eba13c0430933d859 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 17 Jul 2025 22:11:36 +0200 Subject: [PATCH] Return `bool` from all built-in `toJson` converters --- src/ArduinoJson/Document/JsonDocument.hpp | 4 +- src/ArduinoJson/MsgPack/MsgPackBinary.hpp | 74 +++++++-------- src/ArduinoJson/MsgPack/MsgPackExtension.hpp | 93 ++++++++++--------- src/ArduinoJson/Object/ObjectImpl.hpp | 3 + src/ArduinoJson/Variant/ConverterImpl.hpp | 69 +++++++------- src/ArduinoJson/Variant/JsonVariant.hpp | 8 +- src/ArduinoJson/Variant/VariantImpl.hpp | 2 +- .../Variant/VariantRefBaseImpl.hpp | 4 +- 8 files changed, 134 insertions(+), 123 deletions(-) diff --git a/src/ArduinoJson/Document/JsonDocument.hpp b/src/ArduinoJson/Document/JsonDocument.hpp index f6368e00..ced13519 100644 --- a/src/ArduinoJson/Document/JsonDocument.hpp +++ b/src/ArduinoJson/Document/JsonDocument.hpp @@ -412,8 +412,8 @@ class JsonDocument : public detail::VariantOperators { mutable detail::VariantData data_; }; -inline void convertToJson(const JsonDocument& src, JsonVariant dst) { - dst.set(src.as()); +inline bool convertToJson(const JsonDocument& src, JsonVariant dst) { + return dst.set(src.as()); } ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/src/ArduinoJson/MsgPack/MsgPackBinary.hpp b/src/ArduinoJson/MsgPack/MsgPackBinary.hpp index a6390ef8..9e40e544 100644 --- a/src/ArduinoJson/MsgPack/MsgPackBinary.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackBinary.hpp @@ -24,46 +24,46 @@ class MsgPackBinary { template <> struct Converter : private detail::VariantAttorney { - static void toJson(MsgPackBinary src, JsonVariant dst) { + static bool toJson(MsgPackBinary src, JsonVariant dst) { auto impl = getImpl(dst); - auto data = impl.data(); - if (!data) - return; + if (impl.isUnbound()) + return false; + + if (!src.data()) + return true; + + size_t headerSize = src.size() >= 0x10000 ? 5 : src.size() >= 0x100 ? 3 : 2; + auto resources = impl.resources(); - impl.clear(); - if (src.data()) { - size_t headerSize = src.size() >= 0x10000 ? 5 - : src.size() >= 0x100 ? 3 - : 2; - auto str = resources->createString(src.size() + headerSize); - if (str) { - resources->saveString(str); - auto ptr = reinterpret_cast(str->data); - switch (headerSize) { - case 2: - ptr[0] = uint8_t(0xc4); - ptr[1] = uint8_t(src.size() & 0xff); - break; - case 3: - ptr[0] = uint8_t(0xc5); - ptr[1] = uint8_t(src.size() >> 8 & 0xff); - ptr[2] = uint8_t(src.size() & 0xff); - break; - case 5: - ptr[0] = uint8_t(0xc6); - ptr[1] = uint8_t(src.size() >> 24 & 0xff); - ptr[2] = uint8_t(src.size() >> 16 & 0xff); - ptr[3] = uint8_t(src.size() >> 8 & 0xff); - ptr[4] = uint8_t(src.size() & 0xff); - break; - default: - ARDUINOJSON_ASSERT(false); - } - memcpy(ptr + headerSize, src.data(), src.size()); - data->setRawString(str); - return; - } + auto str = resources->createString(src.size() + headerSize); + if (!str) + return false; + resources->saveString(str); + + auto ptr = reinterpret_cast(str->data); + switch (headerSize) { + case 2: + ptr[0] = uint8_t(0xc4); + ptr[1] = uint8_t(src.size() & 0xff); + break; + case 3: + ptr[0] = uint8_t(0xc5); + ptr[1] = uint8_t(src.size() >> 8 & 0xff); + ptr[2] = uint8_t(src.size() & 0xff); + break; + case 5: + ptr[0] = uint8_t(0xc6); + ptr[1] = uint8_t(src.size() >> 24 & 0xff); + ptr[2] = uint8_t(src.size() >> 16 & 0xff); + ptr[3] = uint8_t(src.size() >> 8 & 0xff); + ptr[4] = uint8_t(src.size() & 0xff); + break; + default: + ARDUINOJSON_ASSERT(false); } + memcpy(ptr + headerSize, src.data(), src.size()); + impl.data()->setRawString(str); + return true; } static MsgPackBinary fromJson(JsonVariantConst src) { diff --git a/src/ArduinoJson/MsgPack/MsgPackExtension.hpp b/src/ArduinoJson/MsgPack/MsgPackExtension.hpp index 59326685..2fed46e9 100644 --- a/src/ArduinoJson/MsgPack/MsgPackExtension.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackExtension.hpp @@ -30,54 +30,57 @@ class MsgPackExtension { template <> struct Converter : private detail::VariantAttorney { - static void toJson(MsgPackExtension src, JsonVariant dst) { + static bool toJson(MsgPackExtension src, JsonVariant dst) { auto impl = getImpl(dst); - auto data = impl.data(); - auto resources = impl.resources(); - if (!data) - return; - impl.clear(); - if (src.data()) { - uint8_t format, sizeBytes; - if (src.size() >= 0x10000) { - format = 0xc9; // ext 32 - sizeBytes = 4; - } else if (src.size() >= 0x100) { - format = 0xc8; // ext 16 - sizeBytes = 2; - } else if (src.size() == 16) { - format = 0xd8; // fixext 16 - sizeBytes = 0; - } else if (src.size() == 8) { - format = 0xd7; // fixext 8 - sizeBytes = 0; - } else if (src.size() == 4) { - format = 0xd6; // fixext 4 - sizeBytes = 0; - } else if (src.size() == 2) { - format = 0xd5; // fixext 2 - sizeBytes = 0; - } else if (src.size() == 1) { - format = 0xd4; // fixext 1 - sizeBytes = 0; - } else { - format = 0xc7; // ext 8 - sizeBytes = 1; - } + if (impl.isUnbound()) + return false; - auto str = resources->createString(src.size() + 2 + sizeBytes); - if (str) { - resources->saveString(str); - auto ptr = reinterpret_cast(str->data); - *ptr++ = uint8_t(format); - for (uint8_t i = 0; i < sizeBytes; i++) - *ptr++ = uint8_t(src.size() >> (sizeBytes - i - 1) * 8 & 0xff); - *ptr++ = uint8_t(src.type()); - memcpy(ptr, src.data(), src.size()); - data->setRawString(str); - return; - } + impl.clear(); + + if (!src.data()) + return true; + + uint8_t format, sizeBytes; + if (src.size() >= 0x10000) { + format = 0xc9; // ext 32 + sizeBytes = 4; + } else if (src.size() >= 0x100) { + format = 0xc8; // ext 16 + sizeBytes = 2; + } else if (src.size() == 16) { + format = 0xd8; // fixext 16 + sizeBytes = 0; + } else if (src.size() == 8) { + format = 0xd7; // fixext 8 + sizeBytes = 0; + } else if (src.size() == 4) { + format = 0xd6; // fixext 4 + sizeBytes = 0; + } else if (src.size() == 2) { + format = 0xd5; // fixext 2 + sizeBytes = 0; + } else if (src.size() == 1) { + format = 0xd4; // fixext 1 + sizeBytes = 0; + } else { + format = 0xc7; // ext 8 + sizeBytes = 1; } + + auto resources = impl.resources(); + auto str = resources->createString(src.size() + 2 + sizeBytes); + if (!str) + return false; + resources->saveString(str); + + auto ptr = reinterpret_cast(str->data); + *ptr++ = uint8_t(format); + for (uint8_t i = 0; i < sizeBytes; i++) + *ptr++ = uint8_t(src.size() >> (sizeBytes - i - 1) * 8 & 0xff); + *ptr++ = uint8_t(src.type()); + memcpy(ptr, src.data(), src.size()); + impl.data()->setRawString(str); + return true; } static MsgPackExtension fromJson(JsonVariantConst src) { diff --git a/src/ArduinoJson/Object/ObjectImpl.hpp b/src/ArduinoJson/Object/ObjectImpl.hpp index 7a165ad6..1200bf4e 100644 --- a/src/ArduinoJson/Object/ObjectImpl.hpp +++ b/src/ArduinoJson/Object/ObjectImpl.hpp @@ -55,6 +55,9 @@ inline VariantData* VariantImpl::addMember(TAdaptedString key) { if (!isObject()) return nullptr; + if (key.isNull()) + return nullptr; // Ignore null key + auto keySlot = allocVariant(); if (!keySlot) return nullptr; diff --git a/src/ArduinoJson/Variant/ConverterImpl.hpp b/src/ArduinoJson/Variant/ConverterImpl.hpp index fc6efe9e..a8a1be65 100644 --- a/src/ArduinoJson/Variant/ConverterImpl.hpp +++ b/src/ArduinoJson/Variant/ConverterImpl.hpp @@ -25,9 +25,10 @@ struct Converter { "type 'char' is not supported, use 'signed char', 'unsigned " "char' or another integer type instead"); - static void toJson(const T& src, JsonVariant dst) { + static auto toJson(const T& src, JsonVariant dst) + -> decltype(convertToJson(src, dst)) { // clang-format off - convertToJson(src, dst); // Error here? See https://arduinojson.org/v7/unsupported-set/ + return convertToJson(src, dst); // Error here? See https://arduinojson.org/v7/unsupported-set/ // clang-format on } @@ -60,9 +61,9 @@ struct Converter::value && : private detail::VariantAttorney { static bool toJson(T src, JsonVariant dst) { ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); - auto variant = getImpl(dst); - variant.clear(); - return variant.setInteger(src); + auto impl = getImpl(dst); + impl.clear(); + return impl.setInteger(src); } static T fromJson(JsonVariantConst src) { @@ -128,10 +129,10 @@ struct Converter::value>> template <> struct Converter : private detail::VariantAttorney { - static void toJson(const char* src, JsonVariant dst) { + static bool toJson(const char* src, JsonVariant dst) { auto impl = getImpl(dst); impl.clear(); - impl.setString(detail::adaptString(src)); + return impl.setString(detail::adaptString(src)); } static const char* fromJson(JsonVariantConst src) { @@ -145,10 +146,10 @@ struct Converter : private detail::VariantAttorney { template <> struct Converter : private detail::VariantAttorney { - static void toJson(JsonString src, JsonVariant dst) { + static bool toJson(JsonString src, JsonVariant dst) { auto impl = getImpl(dst); impl.clear(); - impl.setString(detail::adaptString(src)); + return impl.setString(detail::adaptString(src)); } static JsonString fromJson(JsonVariantConst src) { @@ -161,11 +162,11 @@ struct Converter : private detail::VariantAttorney { }; template -inline detail::enable_if_t::value> convertToJson( +inline detail::enable_if_t::value, bool> convertToJson( const T& src, JsonVariant dst) { - auto variant = detail::VariantAttorney::getImpl(dst); - variant.clear(); - variant.setString(detail::adaptString(src)); + auto impl = detail::VariantAttorney::getImpl(dst); + impl.clear(); + return impl.setString(detail::adaptString(src)); } // SerializedValue @@ -174,16 +175,19 @@ inline detail::enable_if_t::value> convertToJson( template struct Converter> : private detail::VariantAttorney { static bool toJson(SerializedValue src, JsonVariant dst) { - auto variant = getImpl(dst); - variant.clear(); - return variant.setRawString(detail::adaptString(src.data(), src.size())); + auto impl = getImpl(dst); + impl.clear(); + return impl.setRawString(detail::adaptString(src.data(), src.size())); } }; template <> struct Converter : private detail::VariantAttorney { - static void toJson(detail::nullptr_t, JsonVariant dst) { + static bool toJson(detail::nullptr_t, JsonVariant dst) { + if (dst.isUnbound()) + return false; getImpl(dst).clear(); + return true; } static detail::nullptr_t fromJson(JsonVariantConst) { return nullptr; @@ -230,16 +234,17 @@ class StringBuilderPrint : public Print { }; } // namespace detail -inline void convertToJson(const ::Printable& src, JsonVariant dst) { +inline bool convertToJson(const ::Printable& src, JsonVariant dst) { auto impl = detail::VariantAttorney::getImpl(dst); if (impl.isUnbound()) - return; + return false; impl.clear(); detail::StringBuilderPrint print(impl.resources()); src.printTo(print); if (print.overflowed()) - return; + return false; print.save(impl.data()); + return true; } #endif @@ -292,11 +297,11 @@ inline bool canConvertFromJson(JsonVariantConst src, const std::string_view&) { template <> struct Converter : private detail::VariantAttorney { - static void toJson(JsonArrayConst src, JsonVariant dst) { + static bool toJson(JsonArrayConst src, JsonVariant dst) { if (src.isNull()) - dst.set(nullptr); + return dst.set(nullptr); else - dst.to().set(src); + return dst.to().set(src); } static JsonArrayConst fromJson(JsonVariantConst src) { @@ -310,11 +315,11 @@ struct Converter : private detail::VariantAttorney { template <> struct Converter : private detail::VariantAttorney { - static void toJson(JsonVariantConst src, JsonVariant dst) { + static bool toJson(JsonVariantConst src, JsonVariant dst) { if (src.isNull()) - dst.set(nullptr); + return dst.set(nullptr); else - dst.to().set(src); + return dst.to().set(src); } static JsonArray fromJson(JsonVariant src) { @@ -328,11 +333,11 @@ struct Converter : private detail::VariantAttorney { template <> struct Converter : private detail::VariantAttorney { - static void toJson(JsonVariantConst src, JsonVariant dst) { + static bool toJson(JsonVariantConst src, JsonVariant dst) { if (src.isNull()) - dst.set(nullptr); + return dst.set(nullptr); else - dst.to().set(src); + return dst.to().set(src); } static JsonObjectConst fromJson(JsonVariantConst src) { @@ -346,11 +351,11 @@ struct Converter : private detail::VariantAttorney { template <> struct Converter : private detail::VariantAttorney { - static void toJson(JsonVariantConst src, JsonVariant dst) { + static bool toJson(JsonVariantConst src, JsonVariant dst) { if (src.isNull()) - dst.set(nullptr); + return dst.set(nullptr); else - dst.to().set(src); + return dst.to().set(src); } static JsonObject fromJson(JsonVariant src) { diff --git a/src/ArduinoJson/Variant/JsonVariant.hpp b/src/ArduinoJson/Variant/JsonVariant.hpp index e8e6910a..8cb3c402 100644 --- a/src/ArduinoJson/Variant/JsonVariant.hpp +++ b/src/ArduinoJson/Variant/JsonVariant.hpp @@ -43,8 +43,8 @@ bool copyVariant(JsonVariant dst, JsonVariantConst src); template <> struct Converter : private detail::VariantAttorney { - static void toJson(JsonVariantConst src, JsonVariant dst) { - copyVariant(dst, src); + static bool toJson(JsonVariantConst src, JsonVariant dst) { + return copyVariant(dst, src); } static JsonVariant fromJson(JsonVariant src) { @@ -58,8 +58,8 @@ struct Converter : private detail::VariantAttorney { template <> struct Converter : private detail::VariantAttorney { - static void toJson(JsonVariantConst src, JsonVariant dst) { - copyVariant(dst, src); + static bool toJson(JsonVariantConst src, JsonVariant dst) { + return copyVariant(dst, src); } static JsonVariantConst fromJson(JsonVariantConst src) { diff --git a/src/ArduinoJson/Variant/VariantImpl.hpp b/src/ArduinoJson/Variant/VariantImpl.hpp index f89c933f..70268f3a 100644 --- a/src/ArduinoJson/Variant/VariantImpl.hpp +++ b/src/ArduinoJson/Variant/VariantImpl.hpp @@ -468,7 +468,7 @@ class VariantImpl { return false; if (value.isNull()) - return false; + return true; if (value.isStatic()) return setLinkedString(value.data()); diff --git a/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp b/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp index af16eed9..6a6bafdc 100644 --- a/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp +++ b/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp @@ -61,9 +61,9 @@ inline JsonObject VariantRefBase::createNestedObject( } template -inline void convertToJson(const VariantRefBase& src, +inline bool convertToJson(const VariantRefBase& src, JsonVariant dst) { - dst.set(src.template as()); + return dst.set(src.template as()); } template