From a8032f81d904ea32605d25f93d833d67d310576d Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sat, 30 Apr 2016 09:47:53 +0200 Subject: [PATCH] Added `JsonVariant JsonBuffer::parse()` (issue #265) --- CHANGELOG.md | 1 + include/ArduinoJson/Internals/JsonParser.hpp | 6 ++ include/ArduinoJson/JsonBuffer.hpp | 15 ++++ src/JsonBuffer.cpp | 5 ++ test/JsonParser_Variant_Tests.cpp | 76 ++++++++++++++++++++ test/JsonVariant_As_Tests.cpp | 12 +++- test/JsonVariant_PrintTo_Tests.cpp | 6 +- test/JsonVariant_Undefined_Tests.cpp | 4 ++ 8 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 test/JsonParser_Variant_Tests.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 526c5744..206c83bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ HEAD ---- * Added custom implementation of `ftoa` (issues #266, #267, #269 and #270) +* Added `JsonVariant JsonBuffer::parse()` (issue #265) * Fixed `unsigned long` printed as `signed long` (issue #170) v5.2.0 diff --git a/include/ArduinoJson/Internals/JsonParser.hpp b/include/ArduinoJson/Internals/JsonParser.hpp index 2e435ab9..6f634c6c 100644 --- a/include/ArduinoJson/Internals/JsonParser.hpp +++ b/include/ArduinoJson/Internals/JsonParser.hpp @@ -27,6 +27,12 @@ class JsonParser { JsonArray &parseArray(); JsonObject &parseObject(); + JsonVariant parseVariant() { + JsonVariant result; + parseAnythingTo(&result); + return result; + } + private: bool skip(char charToSkip); diff --git a/include/ArduinoJson/JsonBuffer.hpp b/include/ArduinoJson/JsonBuffer.hpp index 9055e914..9cf2408a 100644 --- a/include/ArduinoJson/JsonBuffer.hpp +++ b/include/ArduinoJson/JsonBuffer.hpp @@ -94,6 +94,21 @@ class JsonBuffer { return parseObject(json.c_str(), nesting); } + // Generalized version of parseArray() and parseObject(), also works for + // integral types. + JsonVariant parse(char *json, uint8_t nestingLimit = DEFAULT_LIMIT); + + // Same with a const char*. + // With this overload, the JsonBuffer will make a copy of the string + JsonVariant parse(const char *json, uint8_t nesting = DEFAULT_LIMIT) { + return parse(strdup(json), nesting); + } + + // Same as above with a String class + JsonVariant parse(const String &json, uint8_t nesting = DEFAULT_LIMIT) { + return parse(json.c_str(), nesting); + } + // Duplicate a string char *strdup(const char *src) { return src ? strdup(src, strlen(src)) : NULL; diff --git a/src/JsonBuffer.cpp b/src/JsonBuffer.cpp index f0afb765..ba8a6953 100644 --- a/src/JsonBuffer.cpp +++ b/src/JsonBuffer.cpp @@ -34,6 +34,11 @@ JsonObject &JsonBuffer::parseObject(char *json, uint8_t nestingLimit) { return parser.parseObject(); } +JsonVariant JsonBuffer::parse(char *json, uint8_t nestingLimit) { + JsonParser parser(this, json, nestingLimit); + return parser.parseVariant(); +} + char *JsonBuffer::strdup(const char *source, size_t length) { size_t size = length + 1; char *dest = static_cast(alloc(size)); diff --git a/test/JsonParser_Variant_Tests.cpp b/test/JsonParser_Variant_Tests.cpp new file mode 100644 index 00000000..b87734dc --- /dev/null +++ b/test/JsonParser_Variant_Tests.cpp @@ -0,0 +1,76 @@ +// Copyright Benoit Blanchon 2014-2016 +// MIT License +// +// Arduino JSON library +// https://github.com/bblanchon/ArduinoJson +// If you like this project, please add a star! + +#include +#include + +class JsonParser_Variant_Test : public testing::Test { + protected: + void whenInputIs(const char* jsonString) { + strcpy(_jsonString, jsonString); + _result = _jsonBuffer.parse(_jsonString); + } + + template + void resultMustEqual(T expected) { + EXPECT_EQ(expected, _result.as()); + } + + void resultMustEqual(const char* expected) { + EXPECT_STREQ(expected, _result.as()); + } + + template + void resultTypeMustBe() { + EXPECT_TRUE(_result.is()); + } + + private: + DynamicJsonBuffer _jsonBuffer; + JsonVariant _result; + char _jsonString[256]; +}; + +TEST_F(JsonParser_Variant_Test, EmptyObject) { + whenInputIs("{}"); + resultTypeMustBe(); +} + +TEST_F(JsonParser_Variant_Test, EmptyArray) { + whenInputIs("[]"); + resultTypeMustBe(); +} + +TEST_F(JsonParser_Variant_Test, Integer) { + whenInputIs("42"); + resultTypeMustBe(); + resultMustEqual(42); +} + +TEST_F(JsonParser_Variant_Test, Double) { + whenInputIs("3.14"); + resultTypeMustBe(); + resultMustEqual(3.14); +} + +TEST_F(JsonParser_Variant_Test, String) { + whenInputIs("\"hello world\""); + resultTypeMustBe(); + resultMustEqual("hello world"); +} + +TEST_F(JsonParser_Variant_Test, True) { + whenInputIs("true"); + resultTypeMustBe(); + resultMustEqual(true); +} + +TEST_F(JsonParser_Variant_Test, False) { + whenInputIs("false"); + resultTypeMustBe(); + resultMustEqual(false); +} diff --git a/test/JsonVariant_As_Tests.cpp b/test/JsonVariant_As_Tests.cpp index f12d8931..205f04b3 100644 --- a/test/JsonVariant_As_Tests.cpp +++ b/test/JsonVariant_As_Tests.cpp @@ -32,6 +32,11 @@ TEST(JsonVariant_As_Tests, DoubleAsLong) { ASSERT_EQ(4L, variant.as()); } +TEST(JsonVariant_As_Tests, DoubleAsUnsigned) { + JsonVariant variant = 4.2; + ASSERT_EQ(4U, variant.as()); +} + TEST(JsonVariant_As_Tests, DoubleZeroAsBool) { JsonVariant variant = 0.0; ASSERT_FALSE(variant.as()); @@ -92,11 +97,16 @@ TEST(JsonVariant_As_Tests, LongZeroAsBool) { ASSERT_FALSE(variant.as()); } -TEST(JsonVariant_As_Tests, LongAsDouble) { +TEST(JsonVariant_As_Tests, PositiveLongAsDouble) { JsonVariant variant = 42L; ASSERT_EQ(42.0, variant.as()); } +TEST(JsonVariant_As_Tests, NegativeLongAsDouble) { + JsonVariant variant = -42L; + ASSERT_EQ(-42.0, variant.as()); +} + TEST(JsonVariant_As_Tests, LongAsString) { JsonVariant variant = 42L; ASSERT_EQ(String("42"), variant.as()); diff --git a/test/JsonVariant_PrintTo_Tests.cpp b/test/JsonVariant_PrintTo_Tests.cpp index 4597f082..ef6d055b 100644 --- a/test/JsonVariant_PrintTo_Tests.cpp +++ b/test/JsonVariant_PrintTo_Tests.cpp @@ -93,9 +93,9 @@ TEST_F(JsonVariant_PrintTo_Tests, Integer) { outputMustBe("42"); } -TEST_F(JsonVariant_PrintTo_Tests, Long) { - variant = 42L; - outputMustBe("42"); +TEST_F(JsonVariant_PrintTo_Tests, NegativeLong) { + variant = -42; + outputMustBe("-42"); } TEST_F(JsonVariant_PrintTo_Tests, UnsignedLong) { diff --git a/test/JsonVariant_Undefined_Tests.cpp b/test/JsonVariant_Undefined_Tests.cpp index 8c0e558d..05c66c95 100644 --- a/test/JsonVariant_Undefined_Tests.cpp +++ b/test/JsonVariant_Undefined_Tests.cpp @@ -17,6 +17,10 @@ TEST_F(JsonVariant_Undefined_Tests, AsLongReturns0) { EXPECT_EQ(0, variant.as()); } +TEST_F(JsonVariant_Undefined_Tests, AsUnsignedReturns0) { + EXPECT_EQ(0, variant.as()); +} + TEST_F(JsonVariant_Undefined_Tests, AsStringReturnsNull) { EXPECT_EQ(0, variant.asString()); }