mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Allowed non-quoted key to contain underscores (fixes #665)
This commit is contained in:
		| @@ -5,6 +5,7 @@ HEAD | |||||||
| ---- | ---- | ||||||
|  |  | ||||||
| * Fixed `JsonVariant::operator|(int)` that returned the default value if the variant contained a double (issue #675) | * Fixed `JsonVariant::operator|(int)` that returned the default value if the variant contained a double (issue #675) | ||||||
|  | * Allowed non-quoted key to contain underscores (issue #665) | ||||||
|  |  | ||||||
| v5.13.0 | v5.13.0 | ||||||
| ------- | ------- | ||||||
|   | |||||||
| @@ -50,13 +50,13 @@ class JsonParser { | |||||||
|   inline bool parseObjectTo(JsonVariant *destination); |   inline bool parseObjectTo(JsonVariant *destination); | ||||||
|   inline bool parseStringTo(JsonVariant *destination); |   inline bool parseStringTo(JsonVariant *destination); | ||||||
|  |  | ||||||
|   static inline bool isInRange(char c, char min, char max) { |   static inline bool isBetween(char c, char min, char max) { | ||||||
|     return min <= c && c <= max; |     return min <= c && c <= max; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static inline bool isLetterOrNumber(char c) { |   static inline bool canBeInNonQuotedString(char c) { | ||||||
|     return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') || |     return isBetween(c, '0', '9') || isBetween(c, '_', 'z') || | ||||||
|            isInRange(c, 'A', 'Z') || c == '+' || c == '-' || c == '.'; |            isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.'; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static inline bool isQuote(char c) { |   static inline bool isQuote(char c) { | ||||||
| @@ -99,5 +99,5 @@ inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser( | |||||||
|   return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json, |   return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json, | ||||||
|                                                              nestingLimit); |                                                              nestingLimit); | ||||||
| } | } | ||||||
| } | }  // namespace Internals | ||||||
| } | }  // namespace ArduinoJson | ||||||
|   | |||||||
| @@ -167,7 +167,7 @@ ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() { | |||||||
|     } |     } | ||||||
|   } else {  // no quotes |   } else {  // no quotes | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       if (!isLetterOrNumber(c)) break; |       if (!canBeInNonQuotedString(c)) break; | ||||||
|       _reader.move(); |       _reader.move(); | ||||||
|       str.append(c); |       str.append(c); | ||||||
|       c = _reader.current(); |       c = _reader.current(); | ||||||
|   | |||||||
| @@ -8,148 +8,163 @@ | |||||||
| TEST_CASE("JsonBuffer::parseObject()") { | TEST_CASE("JsonBuffer::parseObject()") { | ||||||
|   DynamicJsonBuffer jb; |   DynamicJsonBuffer jb; | ||||||
|  |  | ||||||
|   SECTION("EmptyObject") { |   SECTION("An empty object") { | ||||||
|     JsonObject& obj = jb.parseObject("{}"); |     JsonObject& obj = jb.parseObject("{}"); | ||||||
|     REQUIRE(obj.success()); |     REQUIRE(obj.success()); | ||||||
|     REQUIRE(obj.size() == 0); |     REQUIRE(obj.size() == 0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("MissingOpeningBrace") { |   SECTION("Quotes") { | ||||||
|     JsonObject& obj = jb.parseObject("}"); |     SECTION("Double quotes") { | ||||||
|     REQUIRE_FALSE(obj.success()); |       JsonObject& obj = jb.parseObject("{\"key\":\"value\"}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 1); | ||||||
|  |       REQUIRE(obj["key"] == "value"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("Single quotes") { | ||||||
|  |       JsonObject& obj = jb.parseObject("{'key':'value'}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 1); | ||||||
|  |       REQUIRE(obj["key"] == "value"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("No quotes") { | ||||||
|  |       JsonObject& obj = jb.parseObject("{key:value}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 1); | ||||||
|  |       REQUIRE(obj["key"] == "value"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("No quotes, allow underscore in key") { | ||||||
|  |       JsonObject& obj = jb.parseObject("{_k_e_y_:42}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 1); | ||||||
|  |       REQUIRE(obj["_k_e_y_"] == 42); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("MissingClosingBrace") { |   SECTION("Spaces") { | ||||||
|     JsonObject& obj = jb.parseObject("{"); |     SECTION("Before the key") { | ||||||
|     REQUIRE_FALSE(obj.success()); |       JsonObject& obj = jb.parseObject("{ \"key\":\"value\"}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 1); | ||||||
|  |       REQUIRE(obj["key"] == "value"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("After the key") { | ||||||
|  |       JsonObject& obj = jb.parseObject("{\"key\" :\"value\"}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 1); | ||||||
|  |       REQUIRE(obj["key"] == "value"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("Before the value") { | ||||||
|  |       JsonObject& obj = jb.parseObject("{\"key\": \"value\"}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 1); | ||||||
|  |       REQUIRE(obj["key"] == "value"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("After the value") { | ||||||
|  |       JsonObject& obj = jb.parseObject("{\"key\":\"value\" }"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 1); | ||||||
|  |       REQUIRE(obj["key"] == "value"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("Before the colon") { | ||||||
|  |       JsonObject& obj = | ||||||
|  |           jb.parseObject("{\"key1\":\"value1\" ,\"key2\":\"value2\"}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 2); | ||||||
|  |       REQUIRE(obj["key1"] == "value1"); | ||||||
|  |       REQUIRE(obj["key2"] == "value2"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("After the colon") { | ||||||
|  |       JsonObject& obj = | ||||||
|  |           jb.parseObject("{\"key1\":\"value1\" ,\"key2\":\"value2\"}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 2); | ||||||
|  |       REQUIRE(obj["key1"] == "value1"); | ||||||
|  |       REQUIRE(obj["key2"] == "value2"); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("MissingColonAndValue") { |   SECTION("Values types") { | ||||||
|     JsonObject& obj = jb.parseObject("{\"key\"}"); |     SECTION("String") { | ||||||
|     REQUIRE_FALSE(obj.success()); |       JsonObject& obj = | ||||||
|  |           jb.parseObject("{\"key1\":\"value1\",\"key2\":\"value2\"}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 2); | ||||||
|  |       REQUIRE(obj["key1"] == "value1"); | ||||||
|  |       REQUIRE(obj["key2"] == "value2"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("Integer") { | ||||||
|  |       JsonObject& obj = jb.parseObject("{\"key1\":42,\"key2\":-42}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 2); | ||||||
|  |       REQUIRE(obj["key1"] == 42); | ||||||
|  |       REQUIRE(obj["key2"] == -42); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("Double") { | ||||||
|  |       JsonObject& obj = jb.parseObject("{\"key1\":12.345,\"key2\":-7E89}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 2); | ||||||
|  |       REQUIRE(obj["key1"] == 12.345); | ||||||
|  |       REQUIRE(obj["key2"] == -7E89); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("Booleans") { | ||||||
|  |       JsonObject& obj = jb.parseObject("{\"key1\":true,\"key2\":false}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 2); | ||||||
|  |       REQUIRE(obj["key1"] == true); | ||||||
|  |       REQUIRE(obj["key2"] == false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("Null") { | ||||||
|  |       JsonObject& obj = jb.parseObject("{\"key1\":null,\"key2\":null}"); | ||||||
|  |       REQUIRE(obj.success()); | ||||||
|  |       REQUIRE(obj.size() == 2); | ||||||
|  |       REQUIRE(obj["key1"].as<char*>() == 0); | ||||||
|  |       REQUIRE(obj["key2"].as<char*>() == 0); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("MissingQuotesAndColonAndValue") { |   SECTION("Misc") { | ||||||
|     JsonObject& obj = jb.parseObject("{key}"); |     SECTION("The opening brace is missing") { | ||||||
|     REQUIRE_FALSE(obj.success()); |       JsonObject& obj = jb.parseObject("}"); | ||||||
|   } |       REQUIRE_FALSE(obj.success()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|   SECTION("OneString") { |     SECTION("The closing brace is missing") { | ||||||
|     JsonObject& obj = jb.parseObject("{\"key\":\"value\"}"); |       JsonObject& obj = jb.parseObject("{"); | ||||||
|     REQUIRE(obj.success()); |       REQUIRE_FALSE(obj.success()); | ||||||
|     REQUIRE(obj.size() == 1); |     } | ||||||
|     REQUIRE(obj["key"] == "value"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("OneStringSingleQuotes") { |     SECTION("A quoted key without value") { | ||||||
|     JsonObject& obj = jb.parseObject("{'key':'value'}"); |       JsonObject& obj = jb.parseObject("{\"key\"}"); | ||||||
|     REQUIRE(obj.success()); |       REQUIRE_FALSE(obj.success()); | ||||||
|     REQUIRE(obj.size() == 1); |     } | ||||||
|     REQUIRE(obj["key"] == "value"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("OneStringNoQuotes") { |     SECTION("A non-quoted key without value") { | ||||||
|     JsonObject& obj = jb.parseObject("{key:value}"); |       JsonObject& obj = jb.parseObject("{key}"); | ||||||
|     REQUIRE(obj.success()); |       REQUIRE_FALSE(obj.success()); | ||||||
|     REQUIRE(obj.size() == 1); |     } | ||||||
|     REQUIRE(obj["key"] == "value"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("OneStringSpaceBeforeKey") { |     SECTION("A dangling comma") { | ||||||
|     JsonObject& obj = jb.parseObject("{ \"key\":\"value\"}"); |       JsonObject& obj = jb.parseObject("{\"key1\":\"value1\",}"); | ||||||
|     REQUIRE(obj.success()); |       REQUIRE_FALSE(obj.success()); | ||||||
|     REQUIRE(obj.size() == 1); |       REQUIRE(obj.size() == 0); | ||||||
|     REQUIRE(obj["key"] == "value"); |     } | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("OneStringSpaceAfterKey") { |     SECTION("null as a key") { | ||||||
|     JsonObject& obj = jb.parseObject("{\"key\" :\"value\"}"); |       JsonObject& obj = jb.parseObject("null:\"value\"}"); | ||||||
|     REQUIRE(obj.success()); |       REQUIRE_FALSE(obj.success()); | ||||||
|     REQUIRE(obj.size() == 1); |     } | ||||||
|     REQUIRE(obj["key"] == "value"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("OneStringSpaceBeforeValue") { |  | ||||||
|     JsonObject& obj = jb.parseObject("{\"key\": \"value\"}"); |  | ||||||
|     REQUIRE(obj.success()); |  | ||||||
|     REQUIRE(obj.size() == 1); |  | ||||||
|     REQUIRE(obj["key"] == "value"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("OneStringSpaceAfterValue") { |  | ||||||
|     JsonObject& obj = jb.parseObject("{\"key\":\"value\" }"); |  | ||||||
|     REQUIRE(obj.success()); |  | ||||||
|     REQUIRE(obj.size() == 1); |  | ||||||
|     REQUIRE(obj["key"] == "value"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("TwoStrings") { |  | ||||||
|     JsonObject& obj = |  | ||||||
|         jb.parseObject("{\"key1\":\"value1\",\"key2\":\"value2\"}"); |  | ||||||
|     REQUIRE(obj.success()); |  | ||||||
|     REQUIRE(obj.size() == 2); |  | ||||||
|     REQUIRE(obj["key1"] == "value1"); |  | ||||||
|     REQUIRE(obj["key2"] == "value2"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("TwoStringsSpaceBeforeComma") { |  | ||||||
|     JsonObject& obj = |  | ||||||
|         jb.parseObject("{\"key1\":\"value1\" ,\"key2\":\"value2\"}"); |  | ||||||
|     REQUIRE(obj.success()); |  | ||||||
|     REQUIRE(obj.size() == 2); |  | ||||||
|     REQUIRE(obj["key1"] == "value1"); |  | ||||||
|     REQUIRE(obj["key2"] == "value2"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("TwoStringsSpaceAfterComma") { |  | ||||||
|     JsonObject& obj = |  | ||||||
|         jb.parseObject("{\"key1\":\"value1\" ,\"key2\":\"value2\"}"); |  | ||||||
|     REQUIRE(obj.success()); |  | ||||||
|     REQUIRE(obj.size() == 2); |  | ||||||
|     REQUIRE(obj["key1"] == "value1"); |  | ||||||
|     REQUIRE(obj["key2"] == "value2"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("EndingWithAComma") { |  | ||||||
|     JsonObject& obj = jb.parseObject("{\"key1\":\"value1\",}"); |  | ||||||
|     REQUIRE_FALSE(obj.success()); |  | ||||||
|     REQUIRE(obj.size() == 0); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("TwoIntergers") { |  | ||||||
|     JsonObject& obj = jb.parseObject("{\"key1\":42,\"key2\":-42}"); |  | ||||||
|     REQUIRE(obj.success()); |  | ||||||
|     REQUIRE(obj.size() == 2); |  | ||||||
|     REQUIRE(obj["key1"] == 42); |  | ||||||
|     REQUIRE(obj["key2"] == -42); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("TwoDoubles") { |  | ||||||
|     JsonObject& obj = jb.parseObject("{\"key1\":12.345,\"key2\":-7E89}"); |  | ||||||
|     REQUIRE(obj.success()); |  | ||||||
|     REQUIRE(obj.size() == 2); |  | ||||||
|     REQUIRE(obj["key1"] == 12.345); |  | ||||||
|     REQUIRE(obj["key2"] == -7E89); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("TwoBooleans") { |  | ||||||
|     JsonObject& obj = jb.parseObject("{\"key1\":true,\"key2\":false}"); |  | ||||||
|     REQUIRE(obj.success()); |  | ||||||
|     REQUIRE(obj.size() == 2); |  | ||||||
|     REQUIRE(obj["key1"] == true); |  | ||||||
|     REQUIRE(obj["key2"] == false); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("TwoNulls") { |  | ||||||
|     JsonObject& obj = jb.parseObject("{\"key1\":null,\"key2\":null}"); |  | ||||||
|     REQUIRE(obj.success()); |  | ||||||
|     REQUIRE(obj.size() == 2); |  | ||||||
|     REQUIRE(obj["key1"].as<char*>() == 0); |  | ||||||
|     REQUIRE(obj["key2"].as<char*>() == 0); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("NullForKey") { |  | ||||||
|     JsonObject& obj = jb.parseObject("null:\"value\"}"); |  | ||||||
|     REQUIRE_FALSE(obj.success()); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user