Skip to content

Commit

Permalink
Deprecate containsKey() in favor of doc["key"].is<T>()
Browse files Browse the repository at this point in the history
See #2121
  • Loading branch information
bblanchon committed Sep 6, 2024
1 parent dd1d96e commit d92eee8
Show file tree
Hide file tree
Showing 22 changed files with 263 additions and 269 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,33 @@ HEAD
* Reduce the slot size (see table below)
* Improve message when user forgets third arg of `serializeJson()` et al.
* Set `ARDUINOJSON_USE_DOUBLE` to `0` by default on 8-bit architectures
* Deprecate `containsKey()` in favor of `doc["key"].is<T>()`

| Architecture | before | after |
|--------------|----------|----------|
| 8-bit | 8 bytes | 6 bytes |
| 32-bit | 16 bytes | 8 bytes |
| 64-bit | 24 bytes | 16 bytes |

> ### BREAKING CHANGES
>
> After being on the death row for years, the `containsKey()` method has finally been deprecated.
> You should replace `doc.containsKey("key")` with `doc["key"].is<T>()`, which not only checks that the key exists but also that the value is of the expected type.
>
> ```cpp
> // Before
> if (doc.containsKey("value")) {
> int value = doc["value"];
> // ...
> }
>
> // After
> if (doc["value"].is<int>()) {
> int value = doc["value"];
> // ...
> }
> ```
v7.1.0 (2024-06-27)
------
Expand Down
3 changes: 2 additions & 1 deletion extras/tests/Deprecated/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ endif()

add_executable(DeprecatedTests
add.cpp
BasicJsonDocument.cpp
containsKey.cpp
createNestedArray.cpp
createNestedObject.cpp
BasicJsonDocument.cpp
DynamicJsonDocument.cpp
macros.cpp
memoryUsage.cpp
Expand Down
210 changes: 210 additions & 0 deletions extras/tests/Deprecated/containsKey.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License

#include <ArduinoJson.h>
#include <catch.hpp>

#include "Literals.hpp"

TEST_CASE("JsonDocument::containsKey()") {
JsonDocument doc;

SECTION("returns true on object") {
doc["hello"] = "world";

REQUIRE(doc.containsKey("hello") == true);
}

SECTION("returns true when value is null") {
doc["hello"] = static_cast<const char*>(0);

REQUIRE(doc.containsKey("hello") == true);
}

SECTION("returns true when key is a std::string") {
doc["hello"] = "world";

REQUIRE(doc.containsKey("hello"_s) == true);
}

SECTION("returns false on object") {
doc["world"] = "hello";

REQUIRE(doc.containsKey("hello") == false);
}

SECTION("returns false on array") {
doc.add("hello");

REQUIRE(doc.containsKey("hello") == false);
}

SECTION("returns false on null") {
REQUIRE(doc.containsKey("hello") == false);
}

SECTION("support JsonVariant") {
doc["hello"] = "world";
doc["key"] = "hello";

REQUIRE(doc.containsKey(doc["key"]) == true);
REQUIRE(doc.containsKey(doc["foo"]) == false);
}
}

TEST_CASE("MemberProxy::containsKey()") {
JsonDocument doc;
auto mp = doc["hello"];

SECTION("containsKey(const char*)") {
mp["key"] = "value";

REQUIRE(mp.containsKey("key") == true);
REQUIRE(mp.containsKey("key") == true);
}

SECTION("containsKey(std::string)") {
mp["key"] = "value";

REQUIRE(mp.containsKey("key"_s) == true);
REQUIRE(mp.containsKey("key"_s) == true);
}
}

TEST_CASE("JsonObject::containsKey()") {
JsonDocument doc;
JsonObject obj = doc.to<JsonObject>();
obj["hello"] = 42;

SECTION("returns true only if key is present") {
REQUIRE(false == obj.containsKey("world"));
REQUIRE(true == obj.containsKey("hello"));
}

SECTION("returns false after remove()") {
obj.remove("hello");

REQUIRE(false == obj.containsKey("hello"));
}

#ifdef HAS_VARIABLE_LENGTH_ARRAY
SECTION("key is a VLA") {
size_t i = 16;
char vla[i];
strcpy(vla, "hello");

REQUIRE(true == obj.containsKey(vla));
}
#endif

SECTION("key is a JsonVariant") {
doc["key"] = "hello";
REQUIRE(true == obj.containsKey(obj["key"]));
REQUIRE(false == obj.containsKey(obj["hello"]));
}

SECTION("std::string") {
REQUIRE(true == obj.containsKey("hello"_s));
}

SECTION("unsigned char[]") {
unsigned char key[] = "hello";
REQUIRE(true == obj.containsKey(key));
}
}

TEST_CASE("JsonObjectConst::containsKey()") {
JsonDocument doc;
doc["hello"] = 42;
auto obj = doc.as<JsonObjectConst>();

SECTION("supports const char*") {
REQUIRE(false == obj.containsKey("world"));
REQUIRE(true == obj.containsKey("hello"));
}

SECTION("supports std::string") {
REQUIRE(false == obj.containsKey("world"_s));
REQUIRE(true == obj.containsKey("hello"_s));
}

#ifdef HAS_VARIABLE_LENGTH_ARRAY
SECTION("supports VLA") {
size_t i = 16;
char vla[i];
strcpy(vla, "hello");

REQUIRE(true == obj.containsKey(vla));
}
#endif

SECTION("supports JsonVariant") {
doc["key"] = "hello";
REQUIRE(true == obj.containsKey(obj["key"]));
REQUIRE(false == obj.containsKey(obj["hello"]));
}
}

TEST_CASE("JsonVariant::containsKey()") {
JsonDocument doc;
JsonVariant var = doc.to<JsonVariant>();

SECTION("returns false is unbound") {
CHECK_FALSE(JsonVariant().containsKey("hello"));
}

SECTION("containsKey(const char*)") {
var["hello"] = "world";

REQUIRE(var.containsKey("hello") == true);
REQUIRE(var.containsKey("world") == false);
}

SECTION("containsKey(std::string)") {
var["hello"] = "world";

REQUIRE(var.containsKey("hello"_s) == true);
REQUIRE(var.containsKey("world"_s) == false);
}

SECTION("containsKey(JsonVariant)") {
var["hello"] = "world";
var["key"] = "hello";

REQUIRE(var.containsKey(doc["key"]) == true);
REQUIRE(var.containsKey(doc["foo"]) == false);
}
}

TEST_CASE("JsonVariantConst::containsKey()") {
JsonDocument doc;
doc["hello"] = "world";
JsonVariantConst var = doc.as<JsonVariant>();

SECTION("support const char*") {
REQUIRE(var.containsKey("hello") == true);
REQUIRE(var.containsKey("world") == false);
}

SECTION("support std::string") {
REQUIRE(var.containsKey("hello"_s) == true);
REQUIRE(var.containsKey("world"_s) == false);
}

#ifdef HAS_VARIABLE_LENGTH_ARRAY
SECTION("supports VLA") {
size_t i = 16;
char vla[i];
strcpy(vla, "hello");

REQUIRE(true == var.containsKey(vla));
}
#endif

SECTION("support JsonVariant") {
doc["key"] = "hello";
REQUIRE(var.containsKey(var["key"]) == true);
REQUIRE(var.containsKey(var["foo"]) == false);
}
}
1 change: 0 additions & 1 deletion extras/tests/JsonDocument/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ add_executable(JsonDocumentTests
clear.cpp
compare.cpp
constructor.cpp
containsKey.cpp
ElementProxy.cpp
isNull.cpp
issue1120.cpp
Expand Down
19 changes: 0 additions & 19 deletions extras/tests/JsonDocument/MemberProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,25 +93,6 @@ TEST_CASE("MemberProxy::operator==()") {
}
}

TEST_CASE("MemberProxy::containsKey()") {
JsonDocument doc;
MemberProxy mp = doc["hello"];

SECTION("containsKey(const char*)") {
mp["key"] = "value";

REQUIRE(mp.containsKey("key") == true);
REQUIRE(mp.containsKey("key") == true);
}

SECTION("containsKey(std::string)") {
mp["key"] = "value";

REQUIRE(mp.containsKey("key"_s) == true);
REQUIRE(mp.containsKey("key"_s) == true);
}
}

TEST_CASE("MemberProxy::operator|()") {
JsonDocument doc;

Expand Down
54 changes: 0 additions & 54 deletions extras/tests/JsonDocument/containsKey.cpp

This file was deleted.

1 change: 0 additions & 1 deletion extras/tests/JsonObject/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
add_executable(JsonObjectTests
clear.cpp
compare.cpp
containsKey.cpp
equals.cpp
isNull.cpp
iterator.cpp
Expand Down
39 changes: 0 additions & 39 deletions extras/tests/JsonObject/containsKey.cpp

This file was deleted.

Loading

0 comments on commit d92eee8

Please sign in to comment.