subscript.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2025, Benoit BLANCHON
  3. // MIT License
  4. #include <ArduinoJson.h>
  5. #include <catch.hpp>
  6. #include "Allocators.hpp"
  7. #include "Literals.hpp"
  8. TEST_CASE("JsonObject::operator[]") {
  9. SpyingAllocator spy;
  10. JsonDocument doc(&spy);
  11. JsonObject obj = doc.to<JsonObject>();
  12. SECTION("int") {
  13. obj["hello"] = 123;
  14. REQUIRE(123 == obj["hello"].as<int>());
  15. REQUIRE(true == obj["hello"].is<int>());
  16. REQUIRE(false == obj["hello"].is<bool>());
  17. }
  18. SECTION("volatile int") { // issue #415
  19. volatile int i = 123;
  20. obj["hello"] = i;
  21. REQUIRE(123 == obj["hello"].as<int>());
  22. REQUIRE(true == obj["hello"].is<int>());
  23. REQUIRE(false == obj["hello"].is<bool>());
  24. }
  25. SECTION("double") {
  26. obj["hello"] = 123.45;
  27. REQUIRE(true == obj["hello"].is<double>());
  28. REQUIRE(false == obj["hello"].is<long>());
  29. REQUIRE(123.45 == obj["hello"].as<double>());
  30. }
  31. SECTION("bool") {
  32. obj["hello"] = true;
  33. REQUIRE(true == obj["hello"].is<bool>());
  34. REQUIRE(false == obj["hello"].is<long>());
  35. REQUIRE(true == obj["hello"].as<bool>());
  36. }
  37. SECTION("const char*") {
  38. obj["hello"] = "h3110";
  39. REQUIRE(true == obj["hello"].is<const char*>());
  40. REQUIRE(false == obj["hello"].is<long>());
  41. REQUIRE("h3110"_s == obj["hello"].as<const char*>());
  42. }
  43. SECTION("array") {
  44. JsonDocument doc2;
  45. JsonArray arr = doc2.to<JsonArray>();
  46. obj["hello"] = arr;
  47. REQUIRE(arr == obj["hello"].as<JsonArray>());
  48. REQUIRE(true == obj["hello"].is<JsonArray>());
  49. REQUIRE(false == obj["hello"].is<JsonObject>());
  50. }
  51. SECTION("object") {
  52. JsonDocument doc2;
  53. JsonObject obj2 = doc2.to<JsonObject>();
  54. obj["hello"] = obj2;
  55. REQUIRE(obj2 == obj["hello"].as<JsonObject>());
  56. REQUIRE(true == obj["hello"].is<JsonObject>());
  57. REQUIRE(false == obj["hello"].is<JsonArray>());
  58. }
  59. SECTION("array subscript") {
  60. JsonDocument doc2;
  61. JsonArray arr = doc2.to<JsonArray>();
  62. arr.add(42);
  63. obj["a"] = arr[0];
  64. REQUIRE(42 == obj["a"]);
  65. }
  66. SECTION("object subscript") {
  67. JsonDocument doc2;
  68. JsonObject obj2 = doc2.to<JsonObject>();
  69. obj2["x"] = 42;
  70. obj["a"] = obj2["x"];
  71. REQUIRE(42 == obj["a"]);
  72. }
  73. SECTION("char key[]") { // issue #423
  74. char key[] = "hello";
  75. obj[key] = 42;
  76. REQUIRE(42 == obj[key]);
  77. }
  78. SECTION("string literals") {
  79. obj["hello"] = "world";
  80. REQUIRE(spy.log() == AllocatorLog{
  81. Allocate(sizeofPool()),
  82. Allocate(sizeofStaticStringPool()),
  83. });
  84. }
  85. SECTION("should duplicate char* value") {
  86. obj["hello"] = const_cast<char*>("world");
  87. REQUIRE(spy.log() == AllocatorLog{
  88. Allocate(sizeofPool()),
  89. Allocate(sizeofStaticStringPool()),
  90. Allocate(sizeofString("world")),
  91. });
  92. }
  93. SECTION("should duplicate char* key") {
  94. obj[const_cast<char*>("hello")] = 42;
  95. REQUIRE(spy.log() == AllocatorLog{
  96. Allocate(sizeofPool()),
  97. Allocate(sizeofString("hello")),
  98. });
  99. }
  100. SECTION("should duplicate char* key&value") {
  101. obj[const_cast<char*>("hello")] = const_cast<char*>("world");
  102. REQUIRE(spy.log() == AllocatorLog{
  103. Allocate(sizeofPool()),
  104. Allocate(sizeofString("hello")),
  105. Allocate(sizeofString("world")),
  106. });
  107. }
  108. SECTION("should duplicate std::string value") {
  109. obj["hello"] = "world"_s;
  110. REQUIRE(spy.log() == AllocatorLog{
  111. Allocate(sizeofPool()),
  112. Allocate(sizeofStaticStringPool()),
  113. Allocate(sizeofString("world")),
  114. });
  115. }
  116. SECTION("should duplicate std::string key") {
  117. obj["hello"_s] = 42;
  118. REQUIRE(spy.log() == AllocatorLog{
  119. Allocate(sizeofPool()),
  120. Allocate(sizeofString("hello")),
  121. });
  122. }
  123. SECTION("should duplicate std::string key&value") {
  124. obj["hello"_s] = "world"_s;
  125. REQUIRE(spy.log() == AllocatorLog{
  126. Allocate(sizeofPool()),
  127. Allocate(sizeofString("hello")),
  128. Allocate(sizeofString("world")),
  129. });
  130. }
  131. SECTION("should duplicate a non-static JsonString key") {
  132. obj[JsonString("hello", false)] = 42;
  133. REQUIRE(spy.log() == AllocatorLog{
  134. Allocate(sizeofPool()),
  135. Allocate(sizeofString("hello")),
  136. });
  137. }
  138. SECTION("should not duplicate a static JsonString key") {
  139. obj[JsonString("hello", true)] = 42;
  140. REQUIRE(spy.log() == AllocatorLog{
  141. Allocate(sizeofPool()),
  142. Allocate(sizeofStaticStringPool()),
  143. });
  144. }
  145. SECTION("should ignore null key") {
  146. // object must have a value to make a call to strcmp()
  147. obj["dummy"] = 42;
  148. const char* null = 0;
  149. obj[null] = 666;
  150. REQUIRE(obj.size() == 1);
  151. REQUIRE(obj[null] == null);
  152. }
  153. SECTION("obj[key].to<JsonArray>()") {
  154. JsonArray arr = obj["hello"].to<JsonArray>();
  155. REQUIRE(arr.isNull() == false);
  156. }
  157. #if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
  158. !defined(SUBSCRIPT_CONFLICTS_WITH_BUILTIN_OPERATOR)
  159. SECTION("obj[VLA] = str") {
  160. size_t i = 16;
  161. char vla[i];
  162. strcpy(vla, "hello");
  163. obj[vla] = "world";
  164. REQUIRE("world"_s == obj["hello"]);
  165. }
  166. SECTION("obj[str] = VLA") { // issue #416
  167. size_t i = 32;
  168. char vla[i];
  169. strcpy(vla, "world");
  170. obj["hello"] = vla;
  171. REQUIRE("world"_s == obj["hello"].as<const char*>());
  172. }
  173. SECTION("obj.set(VLA, str)") {
  174. size_t i = 16;
  175. char vla[i];
  176. strcpy(vla, "hello");
  177. obj[vla] = "world";
  178. REQUIRE("world"_s == obj["hello"]);
  179. }
  180. SECTION("obj.set(str, VLA)") {
  181. size_t i = 32;
  182. char vla[i];
  183. strcpy(vla, "world");
  184. obj["hello"].set(vla);
  185. REQUIRE("world"_s == obj["hello"].as<const char*>());
  186. }
  187. SECTION("obj[VLA]") {
  188. size_t i = 16;
  189. char vla[i];
  190. strcpy(vla, "hello");
  191. deserializeJson(doc, "{\"hello\":\"world\"}");
  192. obj = doc.as<JsonObject>();
  193. REQUIRE("world"_s == obj[vla]);
  194. }
  195. #endif
  196. SECTION("chain") {
  197. obj["hello"]["world"] = 123;
  198. REQUIRE(123 == obj["hello"]["world"].as<int>());
  199. REQUIRE(true == obj["hello"]["world"].is<int>());
  200. REQUIRE(false == obj["hello"]["world"].is<bool>());
  201. }
  202. SECTION("JsonVariant") {
  203. obj["hello"] = "world";
  204. obj["a\0b"_s] = "ABC";
  205. doc["key1"] = "hello";
  206. doc["key2"] = "a\0b"_s;
  207. doc["key3"] = "foo";
  208. REQUIRE(obj[obj["key1"]] == "world");
  209. REQUIRE(obj[obj["key2"]] == "ABC");
  210. REQUIRE(obj[obj["key3"]] == nullptr);
  211. REQUIRE(obj[obj["key4"]] == nullptr);
  212. }
  213. }