json::ObjectMapper: use mapping::Tree for Deserialization

This commit is contained in:
Leonid Stryzhevskyi 2024-04-30 02:35:40 +03:00
parent 87af860824
commit 8137eba15e
11 changed files with 297 additions and 695 deletions

View File

@ -80,7 +80,7 @@ void ObjectToTreeMapper::setMapperMethod(const data::mapping::type::ClassId& cla
m_methods[id] = method;
}
void ObjectToTreeMapper::map(MappingState& state, const oatpp::Void& polymorph)
void ObjectToTreeMapper::map(MappingState& state, const oatpp::Void& polymorph) const
{
auto id = static_cast<v_uint32>(polymorph.getValueType()->classId.id);
auto& method = m_methods[id];
@ -101,7 +101,7 @@ void ObjectToTreeMapper::map(MappingState& state, const oatpp::Void& polymorph)
}
}
void ObjectToTreeMapper::mapString(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
void ObjectToTreeMapper::mapString(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
if(!polymorph) {
state.tree->setNull();
return;
@ -109,7 +109,7 @@ void ObjectToTreeMapper::mapString(ObjectToTreeMapper* mapper, MappingState& sta
state.tree->setString(oatpp::String(std::static_pointer_cast<std::string>(polymorph.getPtr()), oatpp::String::Class::getType()));
}
void ObjectToTreeMapper::mapAny(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
void ObjectToTreeMapper::mapAny(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
if(!polymorph) {
state.tree->setNull();
return;
@ -118,7 +118,7 @@ void ObjectToTreeMapper::mapAny(ObjectToTreeMapper* mapper, MappingState& state,
mapper->map(state, oatpp::Void(anyHandle->ptr, anyHandle->type));
}
void ObjectToTreeMapper::mapEnum(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
void ObjectToTreeMapper::mapEnum(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
if(!polymorph) {
state.tree->setNull();
@ -150,7 +150,7 @@ void ObjectToTreeMapper::mapEnum(ObjectToTreeMapper* mapper, MappingState& state
}
void ObjectToTreeMapper::mapCollection(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
void ObjectToTreeMapper::mapCollection(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
if(!polymorph) {
state.tree->setNull();
@ -196,7 +196,7 @@ void ObjectToTreeMapper::mapCollection(ObjectToTreeMapper* mapper, MappingState&
}
void ObjectToTreeMapper::mapMap(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
void ObjectToTreeMapper::mapMap(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
if(!polymorph) {
state.tree->setNull();
@ -243,7 +243,7 @@ void ObjectToTreeMapper::mapMap(ObjectToTreeMapper* mapper, MappingState& state,
}
void ObjectToTreeMapper::mapObject(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
void ObjectToTreeMapper::mapObject(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
if(!polymorph) {
state.tree->setNull();

View File

@ -52,11 +52,11 @@ public:
};
public:
typedef void (*MapperMethod)(ObjectToTreeMapper*, MappingState&, const oatpp::Void&);
typedef void (*MapperMethod)(const ObjectToTreeMapper*, MappingState&, const oatpp::Void&);
public:
template<class T>
static void mapPrimitive(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph){
static void mapPrimitive(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph){
(void) mapper;
if(polymorph){
state.tree->setValue<typename T::ObjectType>(* static_cast<typename T::ObjectType*>(polymorph.get()));
@ -65,14 +65,14 @@ public:
}
}
static void mapString(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapAny(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapEnum(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapString(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapAny(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapEnum(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapCollection(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapMap(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapCollection(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapMap(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapObject(ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
static void mapObject(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph);
private:
std::vector<MapperMethod> m_methods;
@ -82,7 +82,7 @@ public:
void setMapperMethod(const data::mapping::type::ClassId& classId, MapperMethod method);
void map(MappingState& state, const oatpp::Void& polymorph);
void map(MappingState& state, const oatpp::Void& polymorph) const;
};

View File

@ -80,7 +80,7 @@ void TreeToObjectMapper::setMapperMethod(const data::mapping::type::ClassId& cla
m_methods[id] = method;
}
oatpp::Void TreeToObjectMapper::map(MappingState& state, const Type* const type) {
oatpp::Void TreeToObjectMapper::map(MappingState& state, const Type* const type) const {
auto id = static_cast<v_uint32>(type->classId.id);
auto& method = m_methods[id];
if(method) {
@ -131,7 +131,7 @@ const Type* TreeToObjectMapper::guessType(const Tree& node) {
}
oatpp::Void TreeToObjectMapper::mapString(TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
oatpp::Void TreeToObjectMapper::mapString(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
(void) mapper;
(void) type;
@ -149,7 +149,7 @@ oatpp::Void TreeToObjectMapper::mapString(TreeToObjectMapper* mapper, MappingSta
}
oatpp::Void TreeToObjectMapper::mapAny(TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
oatpp::Void TreeToObjectMapper::mapAny(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
(void) type;
if(state.tree->isNull()){
return oatpp::Void(Any::Class::getType());
@ -164,7 +164,7 @@ oatpp::Void TreeToObjectMapper::mapAny(TreeToObjectMapper* mapper, MappingState&
return oatpp::Void(Any::Class::getType());
}
oatpp::Void TreeToObjectMapper::mapEnum(TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
oatpp::Void TreeToObjectMapper::mapEnum(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::PolymorphicDispatcher*>(
type->polymorphicDispatcher
@ -198,7 +198,7 @@ oatpp::Void TreeToObjectMapper::mapEnum(TreeToObjectMapper* mapper, MappingState
}
oatpp::Void TreeToObjectMapper::mapCollection(TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
oatpp::Void TreeToObjectMapper::mapCollection(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
if(state.tree->isNull()){
return oatpp::Void(type);
@ -242,7 +242,7 @@ oatpp::Void TreeToObjectMapper::mapCollection(TreeToObjectMapper* mapper, Mappin
}
oatpp::Void TreeToObjectMapper::mapMap(TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
oatpp::Void TreeToObjectMapper::mapMap(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
if(state.tree->isNull()){
return oatpp::Void(type);
@ -290,7 +290,7 @@ oatpp::Void TreeToObjectMapper::mapMap(TreeToObjectMapper* mapper, MappingState&
}
oatpp::Void TreeToObjectMapper::mapObject(TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
oatpp::Void TreeToObjectMapper::mapObject(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type) {
if(state.tree->isNull()){
return oatpp::Void(type);

View File

@ -50,11 +50,11 @@ public:
};
public:
typedef oatpp::Void (*MapperMethod)(TreeToObjectMapper*, MappingState&, const Type* const);
typedef oatpp::Void (*MapperMethod)(const TreeToObjectMapper*, MappingState&, const Type* const);
public:
template<class T>
static oatpp::Void mapPrimitive(TreeToObjectMapper* mapper, MappingState& state, const Type* const type){
static oatpp::Void mapPrimitive(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type){
(void) mapper;
(void) type;
if(state.tree->isNull()) {
@ -69,14 +69,14 @@ public:
static const Type* guessType(const Tree& node);
static oatpp::Void mapString(TreeToObjectMapper* mapper, MappingState& state, const Type* const type);
static oatpp::Void mapAny(TreeToObjectMapper* mapper, MappingState& state, const Type* const type);
static oatpp::Void mapEnum(TreeToObjectMapper* mapper, MappingState& state, const Type* const type);
static oatpp::Void mapString(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type);
static oatpp::Void mapAny(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type);
static oatpp::Void mapEnum(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type);
static oatpp::Void mapCollection(TreeToObjectMapper* mapper, MappingState& state, const Type* type);
static oatpp::Void mapMap(TreeToObjectMapper* mapper, MappingState& state, const Type* const type);
static oatpp::Void mapCollection(const TreeToObjectMapper* mapper, MappingState& state, const Type* type);
static oatpp::Void mapMap(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type);
static oatpp::Void mapObject(TreeToObjectMapper* mapper, MappingState& state, const Type* const type);
static oatpp::Void mapObject(const TreeToObjectMapper* mapper, MappingState& state, const Type* const type);
private:
std::vector<MapperMethod> m_methods;
@ -86,7 +86,7 @@ public:
void setMapperMethod(const data::mapping::type::ClassId& classId, MapperMethod method);
oatpp::Void map(MappingState& state, const Type* const type);
oatpp::Void map(MappingState& state, const Type* const type) const;
};

View File

@ -24,505 +24,194 @@
#include "Deserializer.hpp"
#include "oatpp/data/stream/BufferStream.hpp"
#include "oatpp/utils/Conversion.hpp"
namespace oatpp { namespace json {
Deserializer::Deserializer(const std::shared_ptr<Config>& config)
: m_config(config)
{
m_methods.resize(static_cast<size_t>(data::mapping::type::ClassId::getClassCount()), nullptr);
setDeserializerMethod(data::mapping::type::__class::String::CLASS_ID, &Deserializer::deserializeString);
setDeserializerMethod(data::mapping::type::__class::Any::CLASS_ID, &Deserializer::deserializeAny);
setDeserializerMethod(data::mapping::type::__class::Int8::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int8>);
setDeserializerMethod(data::mapping::type::__class::UInt8::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt8>);
setDeserializerMethod(data::mapping::type::__class::Int16::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int16>);
setDeserializerMethod(data::mapping::type::__class::UInt16::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt16>);
setDeserializerMethod(data::mapping::type::__class::Int32::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int32>);
setDeserializerMethod(data::mapping::type::__class::UInt32::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt32>);
setDeserializerMethod(data::mapping::type::__class::Int64::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int64>);
setDeserializerMethod(data::mapping::type::__class::UInt64::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt64>);
setDeserializerMethod(data::mapping::type::__class::Float32::CLASS_ID, &Deserializer::deserializeFloat32);
setDeserializerMethod(data::mapping::type::__class::Float64::CLASS_ID, &Deserializer::deserializeFloat64);
setDeserializerMethod(data::mapping::type::__class::Boolean::CLASS_ID, &Deserializer::deserializeBoolean);
setDeserializerMethod(data::mapping::type::__class::AbstractObject::CLASS_ID, &Deserializer::deserializeObject);
setDeserializerMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Deserializer::deserializeEnum);
setDeserializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Deserializer::deserializeCollection);
setDeserializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Deserializer::deserializeCollection);
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Deserializer::deserializeCollection);
setDeserializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Deserializer::deserializeMap);
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Deserializer::deserializeMap);
}
void Deserializer::setDeserializerMethod(const data::mapping::type::ClassId& classId, DeserializerMethod method) {
const v_uint32 id = static_cast<v_uint32>(classId.id);
if(id >= m_methods.size()) {
m_methods.resize(id + 1, nullptr);
oatpp::String Deserializer::MappingState::errorStacktrace() const {
data::stream::BufferOutputStream ss;
for(auto& s : errorStack) {
ss << s << "\n";
}
m_methods[id] = method;
return ss.toString();
}
void Deserializer::skipScope(oatpp::utils::parser::Caret& caret, v_char8 charOpen, v_char8 charClose){
const char* data = caret.getData();
v_buff_size size = caret.getDataSize();
v_buff_size pos = caret.getPosition();
v_int32 scopeCounter = 0;
bool isInString = false;
while(pos < size){
v_char8 a = static_cast<v_char8>(data[pos]);
if(a == charOpen){
if(!isInString){
scopeCounter ++;
}
} else if(a == charClose){
if(!isInString){
scopeCounter --;
if(scopeCounter == 0){
caret.setPosition(pos + 1);
return;
}
}
} else if(a == '"') {
isInString = !isInString;
} else if(a == '\\'){
pos ++;
}
pos ++;
void Deserializer::deserializeNull(MappingState& state) {
if(state.caret->isAtText("null", true)){
state.tree->setNull();
} else {
state.errorStack.emplace_back("[oatpp::json::Deserializer::deserializeNull()]: 'null' expected");
}
}
void Deserializer::skipString(oatpp::utils::parser::Caret& caret){
const char* data = caret.getData();
v_buff_size size = caret.getDataSize();
v_buff_size pos = caret.getPosition();
v_int32 scopeCounter = 0;
while(pos < size){
v_char8 a = static_cast<v_char8>(data[pos]);
if(a == '"'){
scopeCounter ++;
if(scopeCounter == 2) {
caret.setPosition(pos + 1);
void Deserializer::deserializeNumber(MappingState& state) {
if (!Utils::findDecimalSeparatorInCurrentNumber(*state.caret)) {
state.tree->setInteger(state.caret->parseInt());
} else {
state.tree->setFloat(state.caret->parseFloat64());
}
}
void Deserializer::deserializeBoolean(MappingState& state) {
if(state.caret->isAtText("true", true)) {
state.tree->setValue<bool>(true);
} else if(state.caret->isAtText("false", true)) {
state.tree->setValue<bool>(false);
} else {
state.errorStack.emplace_back("[oatpp::json::Deserializer::deserializeBoolean()]: 'true' or 'false' expected");
}
}
void Deserializer::deserializeString(MappingState& state) {
state.tree->setString(Utils::parseString(*state.caret));
}
void Deserializer::deserializeArray(MappingState& state) {
if(state.caret->canContinueAtChar('[', 1)) {
state.tree->setVector(0);
auto& vector = state.tree->getVector();
state.caret->skipBlankChars();
v_int64 index = 0;
while(!state.caret->isAtChar(']') && state.caret->canContinue()){
state.caret->skipBlankChars();
vector.emplace_back();
MappingState nestedState;
nestedState.caret = state.caret;
nestedState.config = state.config;
nestedState.tree = &vector[vector.size() - 1];
deserialize(nestedState);
if(!nestedState.errorStack.empty()) {
state.errorStack.splice(state.errorStack.end(), nestedState.errorStack);
state.errorStack.emplace_back("[oatpp::json::Deserializer::deserializeArray()]: index=" + utils::Conversion::int64ToStr(index));
return;
}
} else if(a == '\\'){
pos ++;
}
pos ++;
}
}
void Deserializer::skipToken(oatpp::utils::parser::Caret& caret){
const char* data = caret.getData();
v_buff_size size = caret.getDataSize();
v_buff_size pos = caret.getPosition();
while(pos < size){
v_char8 a = static_cast<v_char8>(data[pos]);
if(a == ' ' || a == '\t' || a == '\n' || a == '\r' || a == '\b' || a == '\f' ||
a == '}' || a == ',' || a == ']') {
caret.setPosition(pos);
state.caret->skipBlankChars();
state.caret->canContinueAtChar(',', 1);
index ++;
}
if(!state.caret->canContinueAtChar(']', 1)){
state.errorStack.emplace_back("[oatpp::json::Deserializer::deserializeArray()]: ']' expected");
return;
}
pos ++;
}
}
void Deserializer::skipValue(oatpp::utils::parser::Caret& caret){
if(caret.isAtChar('{')){
skipScope(caret, '{', '}');
} else if(caret.isAtChar('[')){
skipScope(caret, '[', ']');
} else if(caret.isAtChar('"')){
skipString(caret);
} else {
skipToken(caret);
}
}
oatpp::Void Deserializer::deserializeFloat32(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type) {
(void) deserializer;
(void) type;
if(caret.isAtText("null", true)){
return oatpp::Void(Float32::Class::getType());
} else {
return Float32(caret.parseFloat32());
}
}
oatpp::Void Deserializer::deserializeFloat64(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type) {
(void) deserializer;
(void) type;
if(caret.isAtText("null", true)){
return oatpp::Void(Float64::Class::getType());
} else {
return Float64(caret.parseFloat64());
state.errorStack.emplace_back("[oatpp::json::Deserializer::deserializeArray()]: '[' expected");
}
}
oatpp::Void Deserializer::deserializeBoolean(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type) {
void Deserializer::deserializeMap(MappingState& state) {
(void) deserializer;
(void) type;
if(state.caret->canContinueAtChar('{', 1)) {
state.caret->skipBlankChars();
state.tree->setMap({});
auto& map = state.tree->getMap();
while (!state.caret->isAtChar('}') && state.caret->canContinue()) {
state.caret->skipBlankChars();
auto key = Utils::parseString(*state.caret);
if(state.caret->hasError()){
state.errorStack.emplace_back("[oatpp::json::Deserializer::deserializeMap()]: Item key name expected");
return;
}
state.caret->skipBlankChars();
if(!state.caret->canContinueAtChar(':', 1)){
state.errorStack.emplace_back("[oatpp::json::Deserializer::deserializeMap()]: ':' expected");
return;
}
state.caret->skipBlankChars();
MappingState nestedState;
nestedState.caret = state.caret;
nestedState.config = state.config;
nestedState.tree = &map[key];
deserialize(nestedState);
if(!nestedState.errorStack.empty()) {
state.errorStack.splice(state.errorStack.end(), nestedState.errorStack);
state.errorStack.emplace_back("[oatpp::json::Deserializer::deserializeMap()]: key='" + key + "'");
return;
}
state.caret->skipBlankChars();
state.caret->canContinueAtChar(',', 1);
if(caret.isAtText("null", true)){
return oatpp::Void(Boolean::Class::getType());
} else {
if(caret.isAtText("true", true)) {
return Boolean(true);
} else if(caret.isAtText("false", true)) {
return Boolean(false);
} else {
caret.setError("[oatpp::json::Deserializer::readBooleanValue()]: Error. 'true' or 'false' - expected.", ERROR_CODE_VALUE_BOOLEAN);
return oatpp::Void(Boolean::Class::getType());
}
}
}
if(!state.caret->canContinueAtChar('}', 1)){
state.errorStack.emplace_back("[oatpp::json::Deserializer::deserializeMap()]: '}' expected");
return;
}
oatpp::Void Deserializer::deserializeString(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type) {
(void) deserializer;
(void) type;
if(caret.isAtText("null", true)){
return oatpp::Void(String::Class::getType());
} else {
return oatpp::Void(Utils::parseString(caret).getPtr(), String::Class::getType());
state.errorStack.emplace_back("[oatpp::json::Deserializer::deserializeMap()]: '{' expected");
}
}
const data::mapping::type::Type* Deserializer::guessNumberType(oatpp::utils::parser::Caret& caret) {
if (!Utils::findDecimalSeparatorInCurrentNumber(caret)) {
if (*caret.getCurrData() == '-') {
return Int64::Class::getType();
} else {
return UInt64::Class::getType();
}
}
return Float64::Class::getType();
}
void Deserializer::deserialize(MappingState& state) {
const data::mapping::type::Type* Deserializer::guessType(oatpp::utils::parser::Caret& caret) {
{
utils::parser::Caret::StateSaveGuard stateGuard(caret);
v_char8 c = static_cast<v_char8>(*caret.getCurrData());
switch (c) {
case '"':
return String::Class::getType();
case '{':
return oatpp::Fields<Any>::Class::getType();
case '[':
return oatpp::List<Any>::Class::getType();
case 't':
if(caret.isAtText("true")) return Boolean::Class::getType();
break;
case 'f':
if(caret.isAtText("false")) return Boolean::Class::getType();
break;
default:
if (c == '-' || caret.isAtDigitChar()) {
return guessNumberType(caret);
}
}
}
caret.setError("[oatpp::json::Deserializer::guessType()]: Error. Can't guess type for oatpp::Any.");
return nullptr;
}
state.caret->skipBlankChars();
oatpp::Void Deserializer::deserializeAny(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type) {
(void) type;
if(caret.isAtText("null", true)){
return oatpp::Void(Any::Class::getType());
} else {
const Type* const fieldType = guessType(caret);
if(fieldType != nullptr) {
auto fieldValue = deserializer->deserialize(caret, fieldType);
auto anyHandle = std::make_shared<data::mapping::type::AnyHandle>(fieldValue.getPtr(), fieldValue.getValueType());
return oatpp::Void(anyHandle, Any::Class::getType());
}
}
return oatpp::Void(Any::Class::getType());
}
oatpp::Void Deserializer::deserializeEnum(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type) {
auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::PolymorphicDispatcher*>(
type->polymorphicDispatcher
);
data::mapping::type::EnumInterpreterError e = data::mapping::type::EnumInterpreterError::OK;
const auto& value = deserializer->deserialize(caret, polymorphicDispatcher->getInterpretationType());
if(caret.hasError()) {
return nullptr;
}
const auto& result = polymorphicDispatcher->fromInterpretation(value, e);
if(e == data::mapping::type::EnumInterpreterError::OK) {
return result;
}
switch(e) {
case data::mapping::type::EnumInterpreterError::CONSTRAINT_NOT_NULL:
caret.setError("[oatpp::json::Deserializer::deserializeEnum()]: Error. Enum constraint violated - 'NotNull'.");
auto c = *state.caret->getCurrData();
switch (c) {
case 'n':
deserializeNull(state);
break;
case '{':
deserializeMap(state);
break;
case '[':
deserializeArray(state);
break;
case '"':
deserializeString(state);
break;
case 't':
case 'f':
deserializeBoolean(state);
break;
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
deserializeNumber(state);
break;
case data::mapping::type::EnumInterpreterError::OK:
case data::mapping::type::EnumInterpreterError::TYPE_MISMATCH_ENUM:
case data::mapping::type::EnumInterpreterError::TYPE_MISMATCH_ENUM_VALUE:
case data::mapping::type::EnumInterpreterError::ENTRY_NOT_FOUND:
default:
caret.setError("[oatpp::json::Deserializer::deserializeEnum()]: Error. Can't deserialize Enum.");
state.errorStack.emplace_back("[json]: Unknown character.");
break;
}
return nullptr;
}
oatpp::Void Deserializer::deserializeCollection(Deserializer* deserializer, utils::parser::Caret& caret, const Type* type) {
if(caret.isAtText("null", true)){
return oatpp::Void(type);
}
if(caret.canContinueAtChar('[', 1)) {
auto dispatcher = static_cast<const data::mapping::type::__class::Collection::PolymorphicDispatcher*>(type->polymorphicDispatcher);
auto collection = dispatcher->createObject();
auto itemType = dispatcher->getItemType();
caret.skipBlankChars();
while(!caret.isAtChar(']') && caret.canContinue()){
caret.skipBlankChars();
auto item = deserializer->deserialize(caret, itemType);
if(caret.hasError()){
return nullptr;
}
dispatcher->addItem(collection, item);
caret.skipBlankChars();
caret.canContinueAtChar(',', 1);
}
if(!caret.canContinueAtChar(']', 1)){
if(!caret.hasError()){
caret.setError("[oatpp::json::Deserializer::deserializeCollection()]: Error. ']' - expected", ERROR_CODE_ARRAY_SCOPE_CLOSE);
}
return nullptr;
}
return collection;
} else {
caret.setError("[oatpp::json::Deserializer::deserializeCollection()]: Error. '[' - expected", ERROR_CODE_ARRAY_SCOPE_OPEN);
return nullptr;
}
}
oatpp::Void Deserializer::deserializeMap(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type) {
if(caret.isAtText("null", true)){
return oatpp::Void(type);
}
if(caret.canContinueAtChar('{', 1)) {
auto dispatcher = static_cast<const data::mapping::type::__class::Map::PolymorphicDispatcher*>(type->polymorphicDispatcher);
auto map = dispatcher->createObject();
auto keyType = dispatcher->getKeyType();
if(keyType->classId != oatpp::String::Class::CLASS_ID){
throw std::runtime_error("[oatpp::json::Deserializer::deserializeMap()]: Invalid json map key. Key should be String");
}
auto valueType = dispatcher->getValueType();
caret.skipBlankChars();
while (!caret.isAtChar('}') && caret.canContinue()) {
caret.skipBlankChars();
auto key = Utils::parseString(caret);
if(caret.hasError()){
return nullptr;
}
caret.skipBlankChars();
if(!caret.canContinueAtChar(':', 1)){
caret.setError("[oatpp::json::Deserializer::deserializeMap()]: Error. ':' - expected", ERROR_CODE_OBJECT_SCOPE_COLON_MISSING);
return nullptr;
}
caret.skipBlankChars();
auto item = deserializer->deserialize(caret, valueType);
if(caret.hasError()){
return nullptr;
}
dispatcher->addItem(map, key, item);
caret.skipBlankChars();
caret.canContinueAtChar(',', 1);
}
if(!caret.canContinueAtChar('}', 1)){
if(!caret.hasError()){
caret.setError("[oatpp::json::Deserializer::deserializeMap()]: Error. '}' - expected", ERROR_CODE_OBJECT_SCOPE_CLOSE);
}
return nullptr;
}
return map;
} else {
caret.setError("[oatpp::json::Deserializer::deserializeMap()]: Error. '{' - expected", ERROR_CODE_OBJECT_SCOPE_OPEN);
}
return nullptr;
}
oatpp::Void Deserializer::deserializeObject(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type) {
if(caret.isAtText("null", true)){
return oatpp::Void(type);
}
if(caret.canContinueAtChar('{', 1)) {
auto dispatcher = static_cast<const oatpp::data::mapping::type::__class::AbstractObject::PolymorphicDispatcher*>(type->polymorphicDispatcher);
auto object = dispatcher->createObject();
const auto& fieldsMap = dispatcher->getProperties()->getMap();
caret.skipBlankChars();
std::vector<std::pair<oatpp::BaseObject::Property*, oatpp::String>> polymorphs;
while (!caret.isAtChar('}') && caret.canContinue()) {
caret.skipBlankChars();
auto key = Utils::parseStringToStdString(caret);
if(caret.hasError()){
return nullptr;
}
auto fieldIterator = fieldsMap.find(key);
if(fieldIterator != fieldsMap.end()){
caret.skipBlankChars();
if(!caret.canContinueAtChar(':', 1)){
caret.setError("[oatpp::json::Deserializer::readObject()]: Error. ':' - expected", ERROR_CODE_OBJECT_SCOPE_COLON_MISSING);
return nullptr;
}
caret.skipBlankChars();
auto field = fieldIterator->second;
if(field->info.typeSelector && field->type == oatpp::Any::Class::getType()) {
auto label = caret.putLabel();
skipValue(caret);
polymorphs.emplace_back(field, label.toString()); // store polymorphs for later processing.
} else {
auto value = deserializer->deserialize(caret, field->type);
if(field->info.required && value == nullptr) {
throw std::runtime_error("[oatpp::json::Deserializer::deserialize()]: "
"Error. " + std::string(type->nameQualifier) + "::"
+ std::string(field->name) + " is required!");
}
field->set(static_cast<oatpp::BaseObject *>(object.get()), value);
}
} else if (deserializer->getConfig()->allowUnknownFields) {
caret.skipBlankChars();
if(!caret.canContinueAtChar(':', 1)){
caret.setError("[oatpp::json::Deserializer::readObject()/if(config->allowUnknownFields){}]: Error. ':' - expected", ERROR_CODE_OBJECT_SCOPE_COLON_MISSING);
return nullptr;
}
caret.skipBlankChars();
skipValue(caret);
} else {
caret.setError("[oatpp::json::Deserializer::readObject()]: Error. Unknown field", ERROR_CODE_OBJECT_SCOPE_UNKNOWN_FIELD);
return nullptr;
}
caret.skipBlankChars();
caret.canContinueAtChar(',', 1);
}
if(!caret.canContinueAtChar('}', 1)){
if(!caret.hasError()){
caret.setError("[oatpp::json::Deserializer::readObject()]: Error. '}' - expected", ERROR_CODE_OBJECT_SCOPE_CLOSE);
}
return nullptr;
}
for(auto& p : polymorphs) {
utils::parser::Caret polyCaret(p.second);
auto selectedType = p.first->info.typeSelector->selectType(static_cast<oatpp::BaseObject *>(object.get()));
auto value = deserializer->deserialize(polyCaret, selectedType);
if(p.first->info.required && value == nullptr) {
throw std::runtime_error("[oatpp::json::Deserializer::deserialize()]: "
"Error. " + std::string(type->nameQualifier) + "::"
+ std::string(p.first->name) + " is required!");
}
oatpp::Any any(value);
p.first->set(static_cast<oatpp::BaseObject *>(object.get()), oatpp::Void(any.getPtr(), p.first->type));
}
return object;
} else {
caret.setError("[oatpp::json::Deserializer::readObject()]: Error. '{' - expected", ERROR_CODE_OBJECT_SCOPE_OPEN);
}
return nullptr;
}
oatpp::Void Deserializer::deserialize(utils::parser::Caret& caret, const Type* const type) {
auto id = static_cast<v_uint32>(type->classId.id);
auto& method = m_methods[id];
if(method) {
return (*method)(this, caret, type);
} else {
auto* interpretation = type->findInterpretation(m_config->enabledInterpretations);
if(interpretation) {
return interpretation->fromInterpretation(deserialize(caret, interpretation->getInterpretationType()));
}
throw std::runtime_error("[oatpp::json::Deserializer::deserialize()]: "
"Error. No deserialize method for type '" + std::string(type->classId.name) + "'");
}
}
const std::shared_ptr<Deserializer::Config>& Deserializer::getConfig() {
return m_config;
}
}}

View File

@ -26,6 +26,9 @@
#define oatpp_json_Deserializer_hpp
#include "./Utils.hpp"
#include "oatpp/data/mapping/TreeToObjectMapper.hpp"
#include "oatpp/utils/parser/Caret.hpp"
#include "oatpp/Types.hpp"
@ -38,50 +41,6 @@ namespace oatpp { namespace json {
* Deserialize oatpp DTO object from json. See [Data Transfer Object(DTO) component](https://oatpp.io/docs/components/dto/).
*/
class Deserializer {
public:
typedef oatpp::data::mapping::type::Type Type;
typedef oatpp::data::mapping::type::BaseObject::Property Property;
typedef oatpp::data::mapping::type::BaseObject::Properties Properties;
typedef oatpp::String String;
public:
/**
* "'{' - expected"
*/
static constexpr v_int32 ERROR_CODE_OBJECT_SCOPE_OPEN = 1;
/**
* "'}' - expected"
*/
static constexpr v_int32 ERROR_CODE_OBJECT_SCOPE_CLOSE = 2;
/**
* "Unknown field"
*/
static constexpr v_int32 ERROR_CODE_OBJECT_SCOPE_UNKNOWN_FIELD = 3;
/**
* "':' - expected"
*/
static constexpr v_int32 ERROR_CODE_OBJECT_SCOPE_COLON_MISSING = 4;
/**
* "'[' - expected"
*/
static constexpr v_int32 ERROR_CODE_ARRAY_SCOPE_OPEN = 5;
/**
* "']' - expected"
*/
static constexpr v_int32 ERROR_CODE_ARRAY_SCOPE_CLOSE = 6;
/**
* "'true' or 'false' - expected"
*/
static constexpr v_int32 ERROR_CODE_VALUE_BOOLEAN = 7;
public:
/**
@ -89,123 +48,36 @@ public:
*/
class Config : public oatpp::base::Countable {
public:
/**
* Constructor.
*/
Config()
{}
public:
/**
* Create shared Config.
* @return - `std::shared_ptr` to Config.
*/
static std::shared_ptr<Config> createShared(){
return std::make_shared<Config>();
}
/**
* Do not fail if unknown field is found in json.
* "unknown field" is the one which is not present in DTO object class.
*/
bool allowUnknownFields = true;
/**
* Enable type interpretations.
*/
std::vector<std::string> enabledInterpretations = {};
};
public:
typedef oatpp::Void (*DeserializerMethod)(Deserializer*, utils::parser::Caret&, const Type* const);
private:
static void skipScope(oatpp::utils::parser::Caret& caret, v_char8 charOpen, v_char8 charClose);
static void skipString(oatpp::utils::parser::Caret& caret);
static void skipToken(oatpp::utils::parser::Caret& caret);
static void skipValue(oatpp::utils::parser::Caret& caret);
private:
static const Type* guessNumberType(oatpp::utils::parser::Caret& caret);
static const Type* guessType(oatpp::utils::parser::Caret& caret);
private:
template<class T>
static oatpp::Void deserializeInt(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type){
struct MappingState {
(void) deserializer;
(void) type;
Config* config;
data::mapping::Tree* tree;
utils::parser::Caret* caret;
if(caret.isAtText("null", true)){
return oatpp::Void(T::Class::getType());
} else {
//TODO: shall we handle overflow cases like
// oatpp::String json = "128";
// auto value = jsonObjectMapper->readFromString<oatpp::Int8>(json); // UInt8 will overflow to -128
return T(static_cast<typename T::UnderlyingType>(caret.parseInt()));
}
std::list<oatpp::String> errorStack;
}
oatpp::String errorStacktrace() const;
template<class T>
static oatpp::Void deserializeUInt(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type){
(void) deserializer;
(void) type;
if(caret.isAtText("null", true)){
return oatpp::Void(T::Class::getType());
} else {
//TODO: shall we handle overflow cases like
// oatpp::String json = "256";
// auto value = jsonObjectMapper->readFromString<oatpp::UInt8>(json); // UInt8 will overflow to 0
return T(static_cast<typename T::UnderlyingType>(caret.parseUnsignedInt()));
}
}
static oatpp::Void deserializeFloat32(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeFloat64(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeBoolean(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeString(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeAny(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeEnum(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeCollection(Deserializer* deserializer, utils::parser::Caret& caret, const Type* type);
static oatpp::Void deserializeMap(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeObject(Deserializer* deserializer, utils::parser::Caret& caret, const Type* const type);
};
private:
std::shared_ptr<Config> m_config;
std::vector<DeserializerMethod> m_methods;
static void deserializeNull(MappingState& state);
static void deserializeNumber(MappingState& state);
static void deserializeBoolean(MappingState& state);
static void deserializeString(MappingState& state);
static void deserializeArray(MappingState& state);
static void deserializeMap(MappingState& state);
public:
/**
* Constructor.
* @param config
*/
Deserializer(const std::shared_ptr<Config>& config = std::make_shared<Config>());
/**
* Set deserializer method for type.
* @param classId - &id:oatpp::data::mapping::type::ClassId;.
* @param method - `typedef oatpp::Void (*DeserializerMethod)(Deserializer*, utils::parser::Caret&, const Type* const)`.
*/
void setDeserializerMethod(const data::mapping::type::ClassId& classId, DeserializerMethod method);
/**
* Deserialize text.
* @param caret - &id:oatpp::utils::parser::Caret;.
* @param type - &id:oatpp::data::mapping::type::Type;
* @return - `oatpp::Void` over deserialized object.
*/
oatpp::Void deserialize(utils::parser::Caret& caret, const Type* const type);
/**
* Get deserializer config.
* @return
*/
const std::shared_ptr<Config>& getConfig();
static void deserialize(MappingState& state);
};

View File

@ -27,21 +27,20 @@
namespace oatpp { namespace json {
ObjectMapper::ObjectMapper(const std::shared_ptr<Serializer::Config>& serializerConfig,
const std::shared_ptr<Deserializer::Config>& deserializerConfig)
const std::shared_ptr<DeserializerConfig>& deserializerConfig)
: data::mapping::ObjectMapper(getMapperInfo())
, m_serializer(std::make_shared<Serializer>(serializerConfig))
, m_deserializer(std::make_shared<Deserializer>(deserializerConfig))
, m_deserializerConfig(deserializerConfig)
{}
ObjectMapper::ObjectMapper(const std::shared_ptr<Serializer>& serializer,
const std::shared_ptr<Deserializer>& deserializer)
ObjectMapper::ObjectMapper(const std::shared_ptr<Serializer>& serializer)
: data::mapping::ObjectMapper(getMapperInfo())
, m_serializer(serializer)
, m_deserializer(deserializer)
, m_deserializerConfig(std::make_shared<DeserializerConfig>())
{}
std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<Serializer::Config>& serializerConfig,
const std::shared_ptr<Deserializer::Config>& deserializerConfig)
const std::shared_ptr<DeserializerConfig>& deserializerConfig)
{
return std::make_shared<ObjectMapper>(serializerConfig, deserializerConfig);
}
@ -49,7 +48,7 @@ std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<S
std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<Serializer>& serializer,
const std::shared_ptr<Deserializer>& deserializer)
{
return std::make_shared<ObjectMapper>(serializer, deserializer);
return std::make_shared<ObjectMapper>(serializer);
}
void ObjectMapper::write(data::stream::ConsistentOutputStream* stream,
@ -58,15 +57,45 @@ void ObjectMapper::write(data::stream::ConsistentOutputStream* stream,
}
oatpp::Void ObjectMapper::read(oatpp::utils::parser::Caret& caret, const oatpp::data::mapping::type::Type* const type) const {
return m_deserializer->deserialize(caret, type);
data::mapping::Tree tree;
{
Deserializer::MappingState state;
state.caret = &caret;
state.tree = &tree;
state.config = m_deserializerConfig.get();
Deserializer::deserialize(state);
if (!state.errorStack.empty()) {
//return nullptr;
throw utils::parser::ParsingError(state.errorStacktrace(), 0, 0);
}
}
{
data::mapping::TreeToObjectMapper::MappingState state;
state.tree = &tree;
state.config = m_deserializerConfig.get();
const auto & result = m_treeToObjectMapper.map(state, type);
if(!state.errorStacktrace()->empty()) {
throw utils::parser::ParsingError(state.errorStacktrace(), 0, 0);
}
return result;
}
}
std::shared_ptr<Serializer> ObjectMapper::getSerializer() {
return m_serializer;
}
std::shared_ptr<Deserializer> ObjectMapper::getDeserializer() {
return m_deserializer;
std::shared_ptr<ObjectMapper::DeserializerConfig> ObjectMapper::getDeserializerConfig() {
return m_deserializerConfig;
}
}}

View File

@ -28,6 +28,7 @@
#include "./Serializer.hpp"
#include "./Deserializer.hpp"
#include "oatpp/data/mapping/TreeToObjectMapper.hpp"
#include "oatpp/data/mapping/ObjectMapper.hpp"
namespace oatpp { namespace json {
@ -43,9 +44,21 @@ private:
static Info info("application/json");
return info;
}
public:
class DeserializerConfig : public data::mapping::TreeToObjectMapper::Config, public Deserializer::Config {
public:
};
private:
std::shared_ptr<Serializer> m_serializer;
std::shared_ptr<Deserializer> m_deserializer;
std::shared_ptr<DeserializerConfig> m_deserializerConfig;
private:
data::mapping::TreeToObjectMapper m_treeToObjectMapper;
public:
/**
* Constructor.
@ -53,15 +66,14 @@ public:
* @param deserializerConfig - &id:oatpp::json::Deserializer::Config;.
*/
ObjectMapper(const std::shared_ptr<Serializer::Config>& serializerConfig,
const std::shared_ptr<Deserializer::Config>& deserializerConfig);
const std::shared_ptr<DeserializerConfig>& deserializerConfig);
/**
* Constructor.
* @param serializer
* @param deserializer
*/
ObjectMapper(const std::shared_ptr<Serializer>& serializer = std::make_shared<Serializer>(),
const std::shared_ptr<Deserializer>& deserializer = std::make_shared<Deserializer>());
ObjectMapper(const std::shared_ptr<Serializer>& serializer = std::make_shared<Serializer>());
public:
/**
@ -72,7 +84,7 @@ public:
*/
static std::shared_ptr<ObjectMapper>
createShared(const std::shared_ptr<Serializer::Config>& serializerConfig,
const std::shared_ptr<Deserializer::Config>& deserializerConfig);
const std::shared_ptr<DeserializerConfig>& deserializerConfig);
/**
* Create shared ObjectMapper.
@ -110,7 +122,7 @@ public:
* Get deserializer.
* @return
*/
std::shared_ptr<Deserializer> getDeserializer();
std::shared_ptr<DeserializerConfig> getDeserializerConfig();
};

View File

@ -79,7 +79,7 @@ namespace {
void runTests() {
/*
oatpp::Environment::printCompilationConfig();
OATPP_LOGD("Tests", "oatpp::String size=%lu", sizeof(oatpp::String))
@ -96,7 +96,7 @@ void runTests() {
OATPP_LOGD("CLASS", "%d --> '%s'", i, name)
i ++;
}
/*
OATPP_RUN_TEST(oatpp::test::LoggerTest);
OATPP_RUN_TEST(oatpp::base::CommandLineArgumentsTest);
@ -112,35 +112,35 @@ void runTests() {
//OATPP_RUN_TEST(oatpp::data::mapping::TreeTest);
OATPP_RUN_TEST(oatpp::data::mapping::TreeToObjectMapperTest);
/*
OATPP_RUN_TEST(oatpp::data::mapping::type::ObjectWrapperTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::TypeTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::StringTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::PrimitiveTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::ListTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::VectorTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::UnorderedSetTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::PairListTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::UnorderedMapTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::AnyTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::EnumTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::ObjectTest);
OATPP_RUN_TEST(oatpp::data::mapping::type::InterpretationTest);
OATPP_RUN_TEST(oatpp::data::mapping::TypeResolverTest);
OATPP_RUN_TEST(oatpp::data::resource::InMemoryDataTest);
OATPP_RUN_TEST(oatpp::async::ConditionVariableTest);
OATPP_RUN_TEST(oatpp::async::LockTest);
OATPP_RUN_TEST(oatpp::utils::parser::CaretTest);
OATPP_RUN_TEST(oatpp::provider::PoolTest);
OATPP_RUN_TEST(oatpp::provider::PoolTemplateTest);
// OATPP_RUN_TEST(oatpp::data::mapping::type::ObjectWrapperTest);
// OATPP_RUN_TEST(oatpp::data::mapping::type::TypeTest);
//
// OATPP_RUN_TEST(oatpp::data::mapping::type::StringTest);
//
// OATPP_RUN_TEST(oatpp::data::mapping::type::PrimitiveTest);
// OATPP_RUN_TEST(oatpp::data::mapping::type::ListTest);
// OATPP_RUN_TEST(oatpp::data::mapping::type::VectorTest);
// OATPP_RUN_TEST(oatpp::data::mapping::type::UnorderedSetTest);
// OATPP_RUN_TEST(oatpp::data::mapping::type::PairListTest);
// OATPP_RUN_TEST(oatpp::data::mapping::type::UnorderedMapTest);
// OATPP_RUN_TEST(oatpp::data::mapping::type::AnyTest);
// OATPP_RUN_TEST(oatpp::data::mapping::type::EnumTest);
//
// OATPP_RUN_TEST(oatpp::data::mapping::type::ObjectTest);
//
// OATPP_RUN_TEST(oatpp::data::mapping::type::InterpretationTest);
// OATPP_RUN_TEST(oatpp::data::mapping::TypeResolverTest);
//
// OATPP_RUN_TEST(oatpp::data::resource::InMemoryDataTest);
//
// OATPP_RUN_TEST(oatpp::async::ConditionVariableTest);
// OATPP_RUN_TEST(oatpp::async::LockTest);
//
// OATPP_RUN_TEST(oatpp::utils::parser::CaretTest);
//
// OATPP_RUN_TEST(oatpp::provider::PoolTest);
// OATPP_RUN_TEST(oatpp::provider::PoolTemplateTest);
OATPP_RUN_TEST(oatpp::json::EnumTest);
OATPP_RUN_TEST(oatpp::json::BooleanTest);
@ -150,7 +150,7 @@ void runTests() {
OATPP_RUN_TEST(oatpp::json::DeserializerTest);
OATPP_RUN_TEST(oatpp::json::DTOMapperPerfTest);
OATPP_RUN_TEST(oatpp::json::DTOMapperTest);
/*
OATPP_RUN_TEST(oatpp::test::encoding::Base64Test);
OATPP_RUN_TEST(oatpp::test::encoding::UnicodeTest);
OATPP_RUN_TEST(oatpp::test::encoding::UrlTest);

View File

@ -182,7 +182,7 @@ void InterpretationTest::onRun() {
}
{
auto config = mapper.getDeserializer()->getConfig();
auto config = mapper.getDeserializerConfig();
config->enabledInterpretations = {"test"};
}

View File

@ -307,12 +307,12 @@ void DeserializerTest::onRun(){
OATPP_ASSERT(dto->any.getStoredType() == Float64::Class::getType())
OATPP_ASSERT(fabs(dto->any.retrieve<Float64>() - 1.2345e30) < std::numeric_limits<double>::epsilon())
}
OATPP_LOGD(TAG, "Any: Unsigned Integer")
OATPP_LOGD(TAG, "Any: Big Integer")
{
auto dto = mapper->readFromString<oatpp::Object<AnyDto>>(R"({"any":12345678901234567890,"another":1.1})");
auto dto = mapper->readFromString<oatpp::Object<AnyDto>>(R"({"any":9223372036854775807,"another":1.1})");
OATPP_ASSERT(dto)
OATPP_ASSERT(dto->any.getStoredType() == UInt64::Class::getType())
OATPP_ASSERT(dto->any.retrieve<UInt64>() == 12345678901234567890u)
OATPP_ASSERT(dto->any.getStoredType() == Int64::Class::getType())
OATPP_ASSERT(dto->any.retrieve<Int64>() == 9223372036854775807)
}
OATPP_LOGD(TAG, "Any: Signed Integer")
{