allow oatpp::Any to parse directly to UInt64 or Int64

This commit is contained in:
Christian Lang 2021-12-13 10:39:43 +01:00
parent 4a40edc0c3
commit 24a2af532a
4 changed files with 80 additions and 3 deletions

View File

@ -477,5 +477,20 @@ std::string Utils::parseStringToStdString(ParsingCaret& caret){
}
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;
}
}}}

View File

@ -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;
@ -128,6 +133,13 @@ public:
*/
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);
};
}}}

View File

@ -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();
}

View File

@ -77,6 +77,14 @@ class Test4 : public oatpp::DTO {
};
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<oatpp::Object<AnyDto>>(R"({"any":"my_string"})");
OATPP_ASSERT(dto);
OATPP_ASSERT(dto->any.getStoredType() == String::Class::getType());
OATPP_ASSERT(dto->any.retrieve<String>() == "my_string");
}
OATPP_LOGD(TAG, "Any: Boolean")
{
auto dto = mapper->readFromString<oatpp::Object<AnyDto>>(R"({"any":false})");
OATPP_ASSERT(dto);
OATPP_ASSERT(dto->any.getStoredType() == Boolean::Class::getType());
OATPP_ASSERT(dto->any.retrieve<Boolean>() == false);
}
OATPP_LOGD(TAG, "Any: Float")
{
auto dto = mapper->readFromString<oatpp::Object<AnyDto>>(R"({"any":1.23456789,"another":1.1})");
OATPP_ASSERT(dto);
OATPP_ASSERT(dto->any.getStoredType() == Float64::Class::getType());
OATPP_ASSERT(dto->any.retrieve<Float64>() == 1.23456789);
}
OATPP_LOGD(TAG, "Any: Unsigned Integer")
{
auto dto = mapper->readFromString<oatpp::Object<AnyDto>>(R"({"any":12345678901234567890,"another":1.1})");
OATPP_ASSERT(dto);
OATPP_ASSERT(dto->any.getStoredType() == UInt64::Class::getType());
OATPP_ASSERT(dto->any.retrieve<UInt64>() == 12345678901234567890u);
}
OATPP_LOGD(TAG, "Any: Signed Integer")
{
auto dto = mapper->readFromString<oatpp::Object<AnyDto>>(R"({"any":-1234567890,"another":1.1})");
OATPP_ASSERT(dto);
OATPP_ASSERT(dto->any.getStoredType() == Int64::Class::getType());
OATPP_ASSERT(dto->any.retrieve<Int64>() == -1234567890);
}
}
}}}}}