Changed JsonVariantConst::is<JsonArray/JsonObject>() to return false (closes #1412)

This commit is contained in:
Benoit Blanchon
2021-02-23 08:58:52 +01:00
parent 744d61f6fd
commit 3aab36fec2
7 changed files with 182 additions and 159 deletions

View File

@ -10,6 +10,7 @@ HEAD
* Removed `DeserializationError::NotSupported`
* Added `JsonVariant::is<JsonArrayConst/JsonObjectConst>()` (issue #1412)
* Added `JsonVariant::is<JsonVariant/JsonVariantConst>()` (issue #1412)
* Changed `JsonVariantConst::is<JsonArray/JsonObject>()` to return `false` (issue #1412)
> ### BREAKING CHANGES
>
@ -38,7 +39,10 @@ HEAD
>
> * `deserializeJson()` leaves `\uXXXX` unchanged (only when `ARDUINOJSON_DECODE_UNICODE` is `0`)
> * `deserializeMsgPack()` replaces unsupported values with `null`s
>
> Lastly, a very minor change conserns `JsonVariantConst::is<T>()`.
> It used to return `true` for `JsonArray` and `JsonOject`, but now it returns `false`.
> Instead, you must use `JsonArrayConst` and `JsonObjectConst`.
v6.17.3 (2021-02-15)
-------

View File

@ -163,9 +163,12 @@ TEST_CASE("JsonVariantConst::is<T>()") {
SECTION("undefined") {
cvariant = JsonVariantConst();
CHECK(cvariant.is<JsonObject>() == false);
CHECK(cvariant.is<JsonArray>() == false);
CHECK(cvariant.is<JsonArrayConst>() == false);
CHECK(cvariant.is<JsonObject>() == false);
CHECK(cvariant.is<JsonObjectConst>() == false);
CHECK(cvariant.is<JsonVariant>() == false);
CHECK(cvariant.is<JsonVariantConst>() == false);
CHECK(cvariant.is<bool>() == false);
CHECK(cvariant.is<char *>() == false);
CHECK(cvariant.is<int>() == false);
@ -175,9 +178,10 @@ TEST_CASE("JsonVariantConst::is<T>()") {
}
SECTION("null") {
CHECK(cvariant.is<JsonVariantConst>() == true);
CHECK(cvariant.is<JsonObject>() == false);
CHECK(cvariant.is<JsonArray>() == false);
CHECK(cvariant.is<JsonVariant>() == true);
CHECK(cvariant.is<JsonVariant>() == false);
CHECK(cvariant.is<bool>() == false);
CHECK(cvariant.is<char *>() == false);
CHECK(cvariant.is<int>() == false);
@ -190,7 +194,8 @@ TEST_CASE("JsonVariantConst::is<T>()") {
variant.set(true);
CHECK(cvariant.is<bool>() == true);
CHECK(cvariant.is<JsonVariant>() == true);
CHECK(cvariant.is<JsonVariantConst>() == true);
CHECK(cvariant.is<JsonVariant>() == false);
CHECK(cvariant.is<JsonObject>() == false);
CHECK(cvariant.is<JsonArray>() == false);
CHECK(cvariant.is<char *>() == false);
@ -204,7 +209,8 @@ TEST_CASE("JsonVariantConst::is<T>()") {
variant.set(false);
CHECK(cvariant.is<bool>() == true);
CHECK(cvariant.is<JsonVariant>() == true);
CHECK(cvariant.is<JsonVariantConst>() == true);
CHECK(cvariant.is<JsonVariant>() == false);
CHECK(cvariant.is<JsonObject>() == false);
CHECK(cvariant.is<JsonArray>() == false);
CHECK(cvariant.is<char *>() == false);
@ -223,10 +229,11 @@ TEST_CASE("JsonVariantConst::is<T>()") {
CHECK(cvariant.is<double>() == true);
CHECK(cvariant.is<float>() == true);
CHECK(cvariant.is<MYENUM2>() == true);
CHECK(cvariant.is<JsonVariant>() == true);
CHECK(cvariant.is<JsonVariantConst>() == true);
CHECK(cvariant.is<bool>() == false);
CHECK(cvariant.is<JsonObject>() == false);
CHECK(cvariant.is<JsonArray>() == false);
CHECK(cvariant.is<JsonVariant>() == false);
CHECK(cvariant.is<char *>() == false);
CHECK(cvariant.is<std::string>() == false);
}
@ -236,10 +243,11 @@ TEST_CASE("JsonVariantConst::is<T>()") {
CHECK(cvariant.is<double>() == true);
CHECK(cvariant.is<float>() == true);
CHECK(cvariant.is<JsonVariant>() == true);
CHECK(cvariant.is<JsonVariantConst>() == true);
CHECK(cvariant.is<bool>() == false);
CHECK(cvariant.is<JsonObject>() == false);
CHECK(cvariant.is<JsonArray>() == false);
CHECK(cvariant.is<JsonVariant>() == false);
CHECK(cvariant.is<char *>() == false);
CHECK(cvariant.is<int>() == false);
CHECK(cvariant.is<std::string>() == false);
@ -252,12 +260,12 @@ TEST_CASE("JsonVariantConst::is<T>()") {
CHECK(cvariant.is<char *>() == true);
CHECK(cvariant.is<const char *>() == true);
CHECK(cvariant.is<std::string>() == true);
CHECK(cvariant.is<JsonVariant>() == true);
CHECK(cvariant.is<double>() == false);
CHECK(cvariant.is<float>() == false);
CHECK(cvariant.is<bool>() == false);
CHECK(cvariant.is<JsonObject>() == false);
CHECK(cvariant.is<JsonArray>() == false);
CHECK(cvariant.is<JsonVariant>() == false);
CHECK(cvariant.is<int>() == false);
CHECK(cvariant.is<MYENUM2>() == false);
}
@ -265,9 +273,10 @@ TEST_CASE("JsonVariantConst::is<T>()") {
SECTION("JsonArray") {
variant.to<JsonArray>();
CHECK(cvariant.is<JsonArray>() == true);
CHECK(cvariant.is<JsonArrayConst>() == true);
CHECK(cvariant.is<JsonVariant>() == true);
CHECK(cvariant.is<JsonVariantConst>() == true);
CHECK(cvariant.is<JsonArray>() == false);
CHECK(cvariant.is<JsonVariant>() == false);
CHECK(cvariant.is<JsonObject>() == false);
CHECK(cvariant.is<JsonObjectConst>() == false);
CHECK(cvariant.is<int>() == false);
@ -280,9 +289,10 @@ TEST_CASE("JsonVariantConst::is<T>()") {
SECTION("JsonObject") {
variant.to<JsonObject>();
CHECK(cvariant.is<JsonObject>() == true);
CHECK(cvariant.is<JsonObjectConst>() == true);
CHECK(cvariant.is<JsonVariant>() == true);
CHECK(cvariant.is<JsonVariantConst>() == true);
CHECK(cvariant.is<JsonObject>() == false);
CHECK(cvariant.is<JsonVariant>() == false);
CHECK(cvariant.is<JsonArray>() == false);
CHECK(cvariant.is<JsonArrayConst>() == false);
CHECK(cvariant.is<int>() == false);

View File

@ -17,11 +17,11 @@ class Filter {
}
bool allowArray() const {
return _variant == true || _variant.is<ArrayRef>();
return _variant == true || _variant.is<ArrayConstRef>();
}
bool allowObject() const {
return _variant == true || _variant.is<ObjectRef>();
return _variant == true || _variant.is<ObjectConstRef>();
}
bool allowValue() const {

View File

@ -35,6 +35,11 @@ class JsonDocument : public Visitable {
_data.setNull();
}
template <typename T>
bool is() {
return getVariant().template is<T>();
}
template <typename T>
bool is() const {
return getVariant().template is<T>();

View File

@ -43,35 +43,6 @@ inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
inline int variantCompare(const VariantData *a, const VariantData *b);
inline bool variantIsArray(const VariantData *var) {
return var && var->isArray();
}
inline bool variantIsBoolean(const VariantData *var) {
return var && var->isBoolean();
}
template <typename T>
inline bool variantIsInteger(const VariantData *var) {
return var && var->isInteger<T>();
}
inline bool variantIsFloat(const VariantData *var) {
return var && var->isFloat();
}
inline bool variantIsString(const VariantData *var) {
return var && var->isString();
}
inline bool variantIsObject(const VariantData *var) {
return var && var->isObject();
}
inline bool variantIsNull(const VariantData *var) {
return var == 0 || var->isNull();
}
inline bool variantSetBoolean(VariantData *var, bool value) {
if (!var)
return false;

View File

@ -0,0 +1,146 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Variant/VariantFunctions.hpp>
namespace ARDUINOJSON_NAMESPACE {
inline bool variantIsNull(const VariantData *var) {
return var == 0 || var->isNull();
}
// bool is<char>() const;
// bool is<signed char>() const;
// bool is<signed short>() const;
// bool is<signed int>() const;
// bool is<signed long>() const;
// bool is<unsigned char>() const;
// bool is<unsigned short>() const;
// bool is<unsigned int>() const;
// bool is<unsigned long>() const;
template <typename T>
NO_INLINE typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
bool>::type
variantIs(const VariantData *var) {
return var && var->isInteger<T>();
}
// bool is<double>() const;
// bool is<float>() const;
template <typename T>
NO_INLINE typename enable_if<is_floating_point<T>::value, bool>::type variantIs(
const VariantData *var) {
return var && var->isFloat();
}
// bool is<bool>() const
template <typename T>
NO_INLINE typename enable_if<is_same<T, bool>::value, bool>::type variantIs(
const VariantData *var) {
return var && var->isBoolean();
}
// bool is<const char*>() const;
// bool is<char*>() const;
// bool is<std::string>() const;
// bool is<String>() const;
template <typename T>
NO_INLINE typename enable_if<is_same<T, const char *>::value ||
is_same<T, char *>::value ||
IsWriteableString<T>::value,
bool>::type
variantIs(const VariantData *var) {
return var && var->isString();
}
// bool is<ArrayConstRef> const;
// bool is<const ArrayConstRef> const;
template <typename T>
NO_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ArrayConstRef>::value, bool>::type
variantIs(const VariantData *var) {
return var && var->isArray();
}
// bool is<ObjectConstRef> const;
// bool is<const ObjectConstRef> const;
template <typename T>
NO_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ObjectConstRef>::value, bool>::type
variantIs(const VariantData *var) {
return var && var->isObject();
}
// bool is<VariantConstRef> const;
// bool is<const VariantConstRef> const;
template <typename T>
NO_INLINE typename enable_if<
is_same<typename remove_const<T>::type, VariantConstRef>::value, bool>::type
variantIs(const VariantData *var) {
return !!var;
}
#if ARDUINOJSON_HAS_NULLPTR
// bool is<nullptr_t> const;
template <typename T>
NO_INLINE typename enable_if<is_same<T, decltype(nullptr)>::value, bool>::type
variantIs(const VariantData *var) {
return variantIsNull(var);
}
#endif
// bool is<enum>() const;
template <typename T>
typename enable_if<is_enum<T>::value, bool>::type variantIs(
const VariantData *var) {
return variantIs<int>(var);
}
// bool is<ArrayRef> const;
// bool is<const ArrayRef> const;
template <typename T>
NO_INLINE
typename enable_if<is_same<typename remove_const<T>::type, ArrayRef>::value,
bool>::type
variantIs(VariantData *var) {
return var && var->isArray();
}
// bool is<ObjectRef> const;
// bool is<const ObjectRef> const;
template <typename T>
NO_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type
variantIs(VariantData *var) {
return var && var->isObject();
}
// bool is<VariantRef> const;
// bool is<const VariantRef> const;
template <typename T>
NO_INLINE typename enable_if<
is_same<typename remove_const<T>::type, VariantRef>::value, bool>::type
variantIs(VariantData *var) {
return !!var;
}
// bool is<ArrayRef> const;
// bool is<const ArrayRef> const;
// bool is<ObjectRef> const;
// bool is<const ObjectRef> const;
// bool is<VariantRef> const;
// bool is<const VariantRef> const;
template <typename T>
typename enable_if<
is_same<typename remove_const<T>::type, ArrayRef>::value ||
is_same<typename remove_const<T>::type, ObjectRef>::value ||
is_same<typename remove_const<T>::type, VariantRef>::value,
bool>::type
variantIs(const VariantData *) {
return false;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -13,6 +13,7 @@
#include <ArduinoJson/Strings/StringAdapters.hpp>
#include <ArduinoJson/Variant/VariantAs.hpp>
#include <ArduinoJson/Variant/VariantFunctions.hpp>
#include <ArduinoJson/Variant/VariantIs.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
#include <ArduinoJson/Variant/VariantShortcuts.hpp>
@ -28,123 +29,9 @@ class ObjectRef;
template <typename TData>
class VariantRefBase : public VariantTag {
public:
// Tells wether the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
//
// bool is<char>() const;
// bool is<signed char>() const;
// bool is<signed short>() const;
// bool is<signed int>() const;
// bool is<signed long>() const;
// bool is<unsigned char>() const;
// bool is<unsigned short>() const;
// bool is<unsigned int>() const;
// bool is<unsigned long>() const;
template <typename T>
FORCE_INLINE
typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
bool>::type
is() const {
return variantIsInteger<T>(_data);
}
//
// bool is<double>() const;
// bool is<float>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_floating_point<T>::value, bool>::type is()
const {
return variantIsFloat(_data);
}
//
// bool is<bool>() const
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, bool>::value, bool>::type is()
const {
return variantIsBoolean(_data);
}
//
// bool is<const char*>() const;
// bool is<char*>() const;
// bool is<std::string>() const;
// bool is<String>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, const char *>::value ||
is_same<T, char *>::value ||
IsWriteableString<T>::value,
bool>::type
is() const {
return variantIsString(_data);
}
//
// bool is<ArrayRef> const;
// bool is<const ArrayRef> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ArrayRef>::value, bool>::type
is() const {
return variantIsArray(_data);
}
//
// bool is<ArrayConstRef> const;
// bool is<const ArrayConstRef> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ArrayConstRef>::value, bool>::type
is() const {
return variantIsArray(_data);
}
//
// bool is<ObjectRef> const;
// bool is<const ObjectRef> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type
is() const {
return variantIsObject(_data);
}
//
// bool is<ObjectConstRef> const;
// bool is<const ObjectConstRef> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ObjectConstRef>::value,
bool>::type
is() const {
return variantIsObject(_data);
}
//
// bool is<VariantRef> const;
// bool is<const VariantRef> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, VariantRef>::value, bool>::type
is() const {
return !!_data;
}
//
// bool is<VariantConstRef> const;
// bool is<const VariantConstRef> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, VariantConstRef>::value,
bool>::type
is() const {
return !!_data;
}
#if ARDUINOJSON_HAS_NULLPTR
//
// bool is<nullptr_t> const;
template <typename T>
FORCE_INLINE
typename enable_if<is_same<T, decltype(nullptr)>::value, bool>::type
is() const {
return variantIsNull(_data);
}
#endif
// bool is<enum>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_enum<T>::value, bool>::type is() const {
return variantIsInteger<int>(_data);
FORCE_INLINE bool is() const {
return variantIs<T>(_data);
}
FORCE_INLINE bool isNull() const {