From 24a2af532a54e8c0eedd15f2f85615b3214d40aa Mon Sep 17 00:00:00 2001 From: Christian Lang Date: Mon, 13 Dec 2021 10:39:43 +0100 Subject: [PATCH] allow oatpp::Any to parse directly to UInt64 or Int64 --- src/oatpp/parser/json/Utils.cpp | 17 ++++++- src/oatpp/parser/json/Utils.hpp | 12 +++++ .../parser/json/mapping/Deserializer.cpp | 8 +++- .../parser/json/mapping/DeserializerTest.cpp | 46 ++++++++++++++++++- 4 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/oatpp/parser/json/Utils.cpp b/src/oatpp/parser/json/Utils.cpp index d1c8729b..c0d29e8e 100644 --- a/src/oatpp/parser/json/Utils.cpp +++ b/src/oatpp/parser/json/Utils.cpp @@ -476,6 +476,21 @@ std::string Utils::parseStringToStdString(ParsingCaret& caret){ return ""; } - + +bool Utils::findDecimalSeparatorInCurrentNumber(ParsingCaret& caret) { + parser::Caret::StateSaveGuard stateGuard(caret); + + // search until a decimal separator is found or no more digits are found or no more data available + while(caret.canContinue()) { + if (caret.isAtChar(JSON_DECIMAL_SEPARATOR)) { + return true; + } + if (!caret.isAtDigitChar()) { + return false; + } + caret.inc(); + } + return false; +} }}} diff --git a/src/oatpp/parser/json/Utils.hpp b/src/oatpp/parser/json/Utils.hpp index 9ce262c2..e4e4123f 100644 --- a/src/oatpp/parser/json/Utils.hpp +++ b/src/oatpp/parser/json/Utils.hpp @@ -61,6 +61,11 @@ public: */ static constexpr v_int64 ERROR_CODE_PARSER_QUOTE_EXPECTED = 3; + /** + * Character that is used as decimal separator in floating point string representations. + */ + static constexpr v_char8 JSON_DECIMAL_SEPARATOR = '.'; + public: typedef oatpp::String String; typedef oatpp::parser::Caret ParsingCaret; @@ -127,6 +132,13 @@ public: * @return - `std::string`. */ static std::string parseStringToStdString(ParsingCaret& caret); + + /** + * Search for a decimal separator in the to analyze number string. + * @param caret - buffer to search for the decimal separator. + * @return - if the analyzed word has been identified as floating point number. + */ + static bool findDecimalSeparatorInCurrentNumber(ParsingCaret& caret); }; diff --git a/src/oatpp/parser/json/mapping/Deserializer.cpp b/src/oatpp/parser/json/mapping/Deserializer.cpp index 2620083a..d755a8ef 100644 --- a/src/oatpp/parser/json/mapping/Deserializer.cpp +++ b/src/oatpp/parser/json/mapping/Deserializer.cpp @@ -212,7 +212,13 @@ oatpp::Void Deserializer::deserializeString(Deserializer* deserializer, parser:: } const data::mapping::type::Type* Deserializer::guessNumberType(oatpp::parser::Caret& caret) { - (void)caret; + if (!Utils::findDecimalSeparatorInCurrentNumber(caret)) { + if (*caret.getCurrData() == '-') { + return Int64::Class::getType(); + } else { + return UInt64::Class::getType(); + } + } return Float64::Class::getType(); } diff --git a/test/oatpp/parser/json/mapping/DeserializerTest.cpp b/test/oatpp/parser/json/mapping/DeserializerTest.cpp index f8c425d8..d27c5b92 100644 --- a/test/oatpp/parser/json/mapping/DeserializerTest.cpp +++ b/test/oatpp/parser/json/mapping/DeserializerTest.cpp @@ -76,7 +76,15 @@ class Test4 : public oatpp::DTO { DTO_FIELD(Fields>, map); }; - + +class AnyDto : public oatpp::DTO { + + DTO_INIT(AnyDto, DTO) + + DTO_FIELD(Any, any); + +}; + #include OATPP_CODEGEN_END(DTO) } @@ -175,6 +183,42 @@ void DeserializerTest::onRun(){ OATPP_ASSERT(obj4->list->size() == 0); OATPP_ASSERT(obj4->map->size() == 0); + OATPP_LOGD(TAG, "Any: String") + { + auto dto = mapper->readFromString>(R"({"any":"my_string"})"); + OATPP_ASSERT(dto); + OATPP_ASSERT(dto->any.getStoredType() == String::Class::getType()); + OATPP_ASSERT(dto->any.retrieve() == "my_string"); + } + OATPP_LOGD(TAG, "Any: Boolean") + { + auto dto = mapper->readFromString>(R"({"any":false})"); + OATPP_ASSERT(dto); + OATPP_ASSERT(dto->any.getStoredType() == Boolean::Class::getType()); + OATPP_ASSERT(dto->any.retrieve() == false); + } + OATPP_LOGD(TAG, "Any: Float") + { + auto dto = mapper->readFromString>(R"({"any":1.23456789,"another":1.1})"); + OATPP_ASSERT(dto); + OATPP_ASSERT(dto->any.getStoredType() == Float64::Class::getType()); + OATPP_ASSERT(dto->any.retrieve() == 1.23456789); + } + OATPP_LOGD(TAG, "Any: Unsigned Integer") + { + auto dto = mapper->readFromString>(R"({"any":12345678901234567890,"another":1.1})"); + OATPP_ASSERT(dto); + OATPP_ASSERT(dto->any.getStoredType() == UInt64::Class::getType()); + OATPP_ASSERT(dto->any.retrieve() == 12345678901234567890u); + } + OATPP_LOGD(TAG, "Any: Signed Integer") + { + auto dto = mapper->readFromString>(R"({"any":-1234567890,"another":1.1})"); + OATPP_ASSERT(dto); + OATPP_ASSERT(dto->any.getStoredType() == Int64::Class::getType()); + OATPP_ASSERT(dto->any.retrieve() == -1234567890); + } + } }}}}}