From 9d19f2a367e08b3b3ce379b41b0141d287b46f11 Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Thu, 2 May 2019 03:39:55 +0900 Subject: [PATCH] Fixed loading elements missing in loadElement. Issue #64 --- src/AutoConnectAux.cpp | 42 +++++++++++++++++++++++++++++++--------- src/AutoConnectAux.h | 36 +++++++++++++++++++++++++++++++--- src/AutoConnectAuxImpl.h | 31 ----------------------------- 3 files changed, 66 insertions(+), 43 deletions(-) diff --git a/src/AutoConnectAux.cpp b/src/AutoConnectAux.cpp index bbdb500..5449e40 100644 --- a/src/AutoConnectAux.cpp +++ b/src/AutoConnectAux.cpp @@ -673,34 +673,58 @@ bool AutoConnectAux::_load(JsonObject& jb) { * @return A reference of loaded AutoConnectElement instance. */ bool AutoConnectAux::loadElement(const String& in, const String& name) { - return _parseElement(in, name); + return _parseElement(in, name); } bool AutoConnectAux::loadElement(const __FlashStringHelper* in, const String& name) { - return _parseElement(in, name); + return _parseElement(in, name); } bool AutoConnectAux::loadElement(Stream& in, const String& name) { - return _parseElement(in, name); + return _parseElement(in, name); } -bool AutoConnectAux::_loadElement(JsonVariant& jb, const String& name) { +bool AutoConnectAux::loadElement(const String& in, std::vector const& names) { + return _parseElement const&>(in, names); +} + +bool AutoConnectAux::loadElement(const __FlashStringHelper* in, std::vector const& names) { + return _parseElement const&>(in, names); +} + +bool AutoConnectAux::loadElement(Stream& in, std::vector const& names) { + return _parseElement const&>(in, names); +} + +bool AutoConnectAux::_loadElement(JsonVariant& jb, std::vector const& names) { bool rc = true; + for (const String& name : names) + rc &= _loadElement(jb, name); + return rc; +} + +bool AutoConnectAux::_loadElement(JsonVariant& jb, const String& name) { + bool rc = false; if (jb.is()) { ArduinoJsonArray elements = jb.as(); for (ArduinoJsonObject element : elements) { + if (name.length()) { + //Finds an element with the specified name in the JSON array and loads it. + if (!name.equalsIgnoreCase(element[F(AUTOCONNECT_JSON_KEY_NAME)].as())) + continue; + } AutoConnectElement& elm = _loadElement(element, name); - if (!elm.name.length()) { - rc = false; + if (elm.name.length()) + rc = true; + if (name.length()) break; - } } } else { ArduinoJsonObject element = jb.as(); AutoConnectElement& elm = _loadElement(element, name); - if (!elm.name.length()) - rc = false; + if (elm.name.length()) + rc = true; } return rc; } diff --git a/src/AutoConnectAux.h b/src/AutoConnectAux.h index 3bd7db1..ed5e28c 100644 --- a/src/AutoConnectAux.h +++ b/src/AutoConnectAux.h @@ -75,8 +75,11 @@ class AutoConnectAux : public PageBuilder { bool load(const __FlashStringHelper* in); /**< Load whole elements to AutoConnectAux Page */ bool load(Stream& in); /**< Load whole elements to AutoConnectAux Page */ bool loadElement(const String& in, const String& name = String("")); /**< Load specified element */ - bool loadElement(const __FlashStringHelper* in, const String& name = String("")); /**< Load specified element */ + bool loadElement(const String& in, std::vector const& names = {}); /**< Load any specified elements */ + bool loadElement(const __FlashStringHelper* in, const String& name = String("")); /**< Load specified element */ + bool loadElement(const __FlashStringHelper* in, std::vector const& names = {}); /**< Load any specified elements */ bool loadElement(Stream& in, const String& name = String("")); /**< Load specified element */ + bool loadElement(Stream& in, std::vector const& names = {}); /**< Load any specified elements */ size_t saveElement(Stream& out, std::vector const& names = {}); /**< Write elements of AutoConnectAux to the stream */ #endif // !AUTOCONNECT_USE_JSON @@ -98,11 +101,38 @@ class AutoConnectAux : public PageBuilder { bool _parseJson(T in); bool _load(JsonObject& in); /**< Load all elements from JSON object */ bool _loadElement(JsonVariant& in, const String& name); /**< Load an element as specified name from JSON object */ - template - bool _parseElement(T in, const String& name); + bool _loadElement(JsonVariant& in, std::vector const& names); /**< Load any elements as specified name from JSON object */ AutoConnectElement& _loadElement(JsonObject& in, const String& name); /**< Load an element as specified name from JSON object */ AutoConnectElement* _createElement(const JsonObject& json); /**< Create an AutoConnectElement instance from JSON object */ static ACElement_t _asElementType(const String& type); /**< Convert a string of element type to the enumeration value */ + /** + * Parse and load a JSON document which declares one of the AutoConnectElement. + * The compiler instantiates this template according to the stored data type that contains the JSON document. + * This template also generates different parsing function calls depending on the ArduinoJson version. + * @param T An object type of the JSON document which must be a passable object to ArduinoJson. + * @param U An instance of a souce name to load. + */ + template::value || std::is_same const&>::value>::type* = nullptr> + bool _parseElement(T in, U name) { + ArduinoJsonBuffer jsonBuffer(AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE); + JsonVariant jb; + #if ARDUINOJSON_VERSION_MAJOR<=5 + jb = jsonBuffer.parse(in); + if (!jb.success()) { + AC_DBG("JSON parse error\n"); + return false; + } + #else + DeserializationError err = deserializeJson(jsonBuffer, in); + if (err) { + AC_DBG("Deserialize:%s\n", err.c_str()); + return false; + } + jb = jsonBuffer.as(); + #endif + return _loadElement(jb, name); + } #endif // !AUTOCONNECT_USE_JSON String _title; /**< A title of the page */ diff --git a/src/AutoConnectAuxImpl.h b/src/AutoConnectAuxImpl.h index 66d01d7..6ee9cc3 100644 --- a/src/AutoConnectAuxImpl.h +++ b/src/AutoConnectAuxImpl.h @@ -230,37 +230,6 @@ bool AutoConnectAux::_parseJson(T in) { return _load(jb); } -/** - * Parse and load a JSON document which declares one of the AutoConnectElement. - * The compiler instantiates this template according to the stored data - * type that contains the JSON document. - * This template also generates different parsing function calls - * depending on the ArduinoJson version. - * @param T An object type of the JSON document which must be a - * passable object to ArduinoJson. - * @param in An instance of a source JSON document to load. - */ -template -bool AutoConnectAux::_parseElement(T in, const String& name) { - ArduinoJsonBuffer jsonBuffer(AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE); - JsonVariant jb; -#if ARDUINOJSON_VERSION_MAJOR<=5 - jb = jsonBuffer.parse(in); - if (!jb.success()) { - AC_DBG("JSON parse error\n"); - return false; - } -#else - DeserializationError err = deserializeJson(jsonBuffer, in); - if (err) { - AC_DBG("Deserialize:%s\n", err.c_str()); - return false; - } - jb = jsonBuffer.as(); -#endif - return _loadElement(jb, name); -} - /** * Get AutoConnectElementJson element. * @param name an element name.