mirror of
https://github.com/oatpp/oatpp.git
synced 2025-01-30 16:59:30 +08:00
json::mapping::ObjectMapper. New deserializer.
This commit is contained in:
parent
fc26498f45
commit
de9296d287
@ -232,7 +232,7 @@ add_library(oatpp
|
|||||||
oatpp/web/url/mapping/Pattern.cpp
|
oatpp/web/url/mapping/Pattern.cpp
|
||||||
oatpp/web/url/mapping/Pattern.hpp
|
oatpp/web/url/mapping/Pattern.hpp
|
||||||
oatpp/web/url/mapping/Router.hpp
|
oatpp/web/url/mapping/Router.hpp
|
||||||
)
|
oatpp/parser/json/mapping/Deserializer2.cpp oatpp/parser/json/mapping/Deserializer2.hpp)
|
||||||
|
|
||||||
set_target_properties(oatpp PROPERTIES
|
set_target_properties(oatpp PROPERTIES
|
||||||
CXX_STANDARD 11
|
CXX_STANDARD 11
|
||||||
|
@ -128,11 +128,13 @@ String operator + (const String& a, const String& b);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Template for primitive mapping-enabled types.
|
* Template for primitive mapping-enabled types.
|
||||||
* @tparam ValueType - type of the value ex.: v_int64.
|
* @tparam TValueType - type of the value ex.: v_int64.
|
||||||
* @tparam Clazz - Class holding static class information.
|
* @tparam Clazz - Class holding static class information.
|
||||||
*/
|
*/
|
||||||
template<typename ValueType, class Clazz>
|
template<typename TValueType, class Clazz>
|
||||||
class Primitive : public oatpp::base::Countable {
|
class Primitive : public oatpp::base::Countable {
|
||||||
|
public:
|
||||||
|
typedef TValueType ValueType;
|
||||||
public:
|
public:
|
||||||
OBJECT_POOL(Primitive_Type_Pool, Primitive, 32)
|
OBJECT_POOL(Primitive_Type_Pool, Primitive, 32)
|
||||||
SHARED_OBJECT_POOL(Shared_Primitive_Type_Pool, Primitive, 32)
|
SHARED_OBJECT_POOL(Shared_Primitive_Type_Pool, Primitive, 32)
|
||||||
|
413
src/oatpp/parser/json/mapping/Deserializer2.cpp
Normal file
413
src/oatpp/parser/json/mapping/Deserializer2.cpp
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
*
|
||||||
|
* Project _____ __ ____ _ _
|
||||||
|
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||||
|
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||||
|
* (_____)(__)(__)(__) |_| |_|
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "Deserializer2.hpp"
|
||||||
|
|
||||||
|
#include "oatpp/parser/json/Utils.hpp"
|
||||||
|
#include "oatpp/core/utils/ConversionUtils.hpp"
|
||||||
|
|
||||||
|
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||||
|
|
||||||
|
Deserializer2::Deserializer2(const std::shared_ptr<Config>& config)
|
||||||
|
: m_config(config)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_methods.resize(data::mapping::type::ClassId::getClassCount(), nullptr);
|
||||||
|
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::String::CLASS_ID, &Deserializer2::deserializeString);
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::Int8::CLASS_ID, &Deserializer2::deserializeInt<oatpp::Int8>);
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::Int16::CLASS_ID, &Deserializer2::deserializeInt<oatpp::Int16>);
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::Int32::CLASS_ID, &Deserializer2::deserializeInt<oatpp::Int32>);
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::Int64::CLASS_ID, &Deserializer2::deserializeInt<oatpp::Int64>);
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::Float32::CLASS_ID, &Deserializer2::deserializeFloat32);
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::Float64::CLASS_ID, &Deserializer2::deserializeFloat64);
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::Boolean::CLASS_ID, &Deserializer2::deserializeBoolean);
|
||||||
|
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::AbstractList::CLASS_ID, &Deserializer2::deserializeList);
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::AbstractListMap::CLASS_ID, &Deserializer2::deserializeFieldsMap);
|
||||||
|
setDeserializerMethod(oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID, &Deserializer2::deserializeObject);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Deserializer2::setDeserializerMethod(const data::mapping::type::ClassId& classId, DeserializerMethod method) {
|
||||||
|
auto id = classId.id;
|
||||||
|
if(id < m_methods.size()) {
|
||||||
|
m_methods[id] = method;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("[oatpp::parser::json::mapping::Deserializer2::setDeserializerMethod()]: Error. Unknown classId");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Deserializer2::skipScope(oatpp::parser::Caret& caret, v_char8 charOpen, v_char8 charClose){
|
||||||
|
|
||||||
|
p_char8 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 = 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 Deserializer2::skipString(oatpp::parser::Caret& caret){
|
||||||
|
p_char8 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 = data[pos];
|
||||||
|
if(a == '"'){
|
||||||
|
scopeCounter ++;
|
||||||
|
if(scopeCounter == 2) {
|
||||||
|
caret.setPosition(pos + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if(a == '\\'){
|
||||||
|
pos ++;
|
||||||
|
}
|
||||||
|
pos ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Deserializer2::skipToken(oatpp::parser::Caret& caret){
|
||||||
|
p_char8 data = caret.getData();
|
||||||
|
v_buff_size size = caret.getDataSize();
|
||||||
|
v_buff_size pos = caret.getPosition();
|
||||||
|
while(pos < size){
|
||||||
|
v_char8 a = data[pos];
|
||||||
|
if(a == ' ' || a == '\t' || a == '\n' || a == '\r' || a == '\b' || a == '\f' ||
|
||||||
|
a == '}' || a == ',' || a == ']') {
|
||||||
|
caret.setPosition(pos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Deserializer2::skipValue(oatpp::parser::Caret& caret){
|
||||||
|
if(caret.isAtChar('{')){
|
||||||
|
skipScope(caret, '{', '}');
|
||||||
|
} else if(caret.isAtChar('[')){
|
||||||
|
skipScope(caret, '[', ']');
|
||||||
|
} else if(caret.isAtChar('"')){
|
||||||
|
skipString(caret);
|
||||||
|
} else {
|
||||||
|
skipToken(caret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data::mapping::type::AbstractObjectWrapper Deserializer2::deserializeFloat32(Deserializer2* deserializer,
|
||||||
|
parser::Caret& caret,
|
||||||
|
const Type* const type)
|
||||||
|
{
|
||||||
|
|
||||||
|
(void) deserializer;
|
||||||
|
(void) type;
|
||||||
|
|
||||||
|
if(caret.isAtText("null", true)){
|
||||||
|
return AbstractObjectWrapper(Float32::ObjectWrapper::Class::getType());
|
||||||
|
} else {
|
||||||
|
return AbstractObjectWrapper(Float32::ObjectType::createAbstract(caret.parseFloat32()), Float32::ObjectWrapper::Class::getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data::mapping::type::AbstractObjectWrapper Deserializer2::deserializeFloat64(Deserializer2* deserializer,
|
||||||
|
parser::Caret& caret,
|
||||||
|
const Type* const type)
|
||||||
|
{
|
||||||
|
|
||||||
|
(void) deserializer;
|
||||||
|
(void) type;
|
||||||
|
|
||||||
|
if(caret.isAtText("null", true)){
|
||||||
|
return AbstractObjectWrapper(Float64::ObjectWrapper::Class::getType());
|
||||||
|
} else {
|
||||||
|
return AbstractObjectWrapper(Float64::ObjectType::createAbstract(caret.parseFloat64()), Float64::ObjectWrapper::Class::getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data::mapping::type::AbstractObjectWrapper Deserializer2::deserializeBoolean(Deserializer2* deserializer,
|
||||||
|
parser::Caret& caret,
|
||||||
|
const Type* const type)
|
||||||
|
{
|
||||||
|
|
||||||
|
(void) deserializer;
|
||||||
|
(void) type;
|
||||||
|
|
||||||
|
if(caret.isAtText("null", true)){
|
||||||
|
return AbstractObjectWrapper(Boolean::ObjectWrapper::Class::getType());
|
||||||
|
} else {
|
||||||
|
if(caret.isAtText("true", true)) {
|
||||||
|
return AbstractObjectWrapper(Boolean::ObjectType::createAbstract(true), Boolean::ObjectWrapper::Class::getType());
|
||||||
|
} else if(caret.isAtText("false", true)) {
|
||||||
|
return AbstractObjectWrapper(Boolean::ObjectType::createAbstract(false), Boolean::ObjectWrapper::Class::getType());
|
||||||
|
} else {
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readBooleanValue()]: Error. 'true' or 'false' - expected.", ERROR_CODE_VALUE_BOOLEAN);
|
||||||
|
return AbstractObjectWrapper(Boolean::ObjectWrapper::Class::getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data::mapping::type::AbstractObjectWrapper Deserializer2::deserializeString(Deserializer2* deserializer,
|
||||||
|
parser::Caret& caret,
|
||||||
|
const Type* const type)
|
||||||
|
{
|
||||||
|
|
||||||
|
(void) deserializer;
|
||||||
|
(void) type;
|
||||||
|
|
||||||
|
if(caret.isAtText("null", true)){
|
||||||
|
return AbstractObjectWrapper(String::Class::getType());
|
||||||
|
} else {
|
||||||
|
return AbstractObjectWrapper(oatpp::parser::json::Utils::parseString(caret).getPtr(), String::Class::getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data::mapping::type::AbstractObjectWrapper Deserializer2::deserializeList(Deserializer2* deserializer,
|
||||||
|
parser::Caret& caret,
|
||||||
|
const Type* const type)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(caret.isAtText("null", true)){
|
||||||
|
return AbstractObjectWrapper(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(caret.canContinueAtChar('[', 1)) {
|
||||||
|
|
||||||
|
auto listWrapper = type->creator();
|
||||||
|
oatpp::data::mapping::type::PolymorphicWrapper<AbstractList>
|
||||||
|
list(std::static_pointer_cast<AbstractList>(listWrapper.getPtr()), listWrapper.valueType);
|
||||||
|
|
||||||
|
Type* itemType = *type->params.begin();
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
|
||||||
|
while(!caret.isAtChar(']') && caret.canContinue()){
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
auto item = deserializer->deserialize(caret, itemType);
|
||||||
|
if(caret.hasError()){
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
list->addPolymorphicItem(item);
|
||||||
|
caret.skipBlankChars();
|
||||||
|
|
||||||
|
caret.canContinueAtChar(',', 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!caret.canContinueAtChar(']', 1)){
|
||||||
|
if(!caret.hasError()){
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readList()]: Error. ']' - expected", ERROR_CODE_ARRAY_SCOPE_CLOSE);
|
||||||
|
}
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
};
|
||||||
|
|
||||||
|
return AbstractObjectWrapper(list.getPtr(), list.valueType);
|
||||||
|
} else {
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readList()]: Error. '[' - expected", ERROR_CODE_ARRAY_SCOPE_OPEN);
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data::mapping::type::AbstractObjectWrapper Deserializer2::deserializeFieldsMap(Deserializer2* deserializer,
|
||||||
|
parser::Caret& caret,
|
||||||
|
const Type* const type)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(caret.isAtText("null", true)){
|
||||||
|
return AbstractObjectWrapper(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(caret.canContinueAtChar('{', 1)) {
|
||||||
|
|
||||||
|
auto mapWrapper = type->creator();
|
||||||
|
oatpp::data::mapping::type::PolymorphicWrapper<AbstractFieldsMap>
|
||||||
|
map(std::static_pointer_cast<AbstractFieldsMap>(mapWrapper.getPtr()), mapWrapper.valueType);
|
||||||
|
|
||||||
|
auto it = type->params.begin();
|
||||||
|
Type* keyType = *it ++;
|
||||||
|
if(keyType->classId.id != oatpp::data::mapping::type::__class::String::CLASS_ID.id){
|
||||||
|
throw std::runtime_error("[oatpp::parser::json::mapping::Deserializer::readListMap()]: Invalid json map key. Key should be String");
|
||||||
|
}
|
||||||
|
Type* valueType = *it;
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
|
||||||
|
while (!caret.isAtChar('}') && caret.canContinue()) {
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
auto key = Utils::parseString(caret);
|
||||||
|
if(caret.hasError()){
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
if(!caret.canContinueAtChar(':', 1)){
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readListMap()]: Error. ':' - expected", ERROR_CODE_OBJECT_SCOPE_COLON_MISSING);
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
|
||||||
|
map->putPolymorphicItem(key, deserializer->deserialize(caret, valueType));
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
caret.canContinueAtChar(',', 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!caret.canContinueAtChar('}', 1)){
|
||||||
|
if(!caret.hasError()){
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readListMap()]: Error. '}' - expected", ERROR_CODE_OBJECT_SCOPE_CLOSE);
|
||||||
|
}
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return AbstractObjectWrapper(map.getPtr(), map.valueType);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readListMap()]: Error. '{' - expected", ERROR_CODE_OBJECT_SCOPE_OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data::mapping::type::AbstractObjectWrapper Deserializer2::deserializeObject(Deserializer2* deserializer,
|
||||||
|
parser::Caret& caret,
|
||||||
|
const Type* const type)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(caret.isAtText("null", true)){
|
||||||
|
return AbstractObjectWrapper(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(caret.canContinueAtChar('{', 1)) {
|
||||||
|
|
||||||
|
auto object = type->creator();
|
||||||
|
const auto& fieldsMap = type->properties->getMap();
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
|
||||||
|
while (!caret.isAtChar('}') && caret.canContinue()) {
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
auto key = Utils::parseStringToStdString(caret);
|
||||||
|
if(caret.hasError()){
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fieldIterator = fieldsMap.find(key);
|
||||||
|
if(fieldIterator != fieldsMap.end()){
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
if(!caret.canContinueAtChar(':', 1)){
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readObject()]: Error. ':' - expected", ERROR_CODE_OBJECT_SCOPE_COLON_MISSING);
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
|
||||||
|
auto field = fieldIterator->second;
|
||||||
|
field->set(object.get(), deserializer->deserialize(caret, field->type));
|
||||||
|
|
||||||
|
} else if (deserializer->getConfig()->allowUnknownFields) {
|
||||||
|
caret.skipBlankChars();
|
||||||
|
if(!caret.canContinueAtChar(':', 1)){
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readObject()/if(config->allowUnknownFields){}]: Error. ':' - expected", ERROR_CODE_OBJECT_SCOPE_COLON_MISSING);
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
}
|
||||||
|
caret.skipBlankChars();
|
||||||
|
skipValue(caret);
|
||||||
|
} else {
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readObject()]: Error. Unknown field", ERROR_CODE_OBJECT_SCOPE_UNKNOWN_FIELD);
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
caret.skipBlankChars();
|
||||||
|
caret.canContinueAtChar(',', 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!caret.canContinueAtChar('}', 1)){
|
||||||
|
if(!caret.hasError()){
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readObject()]: Error. '}' - expected", ERROR_CODE_OBJECT_SCOPE_CLOSE);
|
||||||
|
}
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
caret.setError("[oatpp::parser::json::mapping::Deserializer::readObject()]: Error. '{' - expected", ERROR_CODE_OBJECT_SCOPE_OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return AbstractObjectWrapper::empty();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data::mapping::type::AbstractObjectWrapper Deserializer2::deserialize(parser::Caret& caret, const Type* const type) {
|
||||||
|
auto id = type->classId.id;
|
||||||
|
auto& method = m_methods[id];
|
||||||
|
if(method) {
|
||||||
|
return (*method)(this, caret, type);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("[oatpp::parser::json::mapping::Deserializer2::deserialize()]: "
|
||||||
|
"Error. No deserialize method for type '" + std::string(type->classId.name) + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<Deserializer2::Config>& Deserializer2::getConfig() {
|
||||||
|
return m_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}}}
|
180
src/oatpp/parser/json/mapping/Deserializer2.hpp
Normal file
180
src/oatpp/parser/json/mapping/Deserializer2.hpp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
*
|
||||||
|
* Project _____ __ ____ _ _
|
||||||
|
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||||
|
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||||
|
* (_____)(__)(__)(__) |_| |_|
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef oatpp_parser_json_mapping_Deserializer2_hpp
|
||||||
|
#define oatpp_parser_json_mapping_Deserializer2_hpp
|
||||||
|
|
||||||
|
#include "oatpp/core/data/mapping/type/ListMap.hpp"
|
||||||
|
#include "oatpp/core/data/mapping/type/List.hpp"
|
||||||
|
#include "oatpp/core/data/mapping/type/Object.hpp"
|
||||||
|
#include "oatpp/core/data/mapping/type/Primitive.hpp"
|
||||||
|
#include "oatpp/core/data/mapping/type/Type.hpp"
|
||||||
|
|
||||||
|
#include "oatpp/core/parser/Caret.hpp"
|
||||||
|
|
||||||
|
#include "oatpp/core/collection/LinkedList.hpp"
|
||||||
|
#include "oatpp/core/Types.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Json Deserializer.
|
||||||
|
* Deserialize oatpp DTO object from json. See [Data Transfer Object(DTO) component](https://oatpp.io/docs/components/dto/).
|
||||||
|
*/
|
||||||
|
class Deserializer2 {
|
||||||
|
public:
|
||||||
|
typedef oatpp::data::mapping::type::Type Type;
|
||||||
|
typedef oatpp::data::mapping::type::Type::Property Property;
|
||||||
|
typedef oatpp::data::mapping::type::Type::Properties Properties;
|
||||||
|
|
||||||
|
typedef oatpp::data::mapping::type::Object Object;
|
||||||
|
typedef oatpp::String String;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using PolymorphicWrapper = data::mapping::type::PolymorphicWrapper<T>;
|
||||||
|
|
||||||
|
typedef oatpp::data::mapping::type::AbstractObjectWrapper AbstractObjectWrapper;
|
||||||
|
typedef oatpp::data::mapping::type::List<AbstractObjectWrapper> AbstractList;
|
||||||
|
typedef oatpp::data::mapping::type::ListMap<String, AbstractObjectWrapper> AbstractFieldsMap;
|
||||||
|
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:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializer config.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef AbstractObjectWrapper (*DeserializerMethod)(Deserializer2*, parser::Caret&, const Type* const);
|
||||||
|
private:
|
||||||
|
static void skipScope(oatpp::parser::Caret& caret, v_char8 charOpen, v_char8 charClose);
|
||||||
|
static void skipString(oatpp::parser::Caret& caret);
|
||||||
|
static void skipToken(oatpp::parser::Caret& caret);
|
||||||
|
static void skipValue(oatpp::parser::Caret& caret);
|
||||||
|
private:
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static AbstractObjectWrapper deserializeInt(Deserializer2* deserializer, parser::Caret& caret, const Type* const type){
|
||||||
|
|
||||||
|
(void) deserializer;
|
||||||
|
(void) type;
|
||||||
|
|
||||||
|
if(caret.isAtText("null", true)){
|
||||||
|
return AbstractObjectWrapper(T::Class::getType());
|
||||||
|
} else {
|
||||||
|
return AbstractObjectWrapper(T::ObjectType::createAbstract((typename T::ObjectType::ValueType) caret.parseInt()), T::ObjectWrapper::Class::getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static AbstractObjectWrapper deserializeFloat32(Deserializer2* deserializer, parser::Caret& caret, const Type* const type);
|
||||||
|
static AbstractObjectWrapper deserializeFloat64(Deserializer2* deserializer, parser::Caret& caret, const Type* const type);
|
||||||
|
|
||||||
|
static AbstractObjectWrapper deserializeBoolean(Deserializer2* deserializer, parser::Caret& caret, const Type* const type);
|
||||||
|
|
||||||
|
static AbstractObjectWrapper deserializeString(Deserializer2* deserializer, parser::Caret& caret, const Type* const type);
|
||||||
|
|
||||||
|
static AbstractObjectWrapper deserializeList(Deserializer2* deserializer, parser::Caret& caret, const Type* const type);
|
||||||
|
static AbstractObjectWrapper deserializeFieldsMap(Deserializer2* deserializer, parser::Caret& caret, const Type* const type);
|
||||||
|
static AbstractObjectWrapper deserializeObject(Deserializer2* deserializer, parser::Caret& caret, const Type* const type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Config> m_config;
|
||||||
|
std::vector<DeserializerMethod> m_methods;
|
||||||
|
public:
|
||||||
|
|
||||||
|
Deserializer2(const std::shared_ptr<Config>& config = std::make_shared<Config>());
|
||||||
|
|
||||||
|
void setDeserializerMethod(const data::mapping::type::ClassId& classId, DeserializerMethod method);
|
||||||
|
|
||||||
|
AbstractObjectWrapper deserialize(parser::Caret& caret, const Type* const type);
|
||||||
|
|
||||||
|
const std::shared_ptr<Config>& getConfig();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}}}}
|
||||||
|
|
||||||
|
#endif /* oatpp_parser_json_mapping_Deserializer2_hpp */
|
@ -27,15 +27,16 @@
|
|||||||
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||||
|
|
||||||
ObjectMapper::ObjectMapper(const std::shared_ptr<Serializer::Config>& pSerializerConfig,
|
ObjectMapper::ObjectMapper(const std::shared_ptr<Serializer::Config>& pSerializerConfig,
|
||||||
const std::shared_ptr<Deserializer::Config>& pDeserializerConfig)
|
const std::shared_ptr<Deserializer2::Config>& pDeserializerConfig)
|
||||||
: data::mapping::ObjectMapper(getMapperInfo())
|
: data::mapping::ObjectMapper(getMapperInfo())
|
||||||
, m_serializer(std::make_shared<Serializer>(pSerializerConfig))
|
, m_serializer(std::make_shared<Serializer>(pSerializerConfig))
|
||||||
|
, m_deserializer(std::make_shared<Deserializer2>(pDeserializerConfig))
|
||||||
, serializerConfig(pSerializerConfig)
|
, serializerConfig(pSerializerConfig)
|
||||||
, deserializerConfig(pDeserializerConfig)
|
, deserializerConfig(pDeserializerConfig)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<Serializer::Config>& serializerConfig,
|
std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<Serializer::Config>& serializerConfig,
|
||||||
const std::shared_ptr<Deserializer::Config>& deserializerConfig){
|
const std::shared_ptr<Deserializer2::Config>& deserializerConfig){
|
||||||
return std::make_shared<ObjectMapper>(serializerConfig, deserializerConfig);
|
return std::make_shared<ObjectMapper>(serializerConfig, deserializerConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ void ObjectMapper::write(data::stream::ConsistentOutputStream* stream,
|
|||||||
|
|
||||||
oatpp::data::mapping::type::AbstractObjectWrapper ObjectMapper::read(oatpp::parser::Caret& caret,
|
oatpp::data::mapping::type::AbstractObjectWrapper ObjectMapper::read(oatpp::parser::Caret& caret,
|
||||||
const oatpp::data::mapping::type::Type* const type) const {
|
const oatpp::data::mapping::type::Type* const type) const {
|
||||||
return Deserializer::deserialize(caret, deserializerConfig, type);
|
return m_deserializer->deserialize(caret, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
}}}}
|
}}}}
|
@ -26,7 +26,7 @@
|
|||||||
#define oatpp_parser_json_mapping_ObjectMapper_hpp
|
#define oatpp_parser_json_mapping_ObjectMapper_hpp
|
||||||
|
|
||||||
#include "./Serializer.hpp"
|
#include "./Serializer.hpp"
|
||||||
#include "./Deserializer.hpp"
|
#include "./Deserializer2.hpp"
|
||||||
|
|
||||||
#include "oatpp/core/data/mapping/ObjectMapper.hpp"
|
#include "oatpp/core/data/mapping/ObjectMapper.hpp"
|
||||||
|
|
||||||
@ -45,6 +45,7 @@ private:
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Serializer> m_serializer;
|
std::shared_ptr<Serializer> m_serializer;
|
||||||
|
std::shared_ptr<Deserializer2> m_deserializer;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -52,7 +53,7 @@ public:
|
|||||||
* @param pDeserializerConfig - &id:oatpp::parser::json::mapping::Deserializer::Config;.
|
* @param pDeserializerConfig - &id:oatpp::parser::json::mapping::Deserializer::Config;.
|
||||||
*/
|
*/
|
||||||
ObjectMapper(const std::shared_ptr<Serializer::Config>& pSerializerConfig = Serializer::Config::createShared(),
|
ObjectMapper(const std::shared_ptr<Serializer::Config>& pSerializerConfig = Serializer::Config::createShared(),
|
||||||
const std::shared_ptr<Deserializer::Config>& pDeserializerConfig = Deserializer::Config::createShared());
|
const std::shared_ptr<Deserializer2::Config>& pDeserializerConfig = Deserializer2::Config::createShared());
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,7 +64,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
static std::shared_ptr<ObjectMapper>
|
static std::shared_ptr<ObjectMapper>
|
||||||
createShared(const std::shared_ptr<Serializer::Config>& serializerConfig = Serializer::Config::createShared(),
|
createShared(const std::shared_ptr<Serializer::Config>& serializerConfig = Serializer::Config::createShared(),
|
||||||
const std::shared_ptr<Deserializer::Config>& deserializerConfig = Deserializer::Config::createShared());
|
const std::shared_ptr<Deserializer2::Config>& deserializerConfig = Deserializer2::Config::createShared());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of &id:oatpp::data::mapping::ObjectMapper::write;.
|
* Implementation of &id:oatpp::data::mapping::ObjectMapper::write;.
|
||||||
@ -90,7 +91,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Deserializer config.
|
* Deserializer config.
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<Deserializer::Config> deserializerConfig;
|
std::shared_ptr<Deserializer2::Config> deserializerConfig;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,18 +34,18 @@ Serializer::Serializer(const std::shared_ptr<Config>& config)
|
|||||||
|
|
||||||
m_methods.resize(data::mapping::type::ClassId::getClassCount(), nullptr);
|
m_methods.resize(data::mapping::type::ClassId::getClassCount(), nullptr);
|
||||||
|
|
||||||
m_methods[oatpp::data::mapping::type::__class::String::CLASS_ID.id] = &Serializer::serializeString;
|
setSerializerMethod(oatpp::data::mapping::type::__class::String::CLASS_ID, &Serializer::serializeString);
|
||||||
m_methods[oatpp::data::mapping::type::__class::Int8::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Int8>;
|
setSerializerMethod(oatpp::data::mapping::type::__class::Int8::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int8>);
|
||||||
m_methods[oatpp::data::mapping::type::__class::Int16::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Int16>;
|
setSerializerMethod(oatpp::data::mapping::type::__class::Int16::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int16>);
|
||||||
m_methods[oatpp::data::mapping::type::__class::Int32::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Int32>;
|
setSerializerMethod(oatpp::data::mapping::type::__class::Int32::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int32>);
|
||||||
m_methods[oatpp::data::mapping::type::__class::Int64::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Int64>;
|
setSerializerMethod(oatpp::data::mapping::type::__class::Int64::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int64>);
|
||||||
m_methods[oatpp::data::mapping::type::__class::Float32::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Float32>;
|
setSerializerMethod(oatpp::data::mapping::type::__class::Float32::CLASS_ID, &Serializer::serializePrimitive<oatpp::Float32>);
|
||||||
m_methods[oatpp::data::mapping::type::__class::Float64::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Float64>;
|
setSerializerMethod(oatpp::data::mapping::type::__class::Float64::CLASS_ID, &Serializer::serializePrimitive<oatpp::Float64>);
|
||||||
m_methods[oatpp::data::mapping::type::__class::Boolean::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Boolean>;
|
setSerializerMethod(oatpp::data::mapping::type::__class::Boolean::CLASS_ID, &Serializer::serializePrimitive<oatpp::Boolean>);
|
||||||
|
|
||||||
m_methods[oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID.id] = &Serializer::serializeObject;
|
setSerializerMethod(oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID, &Serializer::serializeObject);
|
||||||
m_methods[oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id] = &Serializer::serializeList;
|
setSerializerMethod(oatpp::data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::serializeList);
|
||||||
m_methods[oatpp::data::mapping::type::__class::AbstractListMap::CLASS_ID.id] = &Serializer::serializeFieldsMap;
|
setSerializerMethod(oatpp::data::mapping::type::__class::AbstractListMap::CLASS_ID, &Serializer::serializeFieldsMap);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,9 +32,6 @@
|
|||||||
#include "oatpp/core/data/mapping/type/Object.hpp"
|
#include "oatpp/core/data/mapping/type/Object.hpp"
|
||||||
#include "oatpp/core/data/mapping/type/Primitive.hpp"
|
#include "oatpp/core/data/mapping/type/Primitive.hpp"
|
||||||
#include "oatpp/core/data/mapping/type/Type.hpp"
|
#include "oatpp/core/data/mapping/type/Type.hpp"
|
||||||
#include "oatpp/core/data/stream/ChunkedBuffer.hpp"
|
|
||||||
|
|
||||||
#include "oatpp/core/parser/Caret.hpp"
|
|
||||||
|
|
||||||
#include "oatpp/core/collection/LinkedList.hpp"
|
#include "oatpp/core/collection/LinkedList.hpp"
|
||||||
#include "oatpp/core/Types.hpp"
|
#include "oatpp/core/Types.hpp"
|
||||||
@ -147,8 +144,8 @@ private:
|
|||||||
data::stream::ConsistentOutputStream* stream,
|
data::stream::ConsistentOutputStream* stream,
|
||||||
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||||
private:
|
private:
|
||||||
std::vector<SerializerMethod> m_methods;
|
|
||||||
std::shared_ptr<Config> m_config;
|
std::shared_ptr<Config> m_config;
|
||||||
|
std::vector<SerializerMethod> m_methods;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Serializer(const std::shared_ptr<Config>& config = std::make_shared<Config>());
|
Serializer(const std::shared_ptr<Config>& config = std::make_shared<Config>());
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
|
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
|
||||||
#include "oatpp/parser/json/mapping/Serializer.hpp"
|
#include "oatpp/parser/json/mapping/Serializer.hpp"
|
||||||
|
#include "oatpp/parser/json/mapping/Deserializer2.hpp"
|
||||||
|
|
||||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ namespace oatpp { namespace test { namespace parser { namespace json { namespace
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
typedef oatpp::parser::json::mapping::Serializer Serializer;
|
typedef oatpp::parser::json::mapping::Serializer Serializer;
|
||||||
typedef oatpp::parser::json::mapping::Deserializer Deserializer;
|
typedef oatpp::parser::json::mapping::Deserializer2 Deserializer;
|
||||||
|
|
||||||
#include OATPP_CODEGEN_BEGIN(DTO)
|
#include OATPP_CODEGEN_BEGIN(DTO)
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ namespace {
|
|||||||
typedef oatpp::data::mapping::type::Object DTO;
|
typedef oatpp::data::mapping::type::Object DTO;
|
||||||
typedef oatpp::parser::Caret ParsingCaret;
|
typedef oatpp::parser::Caret ParsingCaret;
|
||||||
typedef oatpp::parser::json::mapping::Serializer Serializer;
|
typedef oatpp::parser::json::mapping::Serializer Serializer;
|
||||||
typedef oatpp::parser::json::mapping::Deserializer Deserializer;
|
typedef oatpp::parser::json::mapping::Deserializer2 Deserializer;
|
||||||
|
|
||||||
class EmptyDto : public DTO {
|
class EmptyDto : public DTO {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user