Selaa lähdekoodia

Merge pull request #529 from langchr86/fix/any_can_parse_integer

allow oatpp::Any to parse directly to UInt64 or Int64
Leonid Stryzhevskyi 2 vuotta sitten
vanhempi
commit
17c655a473

+ 16 - 1
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;
+}
   
 }}}

+ 12 - 0
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);
   
 };
   

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

+ 45 - 1
test/oatpp/parser/json/mapping/DeserializerTest.cpp

@@ -76,7 +76,15 @@ class Test4 : public oatpp::DTO {
   DTO_FIELD(Fields<Object<EmptyDto>>, 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<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);
+  }
+
 }
   
 }}}}}