mirror of
https://github.com/oatpp/oatpp.git
synced 2025-01-18 16:43:57 +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.hpp
|
||||
oatpp/web/url/mapping/Router.hpp
|
||||
)
|
||||
oatpp/parser/json/mapping/Deserializer2.cpp oatpp/parser/json/mapping/Deserializer2.hpp)
|
||||
|
||||
set_target_properties(oatpp PROPERTIES
|
||||
CXX_STANDARD 11
|
||||
|
@ -128,11 +128,13 @@ String operator + (const String& a, const String& b);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
template<typename ValueType, class Clazz>
|
||||
template<typename TValueType, class Clazz>
|
||||
class Primitive : public oatpp::base::Countable {
|
||||
public:
|
||||
typedef TValueType ValueType;
|
||||
public:
|
||||
OBJECT_POOL(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 {
|
||||
|
||||
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())
|
||||
, m_serializer(std::make_shared<Serializer>(pSerializerConfig))
|
||||
, m_deserializer(std::make_shared<Deserializer2>(pDeserializerConfig))
|
||||
, serializerConfig(pSerializerConfig)
|
||||
, deserializerConfig(pDeserializerConfig)
|
||||
{}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -46,7 +47,7 @@ void ObjectMapper::write(data::stream::ConsistentOutputStream* stream,
|
||||
|
||||
oatpp::data::mapping::type::AbstractObjectWrapper ObjectMapper::read(oatpp::parser::Caret& caret,
|
||||
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
|
||||
|
||||
#include "./Serializer.hpp"
|
||||
#include "./Deserializer.hpp"
|
||||
#include "./Deserializer2.hpp"
|
||||
|
||||
#include "oatpp/core/data/mapping/ObjectMapper.hpp"
|
||||
|
||||
@ -45,6 +45,7 @@ private:
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<Serializer> m_serializer;
|
||||
std::shared_ptr<Deserializer2> m_deserializer;
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
@ -52,7 +53,7 @@ public:
|
||||
* @param pDeserializerConfig - &id:oatpp::parser::json::mapping::Deserializer::Config;.
|
||||
*/
|
||||
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:
|
||||
|
||||
/**
|
||||
@ -63,7 +64,7 @@ public:
|
||||
*/
|
||||
static std::shared_ptr<ObjectMapper>
|
||||
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;.
|
||||
@ -90,7 +91,7 @@ public:
|
||||
/**
|
||||
* 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[oatpp::data::mapping::type::__class::String::CLASS_ID.id] = &Serializer::serializeString;
|
||||
m_methods[oatpp::data::mapping::type::__class::Int8::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Int8>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Int16::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Int16>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Int32::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Int32>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Int64::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Int64>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Float32::CLASS_ID.id] = &Serializer::serializePrimitive<oatpp::Float32>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Float64::CLASS_ID.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::String::CLASS_ID, &Serializer::serializeString);
|
||||
setSerializerMethod(oatpp::data::mapping::type::__class::Int8::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int8>);
|
||||
setSerializerMethod(oatpp::data::mapping::type::__class::Int16::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int16>);
|
||||
setSerializerMethod(oatpp::data::mapping::type::__class::Int32::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int32>);
|
||||
setSerializerMethod(oatpp::data::mapping::type::__class::Int64::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int64>);
|
||||
setSerializerMethod(oatpp::data::mapping::type::__class::Float32::CLASS_ID, &Serializer::serializePrimitive<oatpp::Float32>);
|
||||
setSerializerMethod(oatpp::data::mapping::type::__class::Float64::CLASS_ID, &Serializer::serializePrimitive<oatpp::Float64>);
|
||||
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;
|
||||
m_methods[oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id] = &Serializer::serializeList;
|
||||
m_methods[oatpp::data::mapping::type::__class::AbstractListMap::CLASS_ID.id] = &Serializer::serializeFieldsMap;
|
||||
setSerializerMethod(oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID, &Serializer::serializeObject);
|
||||
setSerializerMethod(oatpp::data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::serializeList);
|
||||
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/Primitive.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/Types.hpp"
|
||||
@ -147,8 +144,8 @@ private:
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
private:
|
||||
std::vector<SerializerMethod> m_methods;
|
||||
std::shared_ptr<Config> m_config;
|
||||
std::vector<SerializerMethod> m_methods;
|
||||
public:
|
||||
|
||||
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/Serializer.hpp"
|
||||
#include "oatpp/parser/json/mapping/Deserializer2.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
|
||||
@ -39,7 +40,7 @@ namespace oatpp { namespace test { namespace parser { namespace json { namespace
|
||||
namespace {
|
||||
|
||||
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)
|
||||
|
||||
|
@ -36,7 +36,7 @@ namespace {
|
||||
typedef oatpp::data::mapping::type::Object DTO;
|
||||
typedef oatpp::parser::Caret ParsingCaret;
|
||||
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 {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user