mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-16 12:02:14 +02: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