- moved "StaticJsonDocument<JSON_BUFFER_SIZE>" to JsonDocument as StaticJsonDocument is marked depriciated. - Fixed display_plus show()-method - Fixed string length for drumset sounds - Newer version of third-party librariesdev
parent
fe256cd8c8
commit
be9fa9eda2
@ -1,5 +1,5 @@ |
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2023, Benoit BLANCHON
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include "src/ArduinoJson.h" |
#include "src/ArduinoJson.h" |
||||||
|
@ -1,854 +1,130 @@ |
|||||||
ArduinoJson: change log |
ArduinoJson: change log |
||||||
======================= |
======================= |
||||||
|
|
||||||
v6.21.3 (2023-07-23) |
v7.0.3 (2024-02-05) |
||||||
------- |
|
||||||
|
|
||||||
* Fix compatibility with the Blynk libary (issue #1914) |
|
||||||
* Fix double lookup in `to<JsonVariant>()` |
|
||||||
* Fix double call to `size()` in `serializeMsgPack()` |
|
||||||
* Include `ARDUINOJSON_SLOT_OFFSET_SIZE` in the namespace name |
|
||||||
* Show a link to the documentation when user passes an unsupported input type |
|
||||||
|
|
||||||
v6.21.2 (2023-04-12) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fix compatibility with the Zephyr Project (issue #1905) |
|
||||||
* Allow using PROGMEM outside of Arduino (issue #1903) |
|
||||||
* Set default for `ARDUINOJSON_ENABLE_PROGMEM` to `1` on AVR |
|
||||||
|
|
||||||
v6.21.1 (2023-03-27) |
|
||||||
------- |
|
||||||
|
|
||||||
* Double speed of `DynamicJsonDocument::garbageCollect()` |
|
||||||
* Fix compatibility with GCC 5.2 (issue #1897) |
|
||||||
|
|
||||||
v6.21.0 (2023-03-14) |
|
||||||
------- |
|
||||||
|
|
||||||
* Drop support for C++98/C++03. Minimum required is C++11. |
|
||||||
* Remove `ARDUINOJSON_NAMESPACE`; use `ArduinoJson` instead. |
|
||||||
* Make string support generic (issue #1807) |
|
||||||
|
|
||||||
v6.20.1 (2023-02-08) |
|
||||||
------- |
|
||||||
|
|
||||||
* Remove explicit exclusion of `as<char*>()` and `as<char>()` (issue #1860) |
|
||||||
If you try to call them, you'll now get the same error message as any unsupported type. |
|
||||||
You could also add a custom converter for `char*` and `char`. |
|
||||||
|
|
||||||
v6.20.0 (2022-12-26) |
|
||||||
------- |
|
||||||
|
|
||||||
* Add `JsonVariant::shallowCopy()` (issue #1343) |
|
||||||
* Fix `9.22337e+18 is outside the range of representable values of type 'long'` |
|
||||||
* Fix comparison operators for `JsonArray`, `JsonArrayConst`, `JsonObject`, and `JsonObjectConst` |
|
||||||
* Fix lax parsing of `true`, `false`, and `null` (issue #1781) |
|
||||||
* Remove undocumented `accept()` functions |
|
||||||
* Rename `addElement()` to `add()` |
|
||||||
* Remove `getElement()`, `getOrAddElement()`, `getMember()`, and `getOrAddMember()` |
|
||||||
* Remove undocumented `JsonDocument::data()` and `JsonDocument::memoryPool()` |
|
||||||
* Remove undocumented `JsonArrayIterator::internal()` and `JsonObjectIterator::internal()` |
|
||||||
* Rename things in `ARDUINOJSON_NAMESPACE` to match the public names |
|
||||||
* Add documentation to most public symbols |
|
||||||
* Remove support for naked `char` (was deprecated since 6.18.0) |
|
||||||
|
|
||||||
> ### BREAKING CHANGES |
|
||||||
> |
|
||||||
> This release hides `JsonVariant`'s functions that were only intended for internal use. |
|
||||||
> If you were using them in your programs, you must replace with `operator[]` and `to<JsonVariant>()`, like so: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> // before |
|
||||||
> JsonVariant a = variant.getElement(idx); |
|
||||||
> JsonVariant b = variant.getOrAddElement(idx); |
|
||||||
> JsonVariant c = variant.getMember(key); |
|
||||||
> JsonVariant d = variant.getOrAddMember(key); |
|
||||||
> |
|
||||||
> // after |
|
||||||
> JsonVariant a = variant[idx]; |
|
||||||
> JsonVariant b = idx < variant.size() ? variant[idx] : variant[idx].to<JsonVariant>(); |
|
||||||
> JsonVariant c = variant[key]; |
|
||||||
> JsonVariant d = variant.containsKey(key) ? variant[key] : variant[key].to<JsonVariant>(); |
|
||||||
> ``` |
|
||||||
|
|
||||||
v6.19.4 (2022-04-05) |
|
||||||
------- |
|
||||||
|
|
||||||
* Add `ElementProxy::memoryUsage()` |
|
||||||
* Add `MemberProxy::memoryUsage()` (issue #1730) |
|
||||||
* Add implicit conversion from `JsonDocument` to `JsonVariant` |
|
||||||
* Fix comparisons operators with `const JsonDocument&` |
|
||||||
|
|
||||||
v6.19.3 (2022-03-08) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fix `call of overloaded 'String(const char*, int)' is ambiguous` |
|
||||||
* Fix `JsonString` operator `==` and `!=` for non-zero-terminated string |
|
||||||
* Fix `-Wsign-conversion` on GCC 8 (issue #1715) |
|
||||||
* MessagePack: serialize round floats as integers (issue #1718) |
|
||||||
|
|
||||||
v6.19.2 (2022-02-14) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fix `cannot convert 'pgm_p' to 'const void*'` (issue #1707) |
|
||||||
|
|
||||||
v6.19.1 (2022-01-14) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fix crash when adding an object member in a too small `JsonDocument` |
|
||||||
* Fix filter not working in zero-copy mode (issue #1697) |
|
||||||
|
|
||||||
v6.19.0 (2022-01-08) |
|
||||||
------- |
|
||||||
|
|
||||||
* Remove `ARDUINOJSON_EMBEDDED_MODE` and assume we run on an embedded platform. |
|
||||||
Dependent settings (like `ARDUINOJSON_DEFAULT_NESTING_LIMIT`) must be set individually. |
|
||||||
* Change the default of `ARDUINOJSON_USE_DOUBLE` to `1` |
|
||||||
* Change the default of `ARDUINOJSON_USE_LONG_LONG` to `1` on 32-bit platforms |
|
||||||
* Add `as<JsonString>()` and `is<JsonString>()` |
|
||||||
* Add safe bool idiom in `JsonString` |
|
||||||
* Add support for NUL in string values (issue #1646) |
|
||||||
* Add support for arbitrary array rank in `copyArray()` |
|
||||||
* Add support for `char[][]` in `copyArray()` |
|
||||||
* Remove `DeserializationError == bool` and `DeserializationError != bool` |
|
||||||
* Renamed undocumented function `isUndefined()` to `isUnbound()` |
|
||||||
* Fix `JsonVariant::memoryUsage()` for raw strings |
|
||||||
* Fix `call of overloaded 'swap(BasicJsonDocument&, BasicJsonDocument&)' is ambiguous` (issue #1678) |
|
||||||
* Fix inconsistent pool capacity between `BasicJsonDocument`'s copy and move constructors |
|
||||||
* Fix inconsistent pool capacity between `BasicJsonDocument`'s copy and move assignments |
|
||||||
* Fix return type of `StaticJsonDocument::operator=` |
|
||||||
* Avoid pool reallocation in `BasicJsonDocument`'s copy assignment if capacity is the same |
|
||||||
* Avoid including `Arduino.h` when all its features are disabled (issue #1692, PR #1693 by @paulocsanz) |
|
||||||
* Assume `PROGMEM` is available as soon as `ARDUINO` is defined (consequence of #1693) |
|
||||||
|
|
||||||
v6.18.5 (2021-09-28) |
|
||||||
------- |
|
||||||
|
|
||||||
* Set `ARDUINOJSON_EMBEDDED_MODE` to `1` on Nios II (issue #1657) |
|
||||||
|
|
||||||
v6.18.4 (2021-09-06) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed error `'dummy' may be used uninitialized` on GCC 11 |
|
||||||
* Fixed error `expected unqualified-id before 'const'` on GCC 11 (issue #1622) |
|
||||||
* Filter: exact match takes precedence over wildcard (issue #1628) |
|
||||||
* Fixed deserialization of `\u0000` (issue #1646) |
|
||||||
|
|
||||||
v6.18.3 (2021-07-27) |
|
||||||
------- |
|
||||||
|
|
||||||
* Changed return type of `convertToJson()` and `Converter<T>::toJson()` to `void` |
|
||||||
* Added `as<std::string_view>()` and `is<std::string_view>()` |
|
||||||
|
|
||||||
v6.18.2 (2021-07-19) |
|
||||||
------- |
|
||||||
|
|
||||||
* Removed a symlink because the Arduino Library Specification forbids it |
|
||||||
|
|
||||||
v6.18.1 (2021-07-03) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed support for `volatile float` and `volatile double` (issue #1557) |
|
||||||
* Fixed error `[Pe070]: incomplete type is not allowed` on IAR (issue #1560) |
|
||||||
* Fixed `serializeJson(doc, String)` when allocation fails (issue #1572) |
|
||||||
* Fixed clang-tidy warnings (issue #1574, PR #1577 by @armandas) |
|
||||||
* Added fake class `InvalidConversion<T1,T2>` to easily identify invalid conversions (issue #1585) |
|
||||||
* Added support for `std::string_view` (issue #1578, PR #1554 by @0xFEEDC0DE64) |
|
||||||
* Fixed warning `definition of implicit copy constructor for 'MsgPackDeserializer' is deprecated because it has a user-declared copy assignment operator` |
|
||||||
* Added `JsonArray::clear()` (issue #1597) |
|
||||||
* Fixed `JsonVariant::as<unsigned>()` (issue #1601) |
|
||||||
* Added support for ESP-IDF component build (PR #1562 by @qt1, PR #1599 by @andreaskuster) |
|
||||||
|
|
||||||
v6.18.0 (2021-05-05) |
|
||||||
------- |
|
||||||
|
|
||||||
* Added support for custom converters (issue #687) |
|
||||||
* Added support for `Printable` (issue #1444) |
|
||||||
* Removed support for `char` values, see below (issue #1498) |
|
||||||
* `deserializeJson()` leaves `\uXXXX` unchanged instead of returning `NotSupported` |
|
||||||
* `deserializeMsgPack()` inserts `null` instead of returning `NotSupported` |
|
||||||
* 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) |
|
||||||
* Simplified `JsonVariant::as<T>()` to always return `T` (see below) |
|
||||||
* Updated folders list in `.mbedignore` (PR #1515 by @AGlass0fMilk) |
|
||||||
* Fixed member-call-on-null-pointer in `getMember()` when array is empty |
|
||||||
* `serializeMsgPack(doc, buffer, size)` doesn't add null-terminator anymore (issue #1545) |
|
||||||
* `serializeJson(doc, buffer, size)` adds null-terminator only if there is enough room |
|
||||||
* PlatformIO: set `build.libArchive` to `false` (PR #1550 by @askreet) |
|
||||||
|
|
||||||
> ### BREAKING CHANGES |
|
||||||
> |
|
||||||
> #### Support for `char` removed |
|
||||||
> |
|
||||||
> We cannot cast a `JsonVariant` to a `char` anymore, so the following will break: |
|
||||||
> ```c++ |
|
||||||
> char age = doc["age"]; // error: no matching function for call to 'variantAs(VariantData*&)' |
|
||||||
> ``` |
|
||||||
> Instead, you must use another integral type, such as `int8_t`: |
|
||||||
> ```c++ |
|
||||||
> int8_t age = doc["age"]; // OK |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> Similarly, we cannot assign from a `char` anymore, so the following will break: |
|
||||||
> ```c++ |
|
||||||
> char age; |
|
||||||
> doc["age"] = age; // error: no matching function for call to 'VariantRef::set(const char&)' |
|
||||||
> ``` |
|
||||||
> Instead, you must use another integral type, such as `int8_t`: |
|
||||||
> ```c++ |
|
||||||
> int8_t age; |
|
||||||
> doc["age"] = age; // OK |
|
||||||
> ``` |
|
||||||
> A deprecation warning with the message "Support for `char` is deprecated, use `int8_t` or `uint8_t` instead" was added to allow a smooth transition. |
|
||||||
> |
|
||||||
> #### `as<T>()` always returns `T` |
|
||||||
> |
|
||||||
> Previously, `JsonVariant::as<T>()` could return a type different from `T`. |
|
||||||
> The most common example is `as<char*>()` that returned a `const char*`. |
|
||||||
> While this feature simplified a few use cases, it was confusing and complicated the |
|
||||||
> implementation of custom converters. |
|
||||||
> |
|
||||||
> Starting from this version, `as<T>` doesn't try to auto-correct the return type and always return `T`, |
|
||||||
> which means that you cannot write this anymore: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> Serial.println(doc["sensor"].as<char*>()); // error: invalid conversion from 'const char*' to 'char*' [-fpermissive] |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> Instead, you must write: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> Serial.println(doc["sensor"].as<const char*>()); // OK |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> A deprecation warning with the message "Replace `as<char*>()` with `as<const char*>()`" was added to allow a smooth transition. |
|
||||||
> |
|
||||||
> #### `DeserializationError::NotSupported` removed |
|
||||||
> |
|
||||||
> On a different topic, `DeserializationError::NotSupported` has been removed. |
|
||||||
> Instead of returning this error: |
|
||||||
> |
|
||||||
> * `deserializeJson()` leaves `\uXXXX` unchanged (only when `ARDUINOJSON_DECODE_UNICODE` is `0`) |
|
||||||
> * `deserializeMsgPack()` replaces unsupported values with `null`s |
|
||||||
> |
|
||||||
> #### Const-aware `is<T>()` |
|
||||||
> |
|
||||||
> Lastly, a very minor change concerns `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) |
|
||||||
------- |
|
||||||
|
|
||||||
* Made `JsonDocument`'s destructor protected (issue #1480) |
|
||||||
* Added missing calls to `client.stop()` in `JsonHttpClient.ino` (issue #1485) |
|
||||||
* Fixed error `expected ')' before 'char'` when `isdigit()` is a macro (issue #1487) |
|
||||||
* Fixed error `definition of implicit copy constructor is deprecated` on Clang 10 |
|
||||||
* PlatformIO: set framework compatibility to `*` (PR #1490 by @maxgerhardt) |
|
||||||
|
|
||||||
v6.17.2 (2020-11-14) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed invalid conversion error in `operator|(JsonVariant, char*)` (issue #1432) |
|
||||||
* Changed the default value of `ARDUINOJSON_ENABLE_PROGMEM` (issue #1433). |
|
||||||
It now checks that the `pgm_read_XXX` macros are defined before enabling `PROGMEM`. |
|
||||||
|
|
||||||
v6.17.1 (2020-11-07) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed error `ambiguous overload for 'operator|'` (issue #1411) |
|
||||||
* Fixed `operator|(MemberProxy, JsonObject)` (issue #1415) |
|
||||||
* Allowed more than 32767 values in non-embedded mode (issue #1414) |
|
||||||
|
|
||||||
v6.17.0 (2020-10-19) |
|
||||||
------- |
|
||||||
|
|
||||||
* Added a build failure when nullptr is defined as a macro (issue #1355) |
|
||||||
* Added `JsonDocument::overflowed()` which tells if the memory pool was too small (issue #1358) |
|
||||||
* Added `DeserializationError::EmptyInput` which tells if the input was empty |
|
||||||
* Added `DeserializationError::f_str()` which returns a `const __FlashStringHelper*` (issue #846) |
|
||||||
* Added `operator|(JsonVariantConst, JsonVariantConst)` |
|
||||||
* Added filtering for MessagePack (issue #1298, PR #1394 by Luca Passarella) |
|
||||||
* Moved float convertion tables to PROGMEM |
|
||||||
* Fixed `JsonVariant::set((char*)0)` which returned false instead of true (issue #1368) |
|
||||||
* Fixed error `No such file or directory #include <WString.h>` (issue #1381) |
|
||||||
|
|
||||||
v6.16.1 (2020-08-04) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed `deserializeJson()` that stopped reading after `{}` (issue #1335) |
|
||||||
|
|
||||||
v6.16.0 (2020-08-01) |
|
||||||
------- |
|
||||||
|
|
||||||
* Added comparisons (`>`, `>=`, `==`, `!=`, `<`, and `<=`) between `JsonVariant`s |
|
||||||
* Added string deduplication (issue #1303) |
|
||||||
* Added `JsonString::operator!=` |
|
||||||
* Added wildcard key (`*`) for filters (issue #1309) |
|
||||||
* Set `ARDUINOJSON_DECODE_UNICODE` to `1` by default |
|
||||||
* Fixed `copyArray()` not working with `String`, `ElementProxy`, and `MemberProxy` |
|
||||||
* Fixed error `getOrAddElement is not a member of ElementProxy` (issue #1311) |
|
||||||
* Fixed excessive stack usage when compiled with `-Og` (issues #1210 and #1314) |
|
||||||
* Fixed `Warning[Pa093]: implicit conversion from floating point to integer` on IAR compiler (PR #1328 by @stawiski) |
|
||||||
|
|
||||||
v6.15.2 (2020-05-15) |
|
||||||
------- |
|
||||||
|
|
||||||
* CMake: don't build tests when imported in another project |
|
||||||
* CMake: made project arch-independent |
|
||||||
* Visual Studio: fixed error C2766 with flag `/Zc:__cplusplus` (issue #1250) |
|
||||||
* Added support for `JsonDocument` to `copyArray()` (issue #1255) |
|
||||||
* Added support for `enum`s in `as<T>()` and `is<T>()` (issue #1256) |
|
||||||
* Added `JsonVariant` as an input type for `deserializeXxx()` |
|
||||||
For example, you can do: `deserializeJson(doc2, doc1["payload"])` |
|
||||||
* Break the build if using 64-bit integers with ARDUINOJSON_USE_LONG_LONG==0 |
|
||||||
|
|
||||||
v6.15.1 (2020-04-08) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed "maybe-uninitialized" warning (issue #1217) |
|
||||||
* Fixed "statement is unreachable" warning on IAR (issue #1233) |
|
||||||
* Fixed "pointless integer comparison" warning on IAR (issue #1233) |
|
||||||
* Added CMake "install" target (issue #1209) |
|
||||||
* Disabled alignment on AVR (issue #1231) |
|
||||||
|
|
||||||
v6.15.0 (2020-03-22) |
|
||||||
------- |
|
||||||
|
|
||||||
* Added `DeserializationOption::Filter` (issue #959) |
|
||||||
* Added example `JsonFilterExample.ino` |
|
||||||
* Changed the array subscript operator to automatically add missing elements |
|
||||||
* Fixed "deprecated-copy" warning on GCC 9 (fixes #1184) |
|
||||||
* Fixed `MemberProxy::set(char[])` not duplicating the string (issue #1191) |
|
||||||
* Fixed enums serialized as booleans (issue #1197) |
|
||||||
* Fixed incorrect string comparison on some platforms (issue #1198) |
|
||||||
* Added move-constructor and move-assignment to `BasicJsonDocument` |
|
||||||
* Added `BasicJsonDocument::garbageCollect()` (issue #1195) |
|
||||||
* Added `StaticJsonDocument::garbageCollect()` |
|
||||||
* Changed copy-constructor of `BasicJsonDocument` to preserve the capacity of the source. |
|
||||||
* Removed copy-constructor of `JsonDocument` (issue #1189) |
|
||||||
|
|
||||||
> ### BREAKING CHANGES |
|
||||||
> |
|
||||||
> #### Copy-constructor of `BasicJsonDocument` |
|
||||||
> |
|
||||||
> In previous versions, the copy constructor of `BasicJsonDocument` looked at the source's `memoryUsage()` to choose its capacity. |
|
||||||
> Now, the copy constructor of `BasicJsonDocument` uses the same capacity as the source. |
|
||||||
> |
|
||||||
> Example: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> DynamicJsonDocument doc1(64); |
|
||||||
> doc1.set(String("example")); |
|
||||||
> |
|
||||||
> DynamicJsonDocument doc2 = doc1; |
|
||||||
> Serial.print(doc2.capacity()); // 8 with ArduinoJson 6.14 |
|
||||||
> // 64 with ArduinoJson 6.15 |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> I made this change to get consistent results between copy-constructor and move-constructor, and whether RVO applies or not. |
|
||||||
> |
|
||||||
> If you use the copy-constructor to optimize your documents, you can use `garbageCollect()` or `shrinkToFit()` instead. |
|
||||||
> |
|
||||||
> #### Copy-constructor of `JsonDocument` |
|
||||||
> |
|
||||||
> In previous versions, it was possible to create a function that take a `JsonDocument` by value. |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> void myFunction(JsonDocument doc) {} |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> This function gives the wrong clues because it doesn't receive a copy of the `JsonDocument`, only a sliced version. |
|
||||||
> It worked because the copy constructor copied the internal pointers, but it was an accident. |
|
||||||
> |
|
||||||
> From now, if you need to pass a `JsonDocument` to a function, you must use a reference: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> void myFunction(JsonDocument& doc) {} |
|
||||||
> ``` |
|
||||||
|
|
||||||
v6.14.1 (2020-01-27) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed regression in UTF16 decoding (issue #1173) |
|
||||||
* Fixed `containsKey()` on `JsonVariantConst` |
|
||||||
* Added `getElement()` and `getMember()` to `JsonVariantConst` |
|
||||||
|
|
||||||
v6.14.0 (2020-01-16) |
|
||||||
------- |
|
||||||
|
|
||||||
* Added `BasicJsonDocument::shrinkToFit()` |
|
||||||
* Added support of `uint8_t` for `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` (issue #1142) |
|
||||||
* Added `ARDUINOJSON_ENABLE_COMMENTS` to enable support for comments (defaults to 0) |
|
||||||
* Auto enable support for `std::string` and `std::stream` on modern compilers (issue #1156) |
|
||||||
(No need to define `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_STD_STREAM` anymore) |
|
||||||
* Improved decoding of UTF-16 surrogate pairs (PR #1157 by @kaysievers) |
|
||||||
(ArduinoJson now produces standard UTF-8 instead of CESU-8) |
|
||||||
* Added `measureJson`, `measureJsonPretty`, and `measureMsgPack` to `keywords.txt` |
|
||||||
(This file is used for syntax highlighting in the Arduino IDE) |
|
||||||
* Fixed `variant.is<nullptr_t>()` |
|
||||||
* Fixed value returned by `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` when writing to a `String` |
|
||||||
* Improved speed of `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` when writing to a `String` |
|
||||||
|
|
||||||
> ### BREAKING CHANGES |
|
||||||
> |
|
||||||
> #### Comments |
|
||||||
> |
|
||||||
> Support for comments in input is now optional and disabled by default. |
|
||||||
> |
|
||||||
> If you need support for comments, you must defined `ARDUINOJSON_ENABLE_COMMENTS` to `1`; otherwise, you'll receive `InvalidInput` errors. |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> #define ARDUINOJSON_ENABLE_COMMENTS 1 |
|
||||||
> #include <ArduinoJson.h> |
|
||||||
> ``` |
|
||||||
|
|
||||||
v6.13.0 (2019-11-01) |
|
||||||
------- |
|
||||||
|
|
||||||
* Added support for custom writer/reader classes (issue #1088) |
|
||||||
* Added conversion from `JsonArray` and `JsonObject` to `bool`, to be consistent with `JsonVariant` |
|
||||||
* Fixed `deserializeJson()` when input contains duplicate keys (issue #1095) |
|
||||||
* Improved `deserializeMsgPack()` speed by reading several bytes at once |
|
||||||
* Added detection of Atmel AVR8/GNU C Compiler (issue #1112) |
|
||||||
* Fixed deserializer that stopped reading at the first `0xFF` (PR #1118 by @mikee47) |
|
||||||
* Fixed dangling reference in copies of `MemberProxy` and `ElementProxy` (issue #1120) |
|
||||||
|
|
||||||
v6.12.0 (2019-09-05) |
|
||||||
------- |
|
||||||
|
|
||||||
* Use absolute instead of relative includes (issue #1072) |
|
||||||
* Changed `JsonVariant::as<bool>()` to return `true` for any non-null value (issue #1005) |
|
||||||
* Moved ancillary files to `extras/` (issue #1011) |
|
||||||
|
|
||||||
v6.11.5 (2019-08-23) |
|
||||||
------- |
|
||||||
|
|
||||||
* Added fallback implementations of `strlen_P()`, `strncmp_P()`, `strcmp_P()`, and `memcpy_P()` (issue #1073) |
|
||||||
|
|
||||||
v6.11.4 (2019-08-12) |
|
||||||
------- |
|
||||||
|
|
||||||
* Added `measureJson()` to the `ArduinoJson` namespace (PR #1069 by @nomis) |
|
||||||
* Added support for `basic_string<char, traits, allocator>` (issue #1045) |
|
||||||
* Fixed example `JsonConfigFile.ino` for ESP8266 |
|
||||||
* Include `Arduino.h` if `ARDUINO` is defined (PR #1071 by @nomis) |
|
||||||
|
|
||||||
v6.11.3 (2019-07-22) |
|
||||||
------- |
|
||||||
|
|
||||||
* Added operators `==` and `!=` for `JsonDocument`, `ElementProxy`, and `MemberProxy` |
|
||||||
* Fixed comparison of `JsonVariant` when one contains a linked string and the other contains an owned string (issue #1051) |
|
||||||
|
|
||||||
v6.11.2 (2019-07-08) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed assignment of `JsonDocument` to `JsonVariant` (issue #1023) |
|
||||||
* Fix invalid conversion error on Particle Argon (issue #1035) |
|
||||||
|
|
||||||
v6.11.1 (2019-06-21) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed `serialized()` not working with Flash strings (issue #1030) |
|
||||||
|
|
||||||
v6.11.0 (2019-05-26) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed `deserializeJson()` silently accepting a `Stream*` (issue #978) |
|
||||||
* Fixed invalid result from `operator|` (issue #981) |
|
||||||
* Made `deserializeJson()` more picky about trailing characters (issue #980) |
|
||||||
* Added `ARDUINOJSON_ENABLE_NAN` (default=0) to enable NaN in JSON (issue #973) |
|
||||||
* Added `ARDUINOJSON_ENABLE_INFINITY` (default=0) to enable Infinity in JSON |
|
||||||
* Removed implicit conversion in comparison operators (issue #998) |
|
||||||
* Added lexicographical comparison for `JsonVariant` |
|
||||||
* Added support for `nullptr` (issue #998) |
|
||||||
|
|
||||||
> ### BREAKING CHANGES |
|
||||||
> |
|
||||||
> #### NaN and Infinity |
|
||||||
> |
|
||||||
> The JSON specification allows neither NaN not Infinity, but previous |
|
||||||
> versions of ArduinoJson supported it. Now, ArduinoJson behaves like most |
|
||||||
> other libraries: a NaN or and Infinity in the `JsonDocument`, becomes |
|
||||||
> a `null` in the output JSON. Also, `deserializeJson()` returns |
|
||||||
> `InvalidInput` if the JSON document contains NaN or Infinity. |
|
||||||
> |
|
||||||
> This version still supports NaN and Infinity in JSON documents, but |
|
||||||
> it's disabled by default to be compatible with other JSON parsers. |
|
||||||
> If you need the old behavior back, define `ARDUINOJSON_ENABLE_NAN` and |
|
||||||
> `ARDUINOJSON_ENABLE_INFINITY` to `1`;: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> #define ARDUINOJSON_ENABLE_NAN 1 |
|
||||||
> #define ARDUINOJSON_ENABLE_INFINITY 1 |
|
||||||
> #include <ArduinoJson.h> |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> #### The "or" operator |
|
||||||
> |
|
||||||
> This version slightly changes the behavior of the | operator when the |
|
||||||
> variant contains a float and the user requests an integer. |
|
||||||
> |
|
||||||
> Older versions returned the floating point value truncated. |
|
||||||
> Now, it returns the default value. |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> // suppose variant contains 1.2 |
|
||||||
> int value = variant | 3; |
|
||||||
> |
|
||||||
> // old behavior: |
|
||||||
> value == 1 |
|
||||||
> |
|
||||||
> // new behavior |
|
||||||
> value == 3 |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> If you need the old behavior, you must add `if (variant.is<float>())`. |
|
||||||
|
|
||||||
v6.10.1 (2019-04-23) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed error "attributes are not allowed on a function-definition" |
|
||||||
* Fixed `deserializeJson()` not being picky enough (issue #969) |
|
||||||
* Fixed error "no matching function for call to write(uint8_t)" (issue #972) |
|
||||||
|
|
||||||
v6.10.0 (2019-03-22) |
|
||||||
------- |
|
||||||
|
|
||||||
* Fixed an integer overflow in the JSON deserializer |
|
||||||
* Added overflow handling in `JsonVariant::as<T>()` and `JsonVariant::is<T>()`. |
|
||||||
- `as<T>()` returns `0` if the integer `T` overflows |
|
||||||
- `is<T>()` returns `false` if the integer `T` overflows |
|
||||||
* Added `BasicJsonDocument` to support custom allocator (issue #876) |
|
||||||
* Added `JsonDocument::containsKey()` (issue #938) |
|
||||||
* Added `JsonVariant::containsKey()` |
|
||||||
|
|
||||||
v6.9.1 (2019-03-01) |
|
||||||
------ |
------ |
||||||
|
|
||||||
* Fixed warning "unused variable" with GCC 4.4 (issue #912) |
* Improve error messages when using `char` or `char*` (issue #2043) |
||||||
* Fixed warning "cast increases required alignment" (issue #914) |
* Reduce stack consumption (issue #2046) |
||||||
* Fixed warning "conversion may alter value" (issue #914) |
* Fix compatibility with GCC 4.8 (issue #2045) |
||||||
* Fixed naming conflict with "CAPACITY" (issue #839) |
|
||||||
* Muted warning "will change in GCC 7.1" (issue #914) |
|
||||||
* Added a clear error message for `StaticJsonBuffer` and `DynamicJsonBuffer` |
|
||||||
* Marked ArduinoJson.h as a "system header" |
|
||||||
|
|
||||||
v6.9.0 (2019-02-26) |
v7.0.2 (2024-01-19) |
||||||
------ |
------ |
||||||
|
|
||||||
* Decode escaped Unicode characters like \u00DE (issue #304, PR #791) |
* Fix assertion `poolIndex < count_` after `JsonDocument::clear()` (issue #2034) |
||||||
Many thanks to Daniel Schulte (aka @trilader) who implemented this feature. |
|
||||||
* Added option ARDUINOJSON_DECODE_UNICODE to enable it |
|
||||||
* Converted `JsonArray::copyFrom()/copyTo()` to free functions `copyArray()` |
|
||||||
* Renamed `JsonArray::copyFrom()` and `JsonObject::copyFrom()` to `set()` |
|
||||||
* Renamed `JsonArray::get()` to `getElement()` |
|
||||||
* Renamed `JsonArray::add()` (without arg) to `addElement()` |
|
||||||
* Renamed `JsonObject::get()` to `getMember()` |
|
||||||
* Renamed `JsonObject::getOrCreate()` to `getOrAddMember()` |
|
||||||
* Fixed `JsonVariant::isNull()` not returning `true` after `set((char*)0)` |
|
||||||
* Fixed segfault after `variant.set(serialized((char*)0))` |
|
||||||
* Detect `IncompleteInput` in `false`, `true`, and `null` |
|
||||||
* Added `JsonDocument::size()` |
|
||||||
* Added `JsonDocument::remove()` |
|
||||||
* Added `JsonVariant::clear()` |
|
||||||
* Added `JsonVariant::remove()` |
|
||||||
|
|
||||||
v6.8.0-beta (2019-01-30) |
|
||||||
----------- |
|
||||||
|
|
||||||
* Import functions in the ArduinoJson namespace to get clearer errors |
|
||||||
* Improved syntax highlighting in Arduino IDE |
|
||||||
* Removed default capacity of `DynamicJsonDocument` |
|
||||||
* `JsonArray::copyFrom()` accepts `JsonArrayConst` |
|
||||||
* `JsonVariant::set()` accepts `JsonArrayConst` and `JsonObjectConst` |
|
||||||
* `JsonDocument` was missing in the ArduinoJson namespace |
|
||||||
* Added `memoryUsage()` to `JsonArray`, `JsonObject`, and `JsonVariant` |
|
||||||
* Added `nesting()` to `JsonArray`, `JsonDocument`, `JsonObject`, and `JsonVariant` |
|
||||||
* Replaced `JsonDocument::nestingLimit` with an additional parameter |
|
||||||
to `deserializeJson()` and `deserializeMsgPack()` |
|
||||||
* Fixed uninitialized variant in `JsonDocument` |
|
||||||
* Fixed `StaticJsonDocument` copy constructor and copy assignment |
|
||||||
* The copy constructor of `DynamicJsonDocument` chooses the capacity according to the memory usage of the source, not from the capacity of the source. |
|
||||||
* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant` |
|
||||||
* Added `JsonDocument::isNull()` |
|
||||||
* Added `JsonDocument::operator[]` |
|
||||||
* Added `ARDUINOJSON_TAB` to configure the indentation character |
|
||||||
* Reduced the size of the pretty JSON serializer |
|
||||||
* Added `add()`, `createNestedArray()` and `createNestedObject()` to `JsonVariant` |
|
||||||
* `JsonVariant` automatically promotes to `JsonObject` or `JsonArray` on write. |
|
||||||
Calling `JsonVariant::to<T>()` is not required anymore. |
|
||||||
* `JsonDocument` now support the same operations as `JsonVariant`. |
|
||||||
Calling `JsonDocument::as<T>()` is not required anymore. |
|
||||||
* Fixed example `JsonHttpClient.ino` |
|
||||||
* User can now use a `JsonString` as a key or a value |
|
||||||
|
|
||||||
> ### BREAKING CHANGES |
|
||||||
> |
|
||||||
> #### `DynamicJsonDocument`'s constructor |
|
||||||
> |
|
||||||
> The parameter to the constructor of `DynamicJsonDocument` is now mandatory |
|
||||||
> |
|
||||||
> Old code: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> DynamicJsonDocument doc; |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> New code: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> DynamicJsonDocument doc(1024); |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> #### Nesting limit |
|
||||||
> |
|
||||||
> `JsonDocument::nestingLimit` was replaced with a new parameter to `deserializeJson()` and `deserializeMsgPack()`. |
|
||||||
> |
|
||||||
> Old code: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> doc.nestingLimit = 15; |
|
||||||
> deserializeJson(doc, input); |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> New code: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> deserializeJson(doc, input, DeserializationOption::NestingLimit(15)); |
|
||||||
> ``` |
|
||||||
|
|
||||||
v6.7.0-beta (2018-12-07) |
|
||||||
----------- |
|
||||||
|
|
||||||
* Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity. |
|
||||||
* Restored the monotonic allocator because the code was getting too big |
|
||||||
* Reduced the memory usage |
|
||||||
* Reduced the code size |
|
||||||
* Renamed `JsonKey` to `JsonString` |
|
||||||
* Removed spurious files in the Particle library |
|
||||||
|
|
||||||
v6.6.0-beta (2018-11-13) |
|
||||||
----------- |
|
||||||
|
|
||||||
* Removed `JsonArray::is<T>(i)` and `JsonArray::set(i,v)` |
|
||||||
* Removed `JsonObject::is<T>(k)` and `JsonObject::set(k,v)` |
|
||||||
* Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)` |
|
||||||
* Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)` |
|
||||||
* Added `JSON_STRING_SIZE()` |
|
||||||
* ~~Replacing or removing a value now releases the memory~~ |
|
||||||
* Added `DeserializationError::code()` to be used in switch statements (issue #846) |
|
||||||
|
|
||||||
v6.5.0-beta (2018-10-13) |
v7.0.1 (2024-01-10) |
||||||
----------- |
------ |
||||||
|
|
||||||
* Added implicit conversion from `JsonArray` and `JsonObject` to `JsonVariant` |
|
||||||
* Allow mixed configuration in compilation units (issue #809) |
|
||||||
* Fixed object keys not being duplicated |
|
||||||
* `JsonPair::key()` now returns a `JsonKey` |
|
||||||
* Increased the default capacity of `DynamicJsonDocument` |
|
||||||
* Fixed `JsonVariant::is<String>()` (closes #763) |
|
||||||
* Added `JsonArrayConst`, `JsonObjectConst`, and `JsonVariantConst` |
|
||||||
* Added copy-constructor and copy-assignment-operator for `JsonDocument` (issue #827) |
|
||||||
|
|
||||||
v6.4.0-beta (2018-09-11) |
|
||||||
----------- |
|
||||||
|
|
||||||
* Copy `JsonArray` and `JsonObject`, instead of storing pointers (issue #780) |
* Fix "no matching function" with `JsonObjectConst::operator[]` (issue #2019) |
||||||
* Added `JsonVariant::to<JsonArray>()` and `JsonVariant::to<JsonObject>()` |
* Remove unused files in the PlatformIO package |
||||||
|
* Fix `volatile bool` serialized as `1` or `0` instead of `true` or `false` (issue #2029) |
||||||
|
|
||||||
v6.3.0-beta (2018-08-31) |
v7.0.0 (2024-01-03) |
||||||
----------- |
------ |
||||||
|
|
||||||
* Implemented reference semantics for `JsonVariant` |
* Remove `BasicJsonDocument` |
||||||
* Replaced `JsonPair`'s `key` and `value` with `key()` and `value()` |
* Remove `StaticJsonDocument` |
||||||
* Fixed `serializeJson(obj[key], dst)` (issue #794) |
* Add abstract `Allocator` class |
||||||
|
* Merge `DynamicJsonDocument` with `JsonDocument` |
||||||
|
* Remove `JSON_ARRAY_SIZE()`, `JSON_OBJECT_SIZE()`, and `JSON_STRING_SIZE()` |
||||||
|
* Remove `ARDUINOJSON_ENABLE_STRING_DEDUPLICATION` (string deduplication cannot be disabled anymore) |
||||||
|
* Remove `JsonDocument::capacity()` |
||||||
|
* Store the strings in the heap |
||||||
|
* Reference-count shared strings |
||||||
|
* Always store `serialized("string")` by copy (#1915) |
||||||
|
* Remove the zero-copy mode of `deserializeJson()` and `deserializeMsgPack()` |
||||||
|
* Fix double lookup in `to<JsonVariant>()` |
||||||
|
* Fix double call to `size()` in `serializeMsgPack()` |
||||||
|
* Include `ARDUINOJSON_SLOT_OFFSET_SIZE` in the namespace name |
||||||
|
* Remove `JsonVariant::shallowCopy()` |
||||||
|
* `JsonDocument`'s capacity grows as needed, no need to pass it to the constructor anymore |
||||||
|
* `JsonDocument`'s allocator is not monotonic anymore, removed values get recycled |
||||||
|
* Show a link to the documentation when user passes an unsupported input type |
||||||
|
* Remove `JsonDocument::memoryUsage()` |
||||||
|
* Remove `JsonDocument::garbageCollect()` |
||||||
|
* Add `deserializeJson(JsonVariant, ...)` and `deserializeMsgPack(JsonVariant, ...)` (#1226) |
||||||
|
* Call `shrinkToFit()` in `deserializeJson()` and `deserializeMsgPack()` |
||||||
|
* `serializeJson()` and `serializeMsgPack()` replace the content of `std::string` and `String` instead of appending to it |
||||||
|
* Replace `add()` with `add<T>()` (`add(T)` is still supported) |
||||||
|
* Remove `createNestedArray()` and `createNestedObject()` (use `to<JsonArray>()` and `to<JsonObject>()` instead) |
||||||
|
|
||||||
> ### BREAKING CHANGES |
> ### BREAKING CHANGES |
||||||
> |
> |
||||||
> #### JsonVariant |
> As every major release, ArduinoJson 7 introduces several breaking changes. |
||||||
|
> I added some stubs so that most existing programs should compile, but I highty recommend you upgrade your code. |
||||||
> |
> |
||||||
> `JsonVariant` now has a semantic similar to `JsonObject` and `JsonArray`. |
> #### `JsonDocument` |
||||||
> It's a reference to a value stored in the `JsonDocument`. |
|
||||||
> As a consequence, a `JsonVariant` cannot be used as a standalone variable anymore. |
|
||||||
> |
> |
||||||
> Old code: |
> In ArduinoJson 6, you could allocate the memory pool on the stack (with `StaticJsonDocument`) or in the heap (with `DynamicJsonDocument`). |
||||||
|
> In ArduinoJson 7, the memory pool is always allocated in the heap, so `StaticJsonDocument` and `DynamicJsonDocument` have been merged into `JsonDocument`. |
||||||
> |
> |
||||||
> ```c++ |
> In ArduinoJson 6, `JsonDocument` had a fixed capacity; in ArduinoJson 7, it has an elastic capacity that grows as needed. |
||||||
> JsonVariant myValue = 42; |
> Therefore, you don't need to specify the capacity anymore, so the macros `JSON_ARRAY_SIZE()`, `JSON_OBJECT_SIZE()`, and `JSON_STRING_SIZE()` have been removed. |
||||||
> ``` |
|
||||||
> |
|
||||||
> New code: |
|
||||||
> |
> |
||||||
> ```c++ |
> ```c++ |
||||||
> DynamicJsonDocument doc; |
> // ArduinoJson 6 |
||||||
> JsonVariant myValue = doc.to<JsonVariant>(); |
> StaticJsonDocument<256> doc; |
||||||
> myValue.set(42); |
> // or |
||||||
> ``` |
> DynamicJsonDocument doc(256); |
||||||
> |
> |
||||||
> #### JsonPair |
> // ArduinoJson 7 |
||||||
> |
> JsonDocument doc; |
||||||
> Old code: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> for(JsonPair p : myObject) { |
|
||||||
> Serial.println(p.key); |
|
||||||
> Serial.println(p.value.as<int>()); |
|
||||||
> } |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> New code: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> for(JsonPair p : myObject) { |
|
||||||
> Serial.println(p.key()); |
|
||||||
> Serial.println(p.value().as<int>()); |
|
||||||
> } |
|
||||||
> ``` |
> ``` |
||||||
> |
> |
||||||
> CAUTION: the key is now read only! |
> In ArduinoJson 7, `JsonDocument` reuses released memory, so `garbageCollect()` has been removed. |
||||||
|
> `shrinkToFit()` is still available and releases the over-allocated memory. |
||||||
v6.2.3-beta (2018-07-19) |
|
||||||
----------- |
|
||||||
|
|
||||||
* Fixed exception when using Flash strings as object keys (issue #784) |
|
||||||
|
|
||||||
v6.2.2-beta (2018-07-18) |
|
||||||
----------- |
|
||||||
|
|
||||||
* Fixed `invalid application of 'sizeof' to incomplete type '__FlashStringHelper'` (issue #783) |
|
||||||
* Fixed `char[]` not duplicated when passed to `JsonVariant::operator[]` |
|
||||||
|
|
||||||
v6.2.1-beta (2018-07-17) |
|
||||||
----------- |
|
||||||
|
|
||||||
* Fixed `JsonObject` not inserting keys of type `String` (issue #782) |
|
||||||
|
|
||||||
v6.2.0-beta (2018-07-12) |
|
||||||
----------- |
|
||||||
|
|
||||||
* Disabled lazy number deserialization (issue #772) |
|
||||||
* Fixed `JsonVariant::is<int>()` that returned true for empty strings |
|
||||||
* Improved float serialization when `-fsingle-precision-constant` is used |
|
||||||
* Renamed function `RawJson()` to `serialized()` |
|
||||||
* `serializeMsgPack()` now supports values marked with `serialized()` |
|
||||||
|
|
||||||
> ### BREAKING CHANGES |
|
||||||
> |
|
||||||
> #### Non quoted strings |
|
||||||
> |
|
||||||
> Non quoted strings are now forbidden in values, but they are still allowed in keys. |
|
||||||
> For example, `{key:"value"}` is accepted, but `{key:value}` is not. |
|
||||||
> |
> |
||||||
> #### Preformatted values |
> Due to a change in the implementation, it's not possible to store a pointer to a variant from another `JsonDocument`, so `shallowCopy()` has been removed. |
||||||
> |
> |
||||||
> Old code: |
> In ArduinoJson 6, the meaning of `memoryUsage()` was clear: it returned the number of bytes used in the memory pool. |
||||||
|
> In ArduinoJson 7, the meaning of `memoryUsage()` would be ambiguous, so it has been removed. |
||||||
> |
> |
||||||
> ```c++ |
> #### Custom allocators |
||||||
> object["values"] = RawJson("[1,2,3,4]"); |
|
||||||
> ``` |
|
||||||
> |
> |
||||||
> New code: |
> In ArduinoJson 6, you could specify a custom allocator class as a template parameter of `BasicJsonDocument`. |
||||||
|
> In ArduinoJson 7, you must inherit from `ArduinoJson::Allocator` and pass a pointer to an instance of your class to the constructor of `JsonDocument`. |
||||||
> |
> |
||||||
> ```c++ |
> ```c++ |
||||||
> object["values"] = serialized("[1,2,3,4]"); |
> // ArduinoJson 6 |
||||||
> ``` |
> class MyAllocator { |
||||||
|
> // ... |
||||||
v6.1.0-beta (2018-07-02) |
> }; |
||||||
----------- |
> BasicJsonDocument<MyAllocator> doc(256); |
||||||
|
|
||||||
* Return `JsonArray` and `JsonObject` by value instead of reference (issue #309) |
|
||||||
* Replaced `success()` with `isNull()` |
|
||||||
|
|
||||||
> ### BREAKING CHANGES |
|
||||||
> |
|
||||||
> Old code: |
|
||||||
> |
> |
||||||
> ```c++ |
> // ArduinoJson 7 |
||||||
> JsonObject& obj = doc.to<JsonObject>(); |
> class MyAllocator : public ArduinoJson::Allocator { |
||||||
> JsonArray& arr = obj.createNestedArray("key"); |
> // ... |
||||||
> if (!arr.success()) { |
> }; |
||||||
> Serial.println("Not enough memory"); |
> MyAllocator myAllocator; |
||||||
> return; |
> JsonDocument doc(&myAllocator); |
||||||
> } |
|
||||||
> ``` |
> ``` |
||||||
> |
> |
||||||
> New code: |
> #### `createNestedArray()` and `createNestedObject()` |
||||||
> |
> |
||||||
> ```c++ |
> In ArduinoJson 6, you could create a nested array or object with `createNestedArray()` and `createNestedObject()`. |
||||||
> JsonObject obj = doc.to<JsonObject>(); |
> In ArduinoJson 7, you must use `add<T>()` or `to<T>()` instead. |
||||||
> JsonArray arr = obj.createNestedArray("key"); |
|
||||||
> if (arr.isNull()) { |
|
||||||
> Serial.println("Not enough memory"); |
|
||||||
> return; |
|
||||||
> } |
|
||||||
> ``` |
|
||||||
|
|
||||||
v6.0.1-beta (2018-06-11) |
|
||||||
----------- |
|
||||||
|
|
||||||
* Fixed conflicts with `isnan()` and `isinf()` macros (issue #752) |
|
||||||
|
|
||||||
v6.0.0-beta (2018-06-07) |
|
||||||
----------- |
|
||||||
|
|
||||||
* Added `DynamicJsonDocument` and `StaticJsonDocument` |
|
||||||
* Added `deserializeJson()` |
|
||||||
* Added `serializeJson()` and `serializeJsonPretty()` |
|
||||||
* Added `measureJson()` and `measureJsonPretty()` |
|
||||||
* Added `serializeMsgPack()`, `deserializeMsgPack()` and `measureMsgPack()` (issue #358) |
|
||||||
* Added example `MsgPackParser.ino` (issue #358) |
|
||||||
* Added support for non zero-terminated strings (issue #704) |
|
||||||
* Removed `JsonBuffer::parseArray()`, `parseObject()` and `parse()` |
|
||||||
* Removed `JsonBuffer::createArray()` and `createObject()` |
|
||||||
* Removed `printTo()` and `prettyPrintTo()` |
|
||||||
* Removed `measureLength()` and `measurePrettyLength()` |
|
||||||
* Removed all deprecated features |
|
||||||
|
|
||||||
> ### BREAKING CHANGES |
|
||||||
> |
|
||||||
> #### Deserialization |
|
||||||
> |
> |
||||||
> Old code: |
> For example, to create `[[],{}]`, you would write: |
||||||
> |
> |
||||||
> ```c++ |
> ```c++ |
||||||
> DynamicJsonBuffer jb; |
> // ArduinoJson 6 |
||||||
> JsonObject& obj = jb.parseObject(json); |
> arr.createNestedArray(); |
||||||
> if (obj.success()) { |
> arr.createNestedObject(); |
||||||
> |
> |
||||||
> } |
> // ArduinoJson 7 |
||||||
|
> arr.add<JsonArray>(); |
||||||
|
> arr.add<JsonObject>(); |
||||||
> ``` |
> ``` |
||||||
> |
> |
||||||
> New code: |
> And to create `{"array":[],"object":{}}`, you would write: |
||||||
> |
> |
||||||
> ```c++ |
> ```c++ |
||||||
> DynamicJsonDocument doc; |
> // ArduinoJson 6 |
||||||
> DeserializationError error = deserializeJson(doc, json); |
> obj.createNestedArray("array"); |
||||||
> if (error) { |
> obj.createNestedObject("object"); |
||||||
> |
|
||||||
> } |
|
||||||
> JsonObject& obj = doc.as<JsonObject>(); |
|
||||||
> ``` |
|
||||||
> |
> |
||||||
> #### Serialization |
> // ArduinoJson 7 |
||||||
> |
> obj["array"].to<JsonArray>(); |
||||||
> Old code: |
> obj["object"].to<JsonObject>(); |
||||||
> |
|
||||||
> ```c++ |
|
||||||
> DynamicJsonBuffer jb; |
|
||||||
> JsonObject& obj = jb.createObject(); |
|
||||||
> obj["key"] = "value"; |
|
||||||
> obj.printTo(Serial); |
|
||||||
> ``` |
|
||||||
> |
|
||||||
> New code: |
|
||||||
> |
|
||||||
> ```c++ |
|
||||||
> DynamicJsonDocument obj; |
|
||||||
> JsonObject& obj = doc.to<JsonObject>(); |
|
||||||
> obj["key"] = "value"; |
|
||||||
> serializeJson(doc, Serial); |
|
||||||
> ``` |
> ``` |
||||||
|
@ -0,0 +1,69 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
#include <string> |
||||||
|
|
||||||
|
using ArduinoJson::detail::is_base_of; |
||||||
|
|
||||||
|
static std::string allocatorLog; |
||||||
|
|
||||||
|
struct CustomAllocator { |
||||||
|
CustomAllocator() { |
||||||
|
allocatorLog = ""; |
||||||
|
} |
||||||
|
|
||||||
|
void* allocate(size_t n) { |
||||||
|
allocatorLog += "A"; |
||||||
|
return malloc(n); |
||||||
|
} |
||||||
|
|
||||||
|
void deallocate(void* p) { |
||||||
|
free(p); |
||||||
|
allocatorLog += "D"; |
||||||
|
} |
||||||
|
|
||||||
|
void* reallocate(void* p, size_t n) { |
||||||
|
allocatorLog += "R"; |
||||||
|
return realloc(p, n); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
TEST_CASE("BasicJsonDocument") { |
||||||
|
allocatorLog.clear(); |
||||||
|
|
||||||
|
SECTION("is a JsonDocument") { |
||||||
|
REQUIRE( |
||||||
|
is_base_of<JsonDocument, BasicJsonDocument<CustomAllocator>>::value == |
||||||
|
true); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("deserialize / serialize") { |
||||||
|
BasicJsonDocument<CustomAllocator> doc(256); |
||||||
|
deserializeJson(doc, "{\"hello\":\"world\"}"); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}"); |
||||||
|
doc.clear(); |
||||||
|
REQUIRE(allocatorLog == "ARAARDDD"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("copy") { |
||||||
|
BasicJsonDocument<CustomAllocator> doc(256); |
||||||
|
doc["hello"] = "world"; |
||||||
|
auto copy = doc; |
||||||
|
REQUIRE(copy.as<std::string>() == "{\"hello\":\"world\"}"); |
||||||
|
REQUIRE(allocatorLog == "AA"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("capacity") { |
||||||
|
BasicJsonDocument<CustomAllocator> doc(256); |
||||||
|
REQUIRE(doc.capacity() == 256); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("garbageCollect()") { |
||||||
|
BasicJsonDocument<CustomAllocator> doc(256); |
||||||
|
doc.garbageCollect(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
# ArduinoJson - https://arduinojson.org |
||||||
|
# Copyright © 2014-2024, Benoit BLANCHON |
||||||
|
# MIT License |
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") |
||||||
|
add_compile_options( |
||||||
|
-w |
||||||
|
) |
||||||
|
endif() |
||||||
|
|
||||||
|
if(MSVC) |
||||||
|
add_compile_options( |
||||||
|
/wd4996 |
||||||
|
) |
||||||
|
endif() |
||||||
|
|
||||||
|
add_executable(DeprecatedTests |
||||||
|
add.cpp |
||||||
|
createNestedArray.cpp |
||||||
|
createNestedObject.cpp |
||||||
|
BasicJsonDocument.cpp |
||||||
|
DynamicJsonDocument.cpp |
||||||
|
macros.cpp |
||||||
|
memoryUsage.cpp |
||||||
|
shallowCopy.cpp |
||||||
|
StaticJsonDocument.cpp |
||||||
|
) |
||||||
|
|
||||||
|
add_test(Deprecated DeprecatedTests) |
||||||
|
|
||||||
|
set_tests_properties(Deprecated |
||||||
|
PROPERTIES |
||||||
|
LABELS "Catch" |
||||||
|
) |
@ -0,0 +1,37 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
using ArduinoJson::detail::is_base_of; |
||||||
|
|
||||||
|
TEST_CASE("DynamicJsonDocument") { |
||||||
|
SECTION("is a JsonDocument") { |
||||||
|
REQUIRE(is_base_of<JsonDocument, DynamicJsonDocument>::value == true); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("deserialize / serialize") { |
||||||
|
DynamicJsonDocument doc(256); |
||||||
|
deserializeJson(doc, "{\"hello\":\"world\"}"); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("copy") { |
||||||
|
DynamicJsonDocument doc(256); |
||||||
|
doc["hello"] = "world"; |
||||||
|
auto copy = doc; |
||||||
|
REQUIRE(copy.as<std::string>() == "{\"hello\":\"world\"}"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("capacity") { |
||||||
|
DynamicJsonDocument doc(256); |
||||||
|
REQUIRE(doc.capacity() == 256); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("garbageCollect()") { |
||||||
|
DynamicJsonDocument doc(256); |
||||||
|
doc.garbageCollect(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
using ArduinoJson::detail::is_base_of; |
||||||
|
|
||||||
|
TEST_CASE("StaticJsonDocument") { |
||||||
|
SECTION("is a JsonDocument") { |
||||||
|
REQUIRE(is_base_of<JsonDocument, StaticJsonDocument<256>>::value == true); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("deserialize / serialize") { |
||||||
|
StaticJsonDocument<256> doc; |
||||||
|
deserializeJson(doc, "{\"hello\":\"world\"}"); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("copy") { |
||||||
|
StaticJsonDocument<256> doc; |
||||||
|
doc["hello"] = "world"; |
||||||
|
auto copy = doc; |
||||||
|
REQUIRE(copy.as<std::string>() == "{\"hello\":\"world\"}"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("capacity") { |
||||||
|
StaticJsonDocument<256> doc; |
||||||
|
REQUIRE(doc.capacity() == 256); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("JsonArray::add()") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonArray array = doc.to<JsonArray>(); |
||||||
|
array.add().set(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "[42]"); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonDocument::add()") { |
||||||
|
JsonDocument doc; |
||||||
|
doc.add().set(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "[42]"); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("ElementProxy::add()") { |
||||||
|
JsonDocument doc; |
||||||
|
doc[0].add().set(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "[[42]]"); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("MemberProxy::add()") { |
||||||
|
JsonDocument doc; |
||||||
|
doc["x"].add().set(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"x\":[42]}"); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::add()") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonVariant v = doc.add(); |
||||||
|
v.add().set(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "[[42]]"); |
||||||
|
} |
@ -0,0 +1,111 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
#include <string> |
||||||
|
|
||||||
|
TEST_CASE("JsonDocument::createNestedArray()") { |
||||||
|
JsonDocument doc; |
||||||
|
|
||||||
|
SECTION("createNestedArray()") { |
||||||
|
JsonArray array = doc.createNestedArray(); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "[[42]]"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("createNestedArray(const char*)") { |
||||||
|
JsonArray array = doc.createNestedArray("key"); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("createNestedArray(std::string)") { |
||||||
|
JsonArray array = doc.createNestedArray(std::string("key")); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}"); |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef HAS_VARIABLE_LENGTH_ARRAY |
||||||
|
SECTION("createNestedArray(VLA)") { |
||||||
|
size_t i = 16; |
||||||
|
char vla[i]; |
||||||
|
strcpy(vla, "key"); |
||||||
|
JsonArray array = doc.createNestedArray(vla); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}"); |
||||||
|
} |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonArray::createNestedArray()") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonArray array = doc.to<JsonArray>(); |
||||||
|
JsonArray nestedArray = array.createNestedArray(); |
||||||
|
nestedArray.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "[[42]]"); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonObject::createNestedArray()") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonObject object = doc.to<JsonObject>(); |
||||||
|
|
||||||
|
SECTION("createNestedArray(const char*)") { |
||||||
|
JsonArray array = object.createNestedArray("key"); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("createNestedArray(std::string)") { |
||||||
|
JsonArray array = object.createNestedArray(std::string("key")); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}"); |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef HAS_VARIABLE_LENGTH_ARRAY |
||||||
|
SECTION("createNestedArray(VLA)") { |
||||||
|
size_t i = 16; |
||||||
|
char vla[i]; |
||||||
|
strcpy(vla, "key"); |
||||||
|
JsonArray array = object.createNestedArray(vla); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}"); |
||||||
|
} |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::createNestedArray()") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonVariant variant = doc.to<JsonVariant>(); |
||||||
|
|
||||||
|
SECTION("createNestedArray()") { |
||||||
|
JsonArray array = variant.createNestedArray(); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "[[42]]"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("createNestedArray(const char*)") { |
||||||
|
JsonArray array = variant.createNestedArray("key"); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("createNestedArray(std::string)") { |
||||||
|
JsonArray array = variant.createNestedArray(std::string("key")); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}"); |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef HAS_VARIABLE_LENGTH_ARRAY |
||||||
|
SECTION("createNestedArray(VLA)") { |
||||||
|
size_t i = 16; |
||||||
|
char vla[i]; |
||||||
|
strcpy(vla, "key"); |
||||||
|
JsonArray array = variant.createNestedArray(vla); |
||||||
|
array.add(42); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":[42]}"); |
||||||
|
} |
||||||
|
#endif |
||||||
|
} |
@ -0,0 +1,111 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
#include <string> |
||||||
|
|
||||||
|
TEST_CASE("JsonDocument::createNestedObject()") { |
||||||
|
JsonDocument doc; |
||||||
|
|
||||||
|
SECTION("createNestedObject()") { |
||||||
|
JsonObject object = doc.createNestedObject(); |
||||||
|
object["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "[{\"hello\":\"world\"}]"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("createNestedObject(const char*)") { |
||||||
|
JsonObject object = doc.createNestedObject("key"); |
||||||
|
object["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("createNestedObject(std::string)") { |
||||||
|
JsonObject object = doc.createNestedObject(std::string("key")); |
||||||
|
object["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}"); |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef HAS_VARIABLE_LENGTH_ARRAY |
||||||
|
SECTION("createNestedObject(VLA)") { |
||||||
|
size_t i = 16; |
||||||
|
char vla[i]; |
||||||
|
strcpy(vla, "key"); |
||||||
|
JsonObject object = doc.createNestedObject(vla); |
||||||
|
object["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}"); |
||||||
|
} |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonArray::createNestedObject()") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonArray array = doc.to<JsonArray>(); |
||||||
|
JsonObject object = array.createNestedObject(); |
||||||
|
object["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "[{\"hello\":\"world\"}]"); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonObject::createNestedObject()") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonObject object = doc.to<JsonObject>(); |
||||||
|
|
||||||
|
SECTION("createNestedObject(const char*)") { |
||||||
|
JsonObject nestedObject = object.createNestedObject("key"); |
||||||
|
nestedObject["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("createNestedObject(std::string)") { |
||||||
|
JsonObject nestedObject = object.createNestedObject(std::string("key")); |
||||||
|
nestedObject["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}"); |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef HAS_VARIABLE_LENGTH_ARRAY |
||||||
|
SECTION("createNestedObject(VLA)") { |
||||||
|
size_t i = 16; |
||||||
|
char vla[i]; |
||||||
|
strcpy(vla, "key"); |
||||||
|
JsonObject nestedObject = object.createNestedObject(vla); |
||||||
|
nestedObject["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}"); |
||||||
|
} |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::createNestedObject()") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonVariant variant = doc.to<JsonVariant>(); |
||||||
|
|
||||||
|
SECTION("createNestedObject()") { |
||||||
|
JsonObject object = variant.createNestedObject(); |
||||||
|
object["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "[{\"hello\":\"world\"}]"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("createNestedObject(const char*)") { |
||||||
|
JsonObject object = variant.createNestedObject("key"); |
||||||
|
object["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}"); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("createNestedObject(std::string)") { |
||||||
|
JsonObject object = variant.createNestedObject(std::string("key")); |
||||||
|
object["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}"); |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef HAS_VARIABLE_LENGTH_ARRAY |
||||||
|
SECTION("createNestedObject(VLA)") { |
||||||
|
size_t i = 16; |
||||||
|
char vla[i]; |
||||||
|
strcpy(vla, "key"); |
||||||
|
JsonObject object = variant.createNestedObject(vla); |
||||||
|
object["hello"] = "world"; |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"key\":{\"hello\":\"world\"}}"); |
||||||
|
} |
||||||
|
#endif |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("JSON_ARRAY_SIZE") { |
||||||
|
REQUIRE(JSON_ARRAY_SIZE(10) == ArduinoJson::detail::sizeofArray(10)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JSON_OBJECT_SIZE") { |
||||||
|
REQUIRE(JSON_OBJECT_SIZE(10) == ArduinoJson::detail::sizeofObject(10)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JSON_STRING_SIZE") { |
||||||
|
REQUIRE(JSON_STRING_SIZE(10) == ArduinoJson::detail::sizeofString(10)); |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("JsonArray::memoryUsage()") { |
||||||
|
JsonArray array; |
||||||
|
REQUIRE(array.memoryUsage() == 0); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonArrayConst::memoryUsage()") { |
||||||
|
JsonArrayConst array; |
||||||
|
REQUIRE(array.memoryUsage() == 0); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonDocument::memoryUsage()") { |
||||||
|
JsonDocument doc; |
||||||
|
REQUIRE(doc.memoryUsage() == 0); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonObject::memoryUsage()") { |
||||||
|
JsonObject array; |
||||||
|
REQUIRE(array.memoryUsage() == 0); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonObjectConst::memoryUsage()") { |
||||||
|
JsonObjectConst array; |
||||||
|
REQUIRE(array.memoryUsage() == 0); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::memoryUsage()") { |
||||||
|
JsonVariant doc; |
||||||
|
REQUIRE(doc.memoryUsage() == 0); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonVariantConst::memoryUsage()") { |
||||||
|
JsonVariantConst doc; |
||||||
|
REQUIRE(doc.memoryUsage() == 0); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("ElementProxy::memoryUsage()") { |
||||||
|
JsonDocument doc; |
||||||
|
REQUIRE(doc[0].memoryUsage() == 0); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("MemberProxy::memoryUsage()") { |
||||||
|
JsonDocument doc; |
||||||
|
REQUIRE(doc["hello"].memoryUsage() == 0); |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("shallowCopy()") { |
||||||
|
JsonDocument doc1, doc2; |
||||||
|
doc1["b"] = "c"; |
||||||
|
doc2["a"].shallowCopy(doc1); |
||||||
|
|
||||||
|
REQUIRE(doc2.as<std::string>() == "{\"a\":{\"b\":\"c\"}}"); |
||||||
|
} |
@ -0,0 +1,283 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <ArduinoJson/Memory/Allocator.hpp> |
||||||
|
#include <ArduinoJson/Memory/StringBuilder.hpp> |
||||||
|
#include <ArduinoJson/Memory/VariantPool.hpp> |
||||||
|
|
||||||
|
#include <sstream> |
||||||
|
|
||||||
|
struct FailingAllocator : ArduinoJson::Allocator { |
||||||
|
static FailingAllocator* instance() { |
||||||
|
static FailingAllocator allocator; |
||||||
|
return &allocator; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
FailingAllocator() = default; |
||||||
|
~FailingAllocator() = default; |
||||||
|
|
||||||
|
void* allocate(size_t) override { |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
|
||||||
|
void deallocate(void*) override {} |
||||||
|
|
||||||
|
void* reallocate(void*, size_t) override { |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
class AllocatorLogEntry { |
||||||
|
public: |
||||||
|
AllocatorLogEntry(std::string s, size_t n = 1) : str_(s), count_(n) {} |
||||||
|
|
||||||
|
const std::string& str() const { |
||||||
|
return str_; |
||||||
|
} |
||||||
|
|
||||||
|
size_t count() const { |
||||||
|
return count_; |
||||||
|
} |
||||||
|
|
||||||
|
AllocatorLogEntry operator*(size_t n) const { |
||||||
|
return AllocatorLogEntry(str_, n); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
std::string str_; |
||||||
|
size_t count_; |
||||||
|
}; |
||||||
|
|
||||||
|
inline AllocatorLogEntry Allocate(size_t s) { |
||||||
|
char buffer[32]; |
||||||
|
sprintf(buffer, "allocate(%zu)", s); |
||||||
|
return AllocatorLogEntry(buffer); |
||||||
|
} |
||||||
|
|
||||||
|
inline AllocatorLogEntry AllocateFail(size_t s) { |
||||||
|
char buffer[32]; |
||||||
|
sprintf(buffer, "allocate(%zu) -> nullptr", s); |
||||||
|
return AllocatorLogEntry(buffer); |
||||||
|
} |
||||||
|
|
||||||
|
inline AllocatorLogEntry Reallocate(size_t s1, size_t s2) { |
||||||
|
char buffer[32]; |
||||||
|
sprintf(buffer, "reallocate(%zu, %zu)", s1, s2); |
||||||
|
return AllocatorLogEntry(buffer); |
||||||
|
} |
||||||
|
|
||||||
|
inline AllocatorLogEntry ReallocateFail(size_t s1, size_t s2) { |
||||||
|
char buffer[32]; |
||||||
|
sprintf(buffer, "reallocate(%zu, %zu) -> nullptr", s1, s2); |
||||||
|
return AllocatorLogEntry(buffer); |
||||||
|
} |
||||||
|
|
||||||
|
inline AllocatorLogEntry Deallocate(size_t s) { |
||||||
|
char buffer[32]; |
||||||
|
sprintf(buffer, "deallocate(%zu)", s); |
||||||
|
return AllocatorLogEntry(buffer); |
||||||
|
} |
||||||
|
|
||||||
|
class AllocatorLog { |
||||||
|
public: |
||||||
|
AllocatorLog() = default; |
||||||
|
AllocatorLog(std::initializer_list<AllocatorLogEntry> list) { |
||||||
|
for (auto& entry : list) |
||||||
|
append(entry); |
||||||
|
} |
||||||
|
|
||||||
|
void clear() { |
||||||
|
log_.str(""); |
||||||
|
} |
||||||
|
|
||||||
|
void append(const AllocatorLogEntry& entry) { |
||||||
|
for (size_t i = 0; i < entry.count(); i++) |
||||||
|
log_ << entry.str() << "\n"; |
||||||
|
} |
||||||
|
|
||||||
|
std::string str() const { |
||||||
|
auto s = log_.str(); |
||||||
|
if (s.empty()) |
||||||
|
return "(empty)"; |
||||||
|
s.pop_back(); // remove the trailing '\n'
|
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
bool operator==(const AllocatorLog& other) const { |
||||||
|
return str() == other.str(); |
||||||
|
} |
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const AllocatorLog& log) { |
||||||
|
os << log.str(); |
||||||
|
return os; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
std::ostringstream log_; |
||||||
|
}; |
||||||
|
|
||||||
|
class SpyingAllocator : public ArduinoJson::Allocator { |
||||||
|
public: |
||||||
|
SpyingAllocator( |
||||||
|
Allocator* upstream = ArduinoJson::detail::DefaultAllocator::instance()) |
||||||
|
: upstream_(upstream) {} |
||||||
|
virtual ~SpyingAllocator() {} |
||||||
|
|
||||||
|
size_t allocatedBytes() const { |
||||||
|
return allocatedBytes_; |
||||||
|
} |
||||||
|
|
||||||
|
void* allocate(size_t n) override { |
||||||
|
auto block = reinterpret_cast<AllocatedBlock*>( |
||||||
|
upstream_->allocate(sizeof(AllocatedBlock) + n - 1)); |
||||||
|
if (block) { |
||||||
|
log_.append(Allocate(n)); |
||||||
|
allocatedBytes_ += n; |
||||||
|
block->size = n; |
||||||
|
return block->payload; |
||||||
|
} else { |
||||||
|
log_.append(AllocateFail(n)); |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void deallocate(void* p) override { |
||||||
|
auto block = AllocatedBlock::fromPayload(p); |
||||||
|
allocatedBytes_ -= block->size; |
||||||
|
log_.append(Deallocate(block ? block->size : 0)); |
||||||
|
upstream_->deallocate(block); |
||||||
|
} |
||||||
|
|
||||||
|
void* reallocate(void* p, size_t n) override { |
||||||
|
auto block = AllocatedBlock::fromPayload(p); |
||||||
|
auto oldSize = block ? block->size : 0; |
||||||
|
block = reinterpret_cast<AllocatedBlock*>( |
||||||
|
upstream_->reallocate(block, sizeof(AllocatedBlock) + n - 1)); |
||||||
|
if (block) { |
||||||
|
log_.append(Reallocate(oldSize, n)); |
||||||
|
block->size = n; |
||||||
|
allocatedBytes_ += n - oldSize; |
||||||
|
return block->payload; |
||||||
|
} else { |
||||||
|
log_.append(ReallocateFail(oldSize, n)); |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void clearLog() { |
||||||
|
log_.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
const AllocatorLog& log() const { |
||||||
|
return log_; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
struct AllocatedBlock { |
||||||
|
size_t size; |
||||||
|
char payload[1]; |
||||||
|
|
||||||
|
static AllocatedBlock* fromPayload(void* p) { |
||||||
|
if (!p) |
||||||
|
return nullptr; |
||||||
|
return reinterpret_cast<AllocatedBlock*>( |
||||||
|
// Cast to void* to silence "cast increases required alignment of
|
||||||
|
// target type [-Werror=cast-align]"
|
||||||
|
reinterpret_cast<void*>(reinterpret_cast<char*>(p) - |
||||||
|
offsetof(AllocatedBlock, payload))); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
AllocatorLog log_; |
||||||
|
Allocator* upstream_; |
||||||
|
size_t allocatedBytes_ = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
class KillswitchAllocator : public ArduinoJson::Allocator { |
||||||
|
public: |
||||||
|
KillswitchAllocator( |
||||||
|
Allocator* upstream = ArduinoJson::detail::DefaultAllocator::instance()) |
||||||
|
: working_(true), upstream_(upstream) {} |
||||||
|
virtual ~KillswitchAllocator() {} |
||||||
|
|
||||||
|
void* allocate(size_t n) override { |
||||||
|
return working_ ? upstream_->allocate(n) : 0; |
||||||
|
} |
||||||
|
|
||||||
|
void deallocate(void* p) override { |
||||||
|
upstream_->deallocate(p); |
||||||
|
} |
||||||
|
|
||||||
|
void* reallocate(void* ptr, size_t n) override { |
||||||
|
return working_ ? upstream_->reallocate(ptr, n) : 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Turn the killswitch on, so all allocation fail
|
||||||
|
void on() { |
||||||
|
working_ = false; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
bool working_; |
||||||
|
Allocator* upstream_; |
||||||
|
}; |
||||||
|
|
||||||
|
class TimebombAllocator : public ArduinoJson::Allocator { |
||||||
|
public: |
||||||
|
TimebombAllocator( |
||||||
|
size_t initialCountdown, |
||||||
|
Allocator* upstream = ArduinoJson::detail::DefaultAllocator::instance()) |
||||||
|
: countdown_(initialCountdown), upstream_(upstream) {} |
||||||
|
virtual ~TimebombAllocator() {} |
||||||
|
|
||||||
|
void* allocate(size_t n) override { |
||||||
|
if (!countdown_) |
||||||
|
return nullptr; |
||||||
|
countdown_--; |
||||||
|
return upstream_->allocate(n); |
||||||
|
} |
||||||
|
|
||||||
|
void deallocate(void* p) override { |
||||||
|
upstream_->deallocate(p); |
||||||
|
} |
||||||
|
|
||||||
|
void* reallocate(void* ptr, size_t n) override { |
||||||
|
if (!countdown_) |
||||||
|
return nullptr; |
||||||
|
countdown_--; |
||||||
|
return upstream_->reallocate(ptr, n); |
||||||
|
} |
||||||
|
|
||||||
|
void setCountdown(size_t value) { |
||||||
|
countdown_ = value; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
size_t countdown_ = 0; |
||||||
|
Allocator* upstream_; |
||||||
|
}; |
||||||
|
|
||||||
|
inline size_t sizeofPoolList(size_t n = ARDUINOJSON_INITIAL_POOL_COUNT) { |
||||||
|
return sizeof(ArduinoJson::detail::VariantPool) * n; |
||||||
|
} |
||||||
|
|
||||||
|
inline size_t sizeofPool( |
||||||
|
ArduinoJson::detail::SlotCount n = ARDUINOJSON_POOL_CAPACITY) { |
||||||
|
return ArduinoJson::detail::VariantPool::slotsToBytes(n); |
||||||
|
} |
||||||
|
|
||||||
|
inline size_t sizeofStringBuffer(size_t iteration = 1) { |
||||||
|
// returns 31, 63, 127, 255, etc.
|
||||||
|
auto capacity = ArduinoJson::detail::StringBuilder::initialCapacity; |
||||||
|
for (size_t i = 1; i < iteration; i++) |
||||||
|
capacity = capacity * 2 + 1; |
||||||
|
return ArduinoJson::detail::sizeofString(capacity); |
||||||
|
} |
||||||
|
|
||||||
|
inline size_t sizeofString(const char* s) { |
||||||
|
return ArduinoJson::detail::sizeofString(strlen(s)); |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
# ArduinoJson - https://arduinojson.org |
||||||
|
# Copyright © 2014-2024, Benoit BLANCHON |
||||||
|
# MIT License |
||||||
|
|
||||||
|
add_executable(JsonArrayConstTests |
||||||
|
equals.cpp |
||||||
|
isNull.cpp |
||||||
|
iterator.cpp |
||||||
|
nesting.cpp |
||||||
|
size.cpp |
||||||
|
subscript.cpp |
||||||
|
) |
||||||
|
|
||||||
|
add_test(JsonArrayConst JsonArrayConstTests) |
||||||
|
|
||||||
|
set_tests_properties(JsonArrayConst |
||||||
|
PROPERTIES |
||||||
|
LABELS "Catch" |
||||||
|
) |
@ -0,0 +1,63 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("JsonArrayConst::operator==()") { |
||||||
|
JsonDocument doc1; |
||||||
|
JsonArrayConst array1 = doc1.to<JsonArray>(); |
||||||
|
|
||||||
|
JsonDocument doc2; |
||||||
|
JsonArrayConst array2 = doc2.to<JsonArray>(); |
||||||
|
|
||||||
|
SECTION("should return false when arrays differ") { |
||||||
|
doc1.add("coucou"); |
||||||
|
doc2.add(1); |
||||||
|
|
||||||
|
REQUIRE_FALSE(array1 == array2); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("should return false when LHS has more elements") { |
||||||
|
doc1.add(1); |
||||||
|
doc1.add(2); |
||||||
|
doc2.add(1); |
||||||
|
|
||||||
|
REQUIRE_FALSE(array1 == array2); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("should return false when RHS has more elements") { |
||||||
|
doc1.add(1); |
||||||
|
doc2.add(1); |
||||||
|
doc2.add(2); |
||||||
|
|
||||||
|
REQUIRE_FALSE(array1 == array2); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("should return true when arrays equal") { |
||||||
|
doc1.add("coucou"); |
||||||
|
doc2.add("coucou"); |
||||||
|
|
||||||
|
REQUIRE(array1 == array2); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("should return false when RHS is null") { |
||||||
|
JsonArrayConst null; |
||||||
|
|
||||||
|
REQUIRE_FALSE(array1 == null); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("should return false when LHS is null") { |
||||||
|
JsonArrayConst null; |
||||||
|
|
||||||
|
REQUIRE_FALSE(null == array1); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("should return true when both are null") { |
||||||
|
JsonArrayConst null1; |
||||||
|
JsonArrayConst null2; |
||||||
|
|
||||||
|
REQUIRE(null1 == null2); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("JsonArrayConst::isNull()") { |
||||||
|
SECTION("returns true") { |
||||||
|
JsonArrayConst arr; |
||||||
|
REQUIRE(arr.isNull() == true); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("returns false") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonArrayConst arr = doc.to<JsonArray>(); |
||||||
|
REQUIRE(arr.isNull() == false); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("JsonArrayConst::operator bool()") { |
||||||
|
SECTION("returns false") { |
||||||
|
JsonArrayConst arr; |
||||||
|
REQUIRE(static_cast<bool>(arr) == false); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("returns true") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonArrayConst arr = doc.to<JsonArray>(); |
||||||
|
REQUIRE(static_cast<bool>(arr) == true); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("JsonArrayConst::begin()/end()") { |
||||||
|
SECTION("Non null JsonArrayConst") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonArrayConst array = doc.to<JsonArray>(); |
||||||
|
doc.add(12); |
||||||
|
doc.add(34); |
||||||
|
|
||||||
|
auto it = array.begin(); |
||||||
|
auto end = array.end(); |
||||||
|
|
||||||
|
REQUIRE(end != it); |
||||||
|
REQUIRE(12 == it->as<int>()); |
||||||
|
REQUIRE(12 == static_cast<int>(*it)); |
||||||
|
++it; |
||||||
|
REQUIRE(end != it); |
||||||
|
REQUIRE(34 == it->as<int>()); |
||||||
|
REQUIRE(34 == static_cast<int>(*it)); |
||||||
|
++it; |
||||||
|
REQUIRE(end == it); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("Null JsonArrayConst") { |
||||||
|
JsonArrayConst array; |
||||||
|
|
||||||
|
REQUIRE(array.begin() == array.end()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("JsonArrayConst::nesting()") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonArrayConst arr = doc.to<JsonArray>(); |
||||||
|
|
||||||
|
SECTION("return 0 if unbound") { |
||||||
|
JsonArrayConst unbound; |
||||||
|
REQUIRE(unbound.nesting() == 0); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("returns 1 for empty array") { |
||||||
|
REQUIRE(arr.nesting() == 1); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("returns 1 for flat array") { |
||||||
|
doc.add("hello"); |
||||||
|
REQUIRE(arr.nesting() == 1); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("returns 2 with nested array") { |
||||||
|
doc.add<JsonArray>(); |
||||||
|
REQUIRE(arr.nesting() == 2); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("returns 2 with nested object") { |
||||||
|
doc.add<JsonObject>(); |
||||||
|
REQUIRE(arr.nesting() == 2); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("JsonArrayConst::size()") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonArrayConst array = doc.to<JsonArray>(); |
||||||
|
|
||||||
|
SECTION("returns 0 if unbound") { |
||||||
|
JsonArrayConst unbound; |
||||||
|
REQUIRE(0U == unbound.size()); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("returns 0 is empty") { |
||||||
|
REQUIRE(0U == array.size()); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("return number of elements") { |
||||||
|
doc.add("hello"); |
||||||
|
doc.add("world"); |
||||||
|
|
||||||
|
REQUIRE(2U == array.size()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("JsonArrayConst::operator[]") { |
||||||
|
JsonDocument doc; |
||||||
|
JsonArrayConst arr = doc.to<JsonArray>(); |
||||||
|
doc.add(1); |
||||||
|
doc.add(2); |
||||||
|
doc.add(3); |
||||||
|
|
||||||
|
REQUIRE(1 == arr[0].as<int>()); |
||||||
|
REQUIRE(2 == arr[1].as<int>()); |
||||||
|
REQUIRE(3 == arr[2].as<int>()); |
||||||
|
REQUIRE(0 == arr[3].as<int>()); |
||||||
|
} |
@ -0,0 +1,108 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h> |
||||||
|
|
||||||
|
#include <catch.hpp> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include "Allocators.hpp" |
||||||
|
|
||||||
|
using ArduinoJson::detail::sizeofArray; |
||||||
|
using ArduinoJson::detail::sizeofObject; |
||||||
|
|
||||||
|
TEST_CASE("deserializeJson(JsonDocument&)") { |
||||||
|
SpyingAllocator spy; |
||||||
|
JsonDocument doc(&spy); |
||||||
|
doc.add(std::string("hello")); |
||||||
|
spy.clearLog(); |
||||||
|
|
||||||
|
auto err = deserializeJson(doc, "[42]"); |
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok); |
||||||
|
REQUIRE(doc.as<std::string>() == "[42]"); |
||||||
|
REQUIRE(spy.log() == AllocatorLog{ |
||||||
|
Deallocate(sizeofPool()), |
||||||
|
Deallocate(sizeofString("hello")), |
||||||
|
Allocate(sizeofPool()), |
||||||
|
Reallocate(sizeofPool(), sizeofArray(1)), |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("deserializeJson(JsonVariant)") { |
||||||
|
SECTION("variant is bound") { |
||||||
|
SpyingAllocator spy; |
||||||
|
JsonDocument doc(&spy); |
||||||
|
doc.add(std::string("hello")); |
||||||
|
spy.clearLog(); |
||||||
|
|
||||||
|
JsonVariant variant = doc[0]; |
||||||
|
|
||||||
|
auto err = deserializeJson(variant, "[42]"); |
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok); |
||||||
|
REQUIRE(doc.as<std::string>() == "[[42]]"); |
||||||
|
REQUIRE(spy.log() == AllocatorLog{ |
||||||
|
Deallocate(sizeofString("hello")), |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("variant is unbound") { |
||||||
|
JsonVariant variant; |
||||||
|
|
||||||
|
auto err = deserializeJson(variant, "[42]"); |
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("deserializeJson(ElementProxy)") { |
||||||
|
SpyingAllocator spy; |
||||||
|
JsonDocument doc(&spy); |
||||||
|
doc.add(std::string("hello")); |
||||||
|
spy.clearLog(); |
||||||
|
|
||||||
|
SECTION("element already exists") { |
||||||
|
auto err = deserializeJson(doc[0], "[42]"); |
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok); |
||||||
|
REQUIRE(doc.as<std::string>() == "[[42]]"); |
||||||
|
REQUIRE(spy.log() == AllocatorLog{ |
||||||
|
Deallocate(sizeofString("hello")), |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("element must be created") { |
||||||
|
auto err = deserializeJson(doc[1], "[42]"); |
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok); |
||||||
|
REQUIRE(doc.as<std::string>() == "[\"hello\",[42]]"); |
||||||
|
REQUIRE(spy.log() == AllocatorLog{}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("deserializeJson(MemberProxy)") { |
||||||
|
SpyingAllocator spy; |
||||||
|
JsonDocument doc(&spy); |
||||||
|
doc[std::string("hello")] = std::string("world"); |
||||||
|
spy.clearLog(); |
||||||
|
|
||||||
|
SECTION("member already exists") { |
||||||
|
auto err = deserializeJson(doc["hello"], "[42]"); |
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":[42]}"); |
||||||
|
REQUIRE(spy.log() == AllocatorLog{ |
||||||
|
Deallocate(sizeofString("world")), |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("member must be created exists") { |
||||||
|
auto err = deserializeJson(doc["value"], "[42]"); |
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok); |
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\",\"value\":[42]}"); |
||||||
|
REQUIRE(spy.log() == AllocatorLog{}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,120 @@ |
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#define ARDUINOJSON_DECODE_UNICODE 1 |
||||||
|
#include <ArduinoJson.h> |
||||||
|
#include <catch.hpp> |
||||||
|
|
||||||
|
TEST_CASE("deserializeJson() returns IncompleteInput") { |
||||||
|
const char* testCases[] = { |
||||||
|
// strings
|
||||||
|
"\"\\", |
||||||
|
"\"hello", |
||||||
|
"\'hello", |
||||||
|
// unicode
|
||||||
|
"'\\u", |
||||||
|
"'\\u00", |
||||||
|
"'\\u000", |
||||||
|
// false
|
||||||
|
"f", |
||||||
|
"fa", |
||||||
|
"fal", |
||||||
|
"fals", |
||||||
|
// true
|
||||||
|
"t", |
||||||
|
"tr", |
||||||
|
"tru", |
||||||
|
// null
|
||||||
|
"n", |
||||||
|
"nu", |
||||||
|
"nul", |
||||||
|
// object
|
||||||
|
"{", |
||||||
|
"{a", |
||||||
|
"{a:", |
||||||
|
"{a:1", |
||||||
|
"{a:1,", |
||||||
|
"{a:1,b", |
||||||
|
"{a:1,b:", |
||||||
|
}; |
||||||
|
|
||||||
|
for (auto input : testCases) { |
||||||
|
SECTION(input) { |
||||||
|
JsonDocument doc; |
||||||
|
REQUIRE(deserializeJson(doc, input) == |
||||||
|
DeserializationError::IncompleteInput); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("deserializeJson() returns InvalidInput") { |
||||||
|
const char* testCases[] = { |
||||||
|
// unicode
|
||||||
|
"'\\u'", "'\\u000g'", "'\\u000'", "'\\u000G'", "'\\u000/'", "\\x1234", |
||||||
|
// numbers
|
||||||
|
"6a9", "1,", "2]", "3}", |
||||||
|
// constants
|
||||||
|
"nulL", "tru3", "fals3", |
||||||
|
// garbage
|
||||||
|
"%*$£¤"}; |
||||||
|
|
||||||
|
for (auto input : testCases) { |
||||||
|
SECTION(input) { |
||||||
|
JsonDocument doc; |
||||||
|
REQUIRE(deserializeJson(doc, input) == |
||||||
|
DeserializationError::InvalidInput); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("deserializeJson() oversees some edge cases") { |
||||||
|
const char* testCases[] = { |
||||||
|
"'\\ud83d'", // leading surrogate without a trailing surrogate
|
||||||
|
"'\\udda4'", // trailing surrogate without a leading surrogate
|
||||||
|
"'\\ud83d\\ud83d'", // two leading surrogates
|
||||||
|
}; |
||||||
|
|
||||||
|
for (auto input : testCases) { |
||||||
|
SECTION(input) { |
||||||
|
JsonDocument doc; |
||||||
|
REQUIRE(deserializeJson(doc, input) == DeserializationError::Ok); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("deserializeJson() returns EmptyInput") { |
||||||
|
JsonDocument doc; |
||||||
|
|
||||||
|
SECTION("null") { |
||||||
|
auto err = deserializeJson(doc, static_cast<const char*>(0)); |
||||||
|
REQUIRE(err == DeserializationError::EmptyInput); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("Empty string") { |
||||||
|
auto err = deserializeJson(doc, ""); |
||||||
|
REQUIRE(err == DeserializationError::EmptyInput); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("Only spaces") { |
||||||
|
auto err = deserializeJson(doc, " \t\n\r"); |
||||||
|
REQUIRE(err == DeserializationError::EmptyInput); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TEST_CASE("deserializeJson() returns NoMemory if string length overflows") { |
||||||
|
JsonDocument doc; |
||||||
|
auto maxLength = ArduinoJson::detail::StringNode::maxLength; |
||||||
|
|
||||||
|
SECTION("max length should succeed") { |
||||||
|
auto err = deserializeJson(doc, "\"" + std::string(maxLength, 'a') + "\""); |
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("one above max length should fail") { |
||||||
|
auto err = |
||||||
|
deserializeJson(doc, "\"" + std::string(maxLength + 1, 'a') + "\""); |
||||||
|
REQUIRE(err == DeserializationError::NoMemory); |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -1,117 +1,49 @@ |
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2023, Benoit BLANCHON
|
// Copyright © 2014-2024, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson.h> |
#include <ArduinoJson.h> |
||||||
#include <catch.hpp> |
#include <catch.hpp> |
||||||
|
|
||||||
using namespace Catch::Matchers; |
#include "Allocators.hpp" |
||||||
|
|
||||||
TEST_CASE("deserializeJson(DynamicJsonDocument&)") { |
using ArduinoJson::detail::sizeofArray; |
||||||
DynamicJsonDocument doc(4096); |
|
||||||
|
|
||||||
SECTION("Edge cases") { |
TEST_CASE("deserializeJson() misc cases") { |
||||||
SECTION("null char*") { |
SpyingAllocator spy; |
||||||
DeserializationError err = deserializeJson(doc, static_cast<char*>(0)); |
JsonDocument doc(&spy); |
||||||
|
|
||||||
REQUIRE(err != DeserializationError::Ok); |
SECTION("null") { |
||||||
} |
DeserializationError err = deserializeJson(doc, "null"); |
||||||
|
REQUIRE(err == DeserializationError::Ok); |
||||||
SECTION("null const char*") { |
REQUIRE(doc.is<float>() == false); |
||||||
DeserializationError err = |
|
||||||
deserializeJson(doc, static_cast<const char*>(0)); |
|
||||||
|
|
||||||
REQUIRE(err != DeserializationError::Ok); |
|
||||||
} |
|
||||||
|
|
||||||
SECTION("Empty input") { |
|
||||||
DeserializationError err = deserializeJson(doc, ""); |
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::EmptyInput); |
|
||||||
} |
|
||||||
|
|
||||||
SECTION("Only spaces") { |
|
||||||
DeserializationError err = deserializeJson(doc, " \t\n\r"); |
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::EmptyInput); |
|
||||||
} |
|
||||||
|
|
||||||
SECTION("issue #628") { |
|
||||||
DeserializationError err = deserializeJson(doc, "null"); |
|
||||||
REQUIRE(err == DeserializationError::Ok); |
|
||||||
REQUIRE(doc.is<float>() == false); |
|
||||||
} |
|
||||||
|
|
||||||
SECTION("Garbage") { |
|
||||||
DeserializationError err = deserializeJson(doc, "%*$£¤"); |
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::InvalidInput); |
|
||||||
} |
|
||||||
} |
} |
||||||
|
|
||||||
SECTION("Booleans") { |
SECTION("true") { |
||||||
SECTION("True") { |
DeserializationError err = deserializeJson(doc, "true"); |
||||||
DeserializationError err = deserializeJson(doc, "true"); |
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok); |
REQUIRE(err == DeserializationError::Ok); |
||||||
REQUIRE(doc.is<bool>()); |
REQUIRE(doc.is<bool>()); |
||||||
REQUIRE(doc.as<bool>() == true); |
REQUIRE(doc.as<bool>() == true); |
||||||
} |
|
||||||
|
|
||||||
SECTION("False") { |
|
||||||
DeserializationError err = deserializeJson(doc, "false"); |
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok); |
|
||||||
REQUIRE(doc.is<bool>()); |
|
||||||
REQUIRE(doc.as<bool>() == false); |
|
||||||
} |
|
||||||
} |
} |
||||||
|
|
||||||
SECTION("Premature null-terminator") { |
SECTION("false") { |
||||||
SECTION("In escape sequence") { |
DeserializationError err = deserializeJson(doc, "false"); |
||||||
DeserializationError err = deserializeJson(doc, "\"\\"); |
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::IncompleteInput); |
|
||||||
} |
|
||||||
|
|
||||||
SECTION("In double quoted string") { |
REQUIRE(err == DeserializationError::Ok); |
||||||
DeserializationError err = deserializeJson(doc, "\"hello"); |
REQUIRE(doc.is<bool>()); |
||||||
|
REQUIRE(doc.as<bool>() == false); |
||||||
REQUIRE(err == DeserializationError::IncompleteInput); |
|
||||||
} |
|
||||||
|
|
||||||
SECTION("In single quoted string") { |
|
||||||
DeserializationError err = deserializeJson(doc, "'hello"); |
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::IncompleteInput); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
SECTION("Premature end of input") { |
|
||||||
SECTION("In escape sequence") { |
|
||||||
DeserializationError err = deserializeJson(doc, "\"\\n\"", 2); |
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::IncompleteInput); |
|
||||||
} |
|
||||||
|
|
||||||
SECTION("In double quoted string") { |
|
||||||
DeserializationError err = deserializeJson(doc, "\"hello\"", 6); |
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::IncompleteInput); |
|
||||||
} |
|
||||||
|
|
||||||
SECTION("In single quoted string") { |
|
||||||
DeserializationError err = deserializeJson(doc, "'hello'", 6); |
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::IncompleteInput); |
|
||||||
} |
|
||||||
} |
} |
||||||
|
|
||||||
SECTION("Should clear the JsonVariant") { |
SECTION("Should clear the JsonVariant") { |
||||||
deserializeJson(doc, "[1,2,3]"); |
deserializeJson(doc, "[1,2,3]"); |
||||||
|
spy.clearLog(); |
||||||
|
|
||||||
deserializeJson(doc, "{}"); |
deserializeJson(doc, "{}"); |
||||||
|
|
||||||
REQUIRE(doc.is<JsonObject>()); |
REQUIRE(doc.is<JsonObject>()); |
||||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0)); |
REQUIRE(spy.log() == AllocatorLog{ |
||||||
|
Deallocate(sizeofArray(3)), |
||||||
|
}); |
||||||
} |
} |
||||||
} |
} |
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue