Return bool from all built-in toJson converters

This commit is contained in:
Benoit Blanchon
2025-07-17 22:11:36 +02:00
parent 0021ec81d1
commit e86c6acf2e
8 changed files with 134 additions and 123 deletions

View File

@ -412,8 +412,8 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
mutable detail::VariantData data_; mutable detail::VariantData data_;
}; };
inline void convertToJson(const JsonDocument& src, JsonVariant dst) { inline bool convertToJson(const JsonDocument& src, JsonVariant dst) {
dst.set(src.as<JsonVariantConst>()); return dst.set(src.as<JsonVariantConst>());
} }
ARDUINOJSON_END_PUBLIC_NAMESPACE ARDUINOJSON_END_PUBLIC_NAMESPACE

View File

@ -24,46 +24,46 @@ class MsgPackBinary {
template <> template <>
struct Converter<MsgPackBinary> : private detail::VariantAttorney { struct Converter<MsgPackBinary> : private detail::VariantAttorney {
static void toJson(MsgPackBinary src, JsonVariant dst) { static bool toJson(MsgPackBinary src, JsonVariant dst) {
auto impl = getImpl(dst); auto impl = getImpl(dst);
auto data = impl.data(); if (impl.isUnbound())
if (!data) return false;
return;
if (!src.data())
return true;
size_t headerSize = src.size() >= 0x10000 ? 5 : src.size() >= 0x100 ? 3 : 2;
auto resources = impl.resources(); auto resources = impl.resources();
impl.clear(); auto str = resources->createString(src.size() + headerSize);
if (src.data()) { if (!str)
size_t headerSize = src.size() >= 0x10000 ? 5 return false;
: src.size() >= 0x100 ? 3 resources->saveString(str);
: 2;
auto str = resources->createString(src.size() + headerSize); auto ptr = reinterpret_cast<uint8_t*>(str->data);
if (str) { switch (headerSize) {
resources->saveString(str); case 2:
auto ptr = reinterpret_cast<uint8_t*>(str->data); ptr[0] = uint8_t(0xc4);
switch (headerSize) { ptr[1] = uint8_t(src.size() & 0xff);
case 2: break;
ptr[0] = uint8_t(0xc4); case 3:
ptr[1] = uint8_t(src.size() & 0xff); ptr[0] = uint8_t(0xc5);
break; ptr[1] = uint8_t(src.size() >> 8 & 0xff);
case 3: ptr[2] = uint8_t(src.size() & 0xff);
ptr[0] = uint8_t(0xc5); break;
ptr[1] = uint8_t(src.size() >> 8 & 0xff); case 5:
ptr[2] = uint8_t(src.size() & 0xff); ptr[0] = uint8_t(0xc6);
break; ptr[1] = uint8_t(src.size() >> 24 & 0xff);
case 5: ptr[2] = uint8_t(src.size() >> 16 & 0xff);
ptr[0] = uint8_t(0xc6); ptr[3] = uint8_t(src.size() >> 8 & 0xff);
ptr[1] = uint8_t(src.size() >> 24 & 0xff); ptr[4] = uint8_t(src.size() & 0xff);
ptr[2] = uint8_t(src.size() >> 16 & 0xff); break;
ptr[3] = uint8_t(src.size() >> 8 & 0xff); default:
ptr[4] = uint8_t(src.size() & 0xff); ARDUINOJSON_ASSERT(false);
break;
default:
ARDUINOJSON_ASSERT(false);
}
memcpy(ptr + headerSize, src.data(), src.size());
data->setRawString(str);
return;
}
} }
memcpy(ptr + headerSize, src.data(), src.size());
impl.data()->setRawString(str);
return true;
} }
static MsgPackBinary fromJson(JsonVariantConst src) { static MsgPackBinary fromJson(JsonVariantConst src) {

View File

@ -30,54 +30,57 @@ class MsgPackExtension {
template <> template <>
struct Converter<MsgPackExtension> : private detail::VariantAttorney { struct Converter<MsgPackExtension> : private detail::VariantAttorney {
static void toJson(MsgPackExtension src, JsonVariant dst) { static bool toJson(MsgPackExtension src, JsonVariant dst) {
auto impl = getImpl(dst); auto impl = getImpl(dst);
auto data = impl.data(); if (impl.isUnbound())
auto resources = impl.resources(); return false;
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;
}
auto str = resources->createString(src.size() + 2 + sizeBytes); impl.clear();
if (str) {
resources->saveString(str); if (!src.data())
auto ptr = reinterpret_cast<uint8_t*>(str->data); return true;
*ptr++ = uint8_t(format);
for (uint8_t i = 0; i < sizeBytes; i++) uint8_t format, sizeBytes;
*ptr++ = uint8_t(src.size() >> (sizeBytes - i - 1) * 8 & 0xff); if (src.size() >= 0x10000) {
*ptr++ = uint8_t(src.type()); format = 0xc9; // ext 32
memcpy(ptr, src.data(), src.size()); sizeBytes = 4;
data->setRawString(str); } else if (src.size() >= 0x100) {
return; 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<uint8_t*>(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) { static MsgPackExtension fromJson(JsonVariantConst src) {

View File

@ -55,6 +55,9 @@ inline VariantData* VariantImpl::addMember(TAdaptedString key) {
if (!isObject()) if (!isObject())
return nullptr; return nullptr;
if (key.isNull())
return nullptr; // Ignore null key
auto keySlot = allocVariant(); auto keySlot = allocVariant();
if (!keySlot) if (!keySlot)
return nullptr; return nullptr;

View File

@ -25,9 +25,10 @@ struct Converter {
"type 'char' is not supported, use 'signed char', 'unsigned " "type 'char' is not supported, use 'signed char', 'unsigned "
"char' or another integer type instead"); "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 // 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 // clang-format on
} }
@ -60,9 +61,9 @@ struct Converter<T, detail::enable_if_t<detail::is_integral<T>::value &&
: private detail::VariantAttorney { : private detail::VariantAttorney {
static bool toJson(T src, JsonVariant dst) { static bool toJson(T src, JsonVariant dst) {
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
auto variant = getImpl(dst); auto impl = getImpl(dst);
variant.clear(); impl.clear();
return variant.setInteger(src); return impl.setInteger(src);
} }
static T fromJson(JsonVariantConst src) { static T fromJson(JsonVariantConst src) {
@ -128,10 +129,10 @@ struct Converter<T, detail::enable_if_t<detail::is_floating_point<T>::value>>
template <> template <>
struct Converter<const char*> : private detail::VariantAttorney { struct Converter<const char*> : private detail::VariantAttorney {
static void toJson(const char* src, JsonVariant dst) { static bool toJson(const char* src, JsonVariant dst) {
auto impl = getImpl(dst); auto impl = getImpl(dst);
impl.clear(); impl.clear();
impl.setString(detail::adaptString(src)); return impl.setString(detail::adaptString(src));
} }
static const char* fromJson(JsonVariantConst src) { static const char* fromJson(JsonVariantConst src) {
@ -145,10 +146,10 @@ struct Converter<const char*> : private detail::VariantAttorney {
template <> template <>
struct Converter<JsonString> : private detail::VariantAttorney { struct Converter<JsonString> : private detail::VariantAttorney {
static void toJson(JsonString src, JsonVariant dst) { static bool toJson(JsonString src, JsonVariant dst) {
auto impl = getImpl(dst); auto impl = getImpl(dst);
impl.clear(); impl.clear();
impl.setString(detail::adaptString(src)); return impl.setString(detail::adaptString(src));
} }
static JsonString fromJson(JsonVariantConst src) { static JsonString fromJson(JsonVariantConst src) {
@ -161,11 +162,11 @@ struct Converter<JsonString> : private detail::VariantAttorney {
}; };
template <typename T> template <typename T>
inline detail::enable_if_t<detail::IsString<T>::value> convertToJson( inline detail::enable_if_t<detail::IsString<T>::value, bool> convertToJson(
const T& src, JsonVariant dst) { const T& src, JsonVariant dst) {
auto variant = detail::VariantAttorney::getImpl(dst); auto impl = detail::VariantAttorney::getImpl(dst);
variant.clear(); impl.clear();
variant.setString(detail::adaptString(src)); return impl.setString(detail::adaptString(src));
} }
// SerializedValue<std::string> // SerializedValue<std::string>
@ -174,16 +175,19 @@ inline detail::enable_if_t<detail::IsString<T>::value> convertToJson(
template <typename T> template <typename T>
struct Converter<SerializedValue<T>> : private detail::VariantAttorney { struct Converter<SerializedValue<T>> : private detail::VariantAttorney {
static bool toJson(SerializedValue<T> src, JsonVariant dst) { static bool toJson(SerializedValue<T> src, JsonVariant dst) {
auto variant = getImpl(dst); auto impl = getImpl(dst);
variant.clear(); impl.clear();
return variant.setRawString(detail::adaptString(src.data(), src.size())); return impl.setRawString(detail::adaptString(src.data(), src.size()));
} }
}; };
template <> template <>
struct Converter<detail::nullptr_t> : private detail::VariantAttorney { struct Converter<detail::nullptr_t> : 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(); getImpl(dst).clear();
return true;
} }
static detail::nullptr_t fromJson(JsonVariantConst) { static detail::nullptr_t fromJson(JsonVariantConst) {
return nullptr; return nullptr;
@ -230,16 +234,17 @@ class StringBuilderPrint : public Print {
}; };
} // namespace detail } // namespace detail
inline void convertToJson(const ::Printable& src, JsonVariant dst) { inline bool convertToJson(const ::Printable& src, JsonVariant dst) {
auto impl = detail::VariantAttorney::getImpl(dst); auto impl = detail::VariantAttorney::getImpl(dst);
if (impl.isUnbound()) if (impl.isUnbound())
return; return false;
impl.clear(); impl.clear();
detail::StringBuilderPrint print(impl.resources()); detail::StringBuilderPrint print(impl.resources());
src.printTo(print); src.printTo(print);
if (print.overflowed()) if (print.overflowed())
return; return false;
print.save(impl.data()); print.save(impl.data());
return true;
} }
#endif #endif
@ -292,11 +297,11 @@ inline bool canConvertFromJson(JsonVariantConst src, const std::string_view&) {
template <> template <>
struct Converter<JsonArrayConst> : private detail::VariantAttorney { struct Converter<JsonArrayConst> : private detail::VariantAttorney {
static void toJson(JsonArrayConst src, JsonVariant dst) { static bool toJson(JsonArrayConst src, JsonVariant dst) {
if (src.isNull()) if (src.isNull())
dst.set(nullptr); return dst.set(nullptr);
else else
dst.to<JsonArray>().set(src); return dst.to<JsonArray>().set(src);
} }
static JsonArrayConst fromJson(JsonVariantConst src) { static JsonArrayConst fromJson(JsonVariantConst src) {
@ -310,11 +315,11 @@ struct Converter<JsonArrayConst> : private detail::VariantAttorney {
template <> template <>
struct Converter<JsonArray> : private detail::VariantAttorney { struct Converter<JsonArray> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) { static bool toJson(JsonVariantConst src, JsonVariant dst) {
if (src.isNull()) if (src.isNull())
dst.set(nullptr); return dst.set(nullptr);
else else
dst.to<JsonArray>().set(src); return dst.to<JsonArray>().set(src);
} }
static JsonArray fromJson(JsonVariant src) { static JsonArray fromJson(JsonVariant src) {
@ -328,11 +333,11 @@ struct Converter<JsonArray> : private detail::VariantAttorney {
template <> template <>
struct Converter<JsonObjectConst> : private detail::VariantAttorney { struct Converter<JsonObjectConst> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) { static bool toJson(JsonVariantConst src, JsonVariant dst) {
if (src.isNull()) if (src.isNull())
dst.set(nullptr); return dst.set(nullptr);
else else
dst.to<JsonObject>().set(src); return dst.to<JsonObject>().set(src);
} }
static JsonObjectConst fromJson(JsonVariantConst src) { static JsonObjectConst fromJson(JsonVariantConst src) {
@ -346,11 +351,11 @@ struct Converter<JsonObjectConst> : private detail::VariantAttorney {
template <> template <>
struct Converter<JsonObject> : private detail::VariantAttorney { struct Converter<JsonObject> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) { static bool toJson(JsonVariantConst src, JsonVariant dst) {
if (src.isNull()) if (src.isNull())
dst.set(nullptr); return dst.set(nullptr);
else else
dst.to<JsonObject>().set(src); return dst.to<JsonObject>().set(src);
} }
static JsonObject fromJson(JsonVariant src) { static JsonObject fromJson(JsonVariant src) {

View File

@ -43,8 +43,8 @@ bool copyVariant(JsonVariant dst, JsonVariantConst src);
template <> template <>
struct Converter<JsonVariant> : private detail::VariantAttorney { struct Converter<JsonVariant> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) { static bool toJson(JsonVariantConst src, JsonVariant dst) {
copyVariant(dst, src); return copyVariant(dst, src);
} }
static JsonVariant fromJson(JsonVariant src) { static JsonVariant fromJson(JsonVariant src) {
@ -58,8 +58,8 @@ struct Converter<JsonVariant> : private detail::VariantAttorney {
template <> template <>
struct Converter<JsonVariantConst> : private detail::VariantAttorney { struct Converter<JsonVariantConst> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) { static bool toJson(JsonVariantConst src, JsonVariant dst) {
copyVariant(dst, src); return copyVariant(dst, src);
} }
static JsonVariantConst fromJson(JsonVariantConst src) { static JsonVariantConst fromJson(JsonVariantConst src) {

View File

@ -468,7 +468,7 @@ class VariantImpl {
return false; return false;
if (value.isNull()) if (value.isNull())
return false; return true;
if (value.isStatic()) if (value.isStatic())
return setLinkedString(value.data()); return setLinkedString(value.data());

View File

@ -61,9 +61,9 @@ inline JsonObject VariantRefBase<TDerived>::createNestedObject(
} }
template <typename TDerived> template <typename TDerived>
inline void convertToJson(const VariantRefBase<TDerived>& src, inline bool convertToJson(const VariantRefBase<TDerived>& src,
JsonVariant dst) { JsonVariant dst) {
dst.set(src.template as<JsonVariantConst>()); return dst.set(src.template as<JsonVariantConst>());
} }
template <typename TDerived> template <typename TDerived>