mirror of
https://github.com/oatpp/oatpp.git
synced 2025-01-18 16:43:57 +08:00
json::mapping::ObjectMapper. Remove old Serializer.
This commit is contained in:
parent
3c5c0d8f67
commit
fc26498f45
@ -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/Serializer2.cpp oatpp/parser/json/mapping/Serializer2.hpp)
|
||||
)
|
||||
|
||||
set_target_properties(oatpp PROPERTIES
|
||||
CXX_STANDARD 11
|
||||
|
@ -26,15 +26,15 @@
|
||||
|
||||
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||
|
||||
ObjectMapper::ObjectMapper(const std::shared_ptr<Serializer2::Config>& pSerializerConfig,
|
||||
ObjectMapper::ObjectMapper(const std::shared_ptr<Serializer::Config>& pSerializerConfig,
|
||||
const std::shared_ptr<Deserializer::Config>& pDeserializerConfig)
|
||||
: data::mapping::ObjectMapper(getMapperInfo())
|
||||
, m_serializer(std::make_shared<Serializer2>(pSerializerConfig))
|
||||
, m_serializer(std::make_shared<Serializer>(pSerializerConfig))
|
||||
, serializerConfig(pSerializerConfig)
|
||||
, deserializerConfig(pDeserializerConfig)
|
||||
{}
|
||||
|
||||
std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<Serializer2::Config>& serializerConfig,
|
||||
std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<Serializer::Config>& serializerConfig,
|
||||
const std::shared_ptr<Deserializer::Config>& deserializerConfig){
|
||||
return std::make_shared<ObjectMapper>(serializerConfig, deserializerConfig);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef oatpp_parser_json_mapping_ObjectMapper_hpp
|
||||
#define oatpp_parser_json_mapping_ObjectMapper_hpp
|
||||
|
||||
#include "./Serializer2.hpp"
|
||||
#include "./Serializer.hpp"
|
||||
#include "./Deserializer.hpp"
|
||||
|
||||
#include "oatpp/core/data/mapping/ObjectMapper.hpp"
|
||||
@ -44,14 +44,14 @@ private:
|
||||
return info;
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<Serializer2> m_serializer;
|
||||
std::shared_ptr<Serializer> m_serializer;
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param pSerializerConfig - &id:oatpp::parser::json::mapping::Serializer::Config;.
|
||||
* @param pDeserializerConfig - &id:oatpp::parser::json::mapping::Deserializer::Config;.
|
||||
*/
|
||||
ObjectMapper(const std::shared_ptr<Serializer2::Config>& pSerializerConfig = Serializer2::Config::createShared(),
|
||||
ObjectMapper(const std::shared_ptr<Serializer::Config>& pSerializerConfig = Serializer::Config::createShared(),
|
||||
const std::shared_ptr<Deserializer::Config>& pDeserializerConfig = Deserializer::Config::createShared());
|
||||
public:
|
||||
|
||||
@ -62,7 +62,7 @@ public:
|
||||
* @return - `std::shared_ptr` to ObjectMapper.
|
||||
*/
|
||||
static std::shared_ptr<ObjectMapper>
|
||||
createShared(const std::shared_ptr<Serializer2::Config>& serializerConfig = Serializer2::Config::createShared(),
|
||||
createShared(const std::shared_ptr<Serializer::Config>& serializerConfig = Serializer::Config::createShared(),
|
||||
const std::shared_ptr<Deserializer::Config>& deserializerConfig = Deserializer::Config::createShared());
|
||||
|
||||
/**
|
||||
@ -85,7 +85,7 @@ public:
|
||||
/**
|
||||
* Serializer config.
|
||||
*/
|
||||
std::shared_ptr<Serializer2::Config> serializerConfig;
|
||||
std::shared_ptr<Serializer::Config> serializerConfig;
|
||||
|
||||
/**
|
||||
* Deserializer config.
|
||||
|
@ -27,153 +27,168 @@
|
||||
#include "oatpp/parser/json/Utils.hpp"
|
||||
|
||||
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||
|
||||
void Serializer::writeString(oatpp::data::stream::ConsistentOutputStream* stream, p_char8 data, v_buff_size size) {
|
||||
|
||||
Serializer::Serializer(const std::shared_ptr<Config>& config)
|
||||
: m_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>;
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
void Serializer::setSerializerMethod(const data::mapping::type::ClassId& classId, SerializerMethod method) {
|
||||
auto id = classId.id;
|
||||
if(id < m_methods.size()) {
|
||||
m_methods[id] = method;
|
||||
} else {
|
||||
throw std::runtime_error("[oatpp::parser::json::mapping::Serializer::setSerializerMethod()]: Error. Unknown classId");
|
||||
}
|
||||
}
|
||||
|
||||
void Serializer::serializeString(oatpp::data::stream::ConsistentOutputStream* stream, p_char8 data, v_buff_size size) {
|
||||
auto encodedValue = Utils::escapeString(data, size, false);
|
||||
stream->writeCharSimple('\"');
|
||||
stream->writeSimple(encodedValue);
|
||||
stream->writeCharSimple('\"');
|
||||
}
|
||||
|
||||
void Serializer::writeString(oatpp::data::stream::ConsistentOutputStream* stream, const char* data) {
|
||||
writeString(stream, (p_char8)data, std::strlen(data));
|
||||
}
|
||||
|
||||
void Serializer::writeList(oatpp::data::stream::ConsistentOutputStream* stream, const AbstractList::ObjectWrapper& list, const std::shared_ptr<Config>& config) {
|
||||
stream->writeCharSimple('[');
|
||||
bool first = true;
|
||||
auto curr = list->getFirstNode();
|
||||
|
||||
while(curr != nullptr){
|
||||
auto value = curr->getData();
|
||||
if(value || config->includeNullFields) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
writeValue(stream, curr->getData(), config);
|
||||
}
|
||||
curr = curr->getNext();
|
||||
}
|
||||
|
||||
stream->writeCharSimple(']');
|
||||
}
|
||||
|
||||
void Serializer::writeFieldsMap(oatpp::data::stream::ConsistentOutputStream* stream, const AbstractFieldsMap::ObjectWrapper& map, const std::shared_ptr<Config>& config) {
|
||||
stream->writeCharSimple('{');
|
||||
bool first = true;
|
||||
auto curr = map->getFirstEntry();
|
||||
|
||||
while(curr != nullptr){
|
||||
auto value = curr->getValue();
|
||||
if(value || config->includeNullFields) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
auto key = curr->getKey();
|
||||
writeString(stream, key->getData(), key->getSize());
|
||||
stream->writeSimple(":", 1);
|
||||
writeValue(stream, curr->getValue(), config);
|
||||
}
|
||||
curr = curr->getNext();
|
||||
}
|
||||
|
||||
stream->writeCharSimple('}');
|
||||
}
|
||||
|
||||
void Serializer::writeObject(oatpp::data::stream::ConsistentOutputStream* stream, const PolymorphicWrapper<Object>& polymorph, const std::shared_ptr<Config>& config) {
|
||||
|
||||
stream->writeCharSimple('{');
|
||||
|
||||
bool first = true;
|
||||
auto fields = polymorph.valueType->properties->getList();
|
||||
Object* object = polymorph.get();
|
||||
|
||||
for (auto const& field : fields) {
|
||||
|
||||
auto value = field->get(object);
|
||||
if(value || config->includeNullFields) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
writeString(stream, field->name);
|
||||
stream->writeSimple(":", 1);
|
||||
writeValue(stream, value, config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stream->writeCharSimple('}');
|
||||
|
||||
}
|
||||
|
||||
void Serializer::writeValue(oatpp::data::stream::ConsistentOutputStream* stream, const AbstractObjectWrapper& polymorph, const std::shared_ptr<Config>& config) {
|
||||
void Serializer::serializeString(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
auto classId = polymorph.valueType->classId.id;
|
||||
|
||||
if(classId == oatpp::data::mapping::type::__class::String::CLASS_ID.id) {
|
||||
auto str = oatpp::data::mapping::type::static_wrapper_cast<oatpp::base::StrBuffer>(polymorph);
|
||||
writeString(stream, str->getData(), str->getSize());
|
||||
} else if(classId == oatpp::data::mapping::type::__class::Int8::CLASS_ID.id) {
|
||||
writeSimpleData(stream, oatpp::data::mapping::type::static_wrapper_cast<Int8::ObjectType>(polymorph));
|
||||
} else if(classId == oatpp::data::mapping::type::__class::Int16::CLASS_ID.id) {
|
||||
writeSimpleData(stream, oatpp::data::mapping::type::static_wrapper_cast<Int16::ObjectType>(polymorph));
|
||||
} else if(classId == oatpp::data::mapping::type::__class::Int32::CLASS_ID.id) {
|
||||
writeSimpleData(stream, oatpp::data::mapping::type::static_wrapper_cast<Int32::ObjectType>(polymorph));
|
||||
} else if(classId == oatpp::data::mapping::type::__class::Int64::CLASS_ID.id) {
|
||||
writeSimpleData(stream, oatpp::data::mapping::type::static_wrapper_cast<Int64::ObjectType>(polymorph));
|
||||
} else if(classId == oatpp::data::mapping::type::__class::Float32::CLASS_ID.id) {
|
||||
writeSimpleData(stream, oatpp::data::mapping::type::static_wrapper_cast<Float32::ObjectType>(polymorph));
|
||||
} else if(classId == oatpp::data::mapping::type::__class::Float64::CLASS_ID.id) {
|
||||
writeSimpleData(stream, oatpp::data::mapping::type::static_wrapper_cast<Float64::ObjectType>(polymorph));
|
||||
} else if(classId == oatpp::data::mapping::type::__class::Boolean::CLASS_ID.id) {
|
||||
writeSimpleData(stream, oatpp::data::mapping::type::static_wrapper_cast<Boolean::ObjectType>(polymorph));
|
||||
} else if(classId == oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id) {
|
||||
writeList(stream, oatpp::data::mapping::type::static_wrapper_cast<AbstractList>(polymorph), config);
|
||||
} else if(classId == oatpp::data::mapping::type::__class::AbstractListMap::CLASS_ID.id) {
|
||||
// TODO Assert that key is String
|
||||
writeFieldsMap(stream, oatpp::data::mapping::type::static_wrapper_cast<AbstractFieldsMap>(polymorph), config);
|
||||
} else if(classId == oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID.id) {
|
||||
writeObject(stream, oatpp::data::mapping::type::static_wrapper_cast<Object>(polymorph), config);
|
||||
} else {
|
||||
if(config->throwOnUnknownTypes) {
|
||||
throw std::runtime_error("[oatpp::kafka::protocol::mapping::Serializer::writeField]: Unknown data type");
|
||||
} else {
|
||||
writeString(stream, "<unknown-type>");
|
||||
|
||||
auto str = static_cast<oatpp::base::StrBuffer*>(polymorph.get());
|
||||
|
||||
serializeString(stream, str->getData(), str->getSize());
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializeList(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* list = static_cast<AbstractList*>(polymorph.get());
|
||||
|
||||
stream->writeCharSimple('[');
|
||||
bool first = true;
|
||||
auto curr = list->getFirstNode();
|
||||
|
||||
while(curr != nullptr){
|
||||
auto value = curr->getData();
|
||||
if(value || serializer->getConfig()->includeNullFields) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
serializer->serialize(stream, curr->getData());
|
||||
}
|
||||
curr = curr->getNext();
|
||||
}
|
||||
|
||||
|
||||
stream->writeCharSimple(']');
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializeToStream(oatpp::data::stream::ConsistentOutputStream* stream,
|
||||
const oatpp::data::mapping::type::AbstractObjectWrapper& polymorph,
|
||||
const std::shared_ptr<Config>& config)
|
||||
void Serializer::serializeFieldsMap(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph)
|
||||
{
|
||||
|
||||
auto type = polymorph.valueType;
|
||||
if(type->classId.id == oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID.id) {
|
||||
writeObject(stream, oatpp::data::mapping::type::static_wrapper_cast<Object>(polymorph), config);
|
||||
} else if(type->classId.id == oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id) {
|
||||
writeList(stream, oatpp::data::mapping::type::static_wrapper_cast<AbstractList>(polymorph), config);
|
||||
} else if(type->classId.id == oatpp::data::mapping::type::__class::AbstractListMap::CLASS_ID.id) {
|
||||
writeFieldsMap(stream, oatpp::data::mapping::type::static_wrapper_cast<AbstractFieldsMap>(polymorph), config);
|
||||
} else {
|
||||
throw std::runtime_error("[oatpp::parser::json::mapping::Serializer::serialize()]: Unknown parameter type");
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
auto map = static_cast<AbstractFieldsMap*>(polymorph.get());
|
||||
|
||||
stream->writeCharSimple('{');
|
||||
bool first = true;
|
||||
auto curr = map->getFirstEntry();
|
||||
|
||||
while(curr != nullptr){
|
||||
auto value = curr->getValue();
|
||||
if(value || serializer->getConfig()->includeNullFields) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
auto key = curr->getKey();
|
||||
serializeString(stream, key->getData(), key->getSize());
|
||||
stream->writeSimple(":", 1);
|
||||
serializer->serialize(stream, curr->getValue());
|
||||
}
|
||||
curr = curr->getNext();
|
||||
}
|
||||
|
||||
stream->writeCharSimple('}');
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serialize(const std::shared_ptr<oatpp::data::stream::ConsistentOutputStream>& stream,
|
||||
const oatpp::data::mapping::type::AbstractObjectWrapper& polymorph,
|
||||
const std::shared_ptr<Config>& config)
|
||||
void Serializer::serializeObject(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph)
|
||||
{
|
||||
|
||||
if(config->useBeautifier) {
|
||||
json::Beautifier beautifier(stream.get(), " ", "\n");
|
||||
serializeToStream(&beautifier, polymorph, config);
|
||||
} else {
|
||||
serializeToStream(stream.get(), polymorph, config);
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
stream->writeCharSimple('{');
|
||||
|
||||
bool first = true;
|
||||
auto fields = polymorph.valueType->properties->getList();
|
||||
Object* object = static_cast<Object*>(polymorph.get());
|
||||
|
||||
for (auto const& field : fields) {
|
||||
|
||||
auto value = field->get(object);
|
||||
if(value || serializer->getConfig()->includeNullFields) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
serializeString(stream, (p_char8)field->name, std::strlen(field->name));
|
||||
stream->writeSimple(":", 1);
|
||||
serializer->serialize(stream, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stream->writeCharSimple('}');
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Serializer::serialize(data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph)
|
||||
{
|
||||
auto id = polymorph.valueType->classId.id;
|
||||
auto& method = m_methods[id];
|
||||
if(method) {
|
||||
(*method)(this, stream, polymorph);
|
||||
} else {
|
||||
throw std::runtime_error("[oatpp::parser::json::mapping::Serializer::serialize()]: "
|
||||
"Error. No serialize method for type '" + std::string(polymorph.valueType->classId.name) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
const std::shared_ptr<Serializer::Config>& Serializer::getConfig() {
|
||||
return m_config;
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include "oatpp/core/collection/LinkedList.hpp"
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||
|
||||
/**
|
||||
@ -50,17 +52,17 @@ 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:
|
||||
/**
|
||||
* Serializer config.
|
||||
@ -109,47 +111,56 @@ public:
|
||||
* Beautifier new line.
|
||||
*/
|
||||
oatpp::String beautifierNewLine = "\n";
|
||||
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
typedef void (*SerializerMethod)(Serializer*,
|
||||
data::stream::ConsistentOutputStream*,
|
||||
const data::mapping::type::AbstractObjectWrapper&);
|
||||
private:
|
||||
|
||||
static void writeString(oatpp::data::stream::ConsistentOutputStream* stream, p_char8 data, v_buff_size size);
|
||||
static void writeString(oatpp::data::stream::ConsistentOutputStream* stream, const char* data);
|
||||
|
||||
|
||||
template<class T>
|
||||
static void writeSimpleData(oatpp::data::stream::ConsistentOutputStream* stream, const PolymorphicWrapper<T>& value){
|
||||
if(value){
|
||||
stream->writeAsString(value.get()->getValue());
|
||||
static void serializePrimitive(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph){
|
||||
if(polymorph){
|
||||
stream->writeAsString(static_cast<typename T::ObjectType*>(polymorph.get())->getValue());
|
||||
} else {
|
||||
stream->writeSimple("null", 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void writeList(oatpp::data::stream::ConsistentOutputStream* stream, const AbstractList::ObjectWrapper& list, const std::shared_ptr<Config>& config);
|
||||
static void writeFieldsMap(oatpp::data::stream::ConsistentOutputStream* stream, const AbstractFieldsMap::ObjectWrapper& map, const std::shared_ptr<Config>& config);
|
||||
static void writeObject(oatpp::data::stream::ConsistentOutputStream* stream, const PolymorphicWrapper<Object>& polymorph, const std::shared_ptr<Config>& config);
|
||||
|
||||
static void writeValue(oatpp::data::stream::ConsistentOutputStream* stream, const AbstractObjectWrapper& polymorph, const std::shared_ptr<Config>& config);
|
||||
|
||||
static void serializeToStream(oatpp::data::stream::ConsistentOutputStream* stream,
|
||||
const oatpp::data::mapping::type::AbstractObjectWrapper& polymorph,
|
||||
const std::shared_ptr<Config>& config);
|
||||
static void serializeString(oatpp::data::stream::ConsistentOutputStream* stream, p_char8 data, v_buff_size size);
|
||||
static void serializeString(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
|
||||
static void serializeList(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
|
||||
static void serializeFieldsMap(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
|
||||
static void serializeObject(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
private:
|
||||
std::vector<SerializerMethod> m_methods;
|
||||
std::shared_ptr<Config> m_config;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Serialize DTO object to stream.
|
||||
* @param stream - stream to write serialized object to. &id:oatpp::data::stream::ConsistentOutputStream;. <br>
|
||||
* @param polymorph - DTO object to serialize.
|
||||
* @param config - &l:Serializer::Config;.
|
||||
*/
|
||||
static void serialize(const std::shared_ptr<oatpp::data::stream::ConsistentOutputStream>& stream,
|
||||
const oatpp::data::mapping::type::AbstractObjectWrapper& polymorph,
|
||||
const std::shared_ptr<Config>& config);
|
||||
|
||||
Serializer(const std::shared_ptr<Config>& config = std::make_shared<Config>());
|
||||
|
||||
void setSerializerMethod(const data::mapping::type::ClassId& classId, SerializerMethod method);
|
||||
|
||||
void serialize(data::stream::ConsistentOutputStream* stream, const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
|
||||
const std::shared_ptr<Config>& getConfig();
|
||||
|
||||
};
|
||||
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /* oatpp_parser_json_mapping_Serializer_hpp */
|
||||
|
@ -1,194 +0,0 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 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 "Serializer2.hpp"
|
||||
|
||||
#include "oatpp/parser/json/Utils.hpp"
|
||||
|
||||
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||
|
||||
Serializer2::Serializer2(const std::shared_ptr<Config>& config)
|
||||
: m_config(config)
|
||||
{
|
||||
|
||||
m_methods.resize(data::mapping::type::ClassId::getClassCount(), nullptr);
|
||||
|
||||
m_methods[oatpp::data::mapping::type::__class::String::CLASS_ID.id] = &Serializer2::serializeString;
|
||||
m_methods[oatpp::data::mapping::type::__class::Int8::CLASS_ID.id] = &Serializer2::serializePrimitive<oatpp::Int8>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Int16::CLASS_ID.id] = &Serializer2::serializePrimitive<oatpp::Int16>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Int32::CLASS_ID.id] = &Serializer2::serializePrimitive<oatpp::Int32>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Int64::CLASS_ID.id] = &Serializer2::serializePrimitive<oatpp::Int64>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Float32::CLASS_ID.id] = &Serializer2::serializePrimitive<oatpp::Float32>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Float64::CLASS_ID.id] = &Serializer2::serializePrimitive<oatpp::Float64>;
|
||||
m_methods[oatpp::data::mapping::type::__class::Boolean::CLASS_ID.id] = &Serializer2::serializePrimitive<oatpp::Boolean>;
|
||||
|
||||
m_methods[oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID.id] = &Serializer2::serializeObject;
|
||||
m_methods[oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id] = &Serializer2::serializeList;
|
||||
m_methods[oatpp::data::mapping::type::__class::AbstractListMap::CLASS_ID.id] = &Serializer2::serializeFieldsMap;
|
||||
|
||||
}
|
||||
|
||||
void Serializer2::setSerializerMethod(const data::mapping::type::ClassId& classId, SerializerMethod method) {
|
||||
auto id = classId.id;
|
||||
if(id < m_methods.size()) {
|
||||
m_methods[id] = method;
|
||||
} else {
|
||||
throw std::runtime_error("[oatpp::parser::json::mapping::Serializer::setSerializerMethod()]: Error. Unknown classId");
|
||||
}
|
||||
}
|
||||
|
||||
void Serializer2::serializeString(oatpp::data::stream::ConsistentOutputStream* stream, p_char8 data, v_buff_size size) {
|
||||
auto encodedValue = Utils::escapeString(data, size, false);
|
||||
stream->writeCharSimple('\"');
|
||||
stream->writeSimple(encodedValue);
|
||||
stream->writeCharSimple('\"');
|
||||
}
|
||||
|
||||
void Serializer2::serializeString(Serializer2* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
auto str = static_cast<oatpp::base::StrBuffer*>(polymorph.get());
|
||||
|
||||
serializeString(stream, str->getData(), str->getSize());
|
||||
|
||||
}
|
||||
|
||||
void Serializer2::serializeList(Serializer2* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* list = static_cast<AbstractList*>(polymorph.get());
|
||||
|
||||
stream->writeCharSimple('[');
|
||||
bool first = true;
|
||||
auto curr = list->getFirstNode();
|
||||
|
||||
while(curr != nullptr){
|
||||
auto value = curr->getData();
|
||||
if(value || serializer->getConfig()->includeNullFields) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
serializer->serialize(stream, curr->getData());
|
||||
}
|
||||
curr = curr->getNext();
|
||||
}
|
||||
|
||||
stream->writeCharSimple(']');
|
||||
|
||||
}
|
||||
|
||||
void Serializer2::serializeFieldsMap(Serializer2* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
auto map = static_cast<AbstractFieldsMap*>(polymorph.get());
|
||||
|
||||
stream->writeCharSimple('{');
|
||||
bool first = true;
|
||||
auto curr = map->getFirstEntry();
|
||||
|
||||
while(curr != nullptr){
|
||||
auto value = curr->getValue();
|
||||
if(value || serializer->getConfig()->includeNullFields) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
auto key = curr->getKey();
|
||||
serializeString(stream, key->getData(), key->getSize());
|
||||
stream->writeSimple(":", 1);
|
||||
serializer->serialize(stream, curr->getValue());
|
||||
}
|
||||
curr = curr->getNext();
|
||||
}
|
||||
|
||||
stream->writeCharSimple('}');
|
||||
|
||||
}
|
||||
|
||||
void Serializer2::serializeObject(Serializer2* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
stream->writeCharSimple('{');
|
||||
|
||||
bool first = true;
|
||||
auto fields = polymorph.valueType->properties->getList();
|
||||
Object* object = static_cast<Object*>(polymorph.get());
|
||||
|
||||
for (auto const& field : fields) {
|
||||
|
||||
auto value = field->get(object);
|
||||
if(value || serializer->getConfig()->includeNullFields) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
serializeString(stream, (p_char8)field->name, std::strlen(field->name));
|
||||
stream->writeSimple(":", 1);
|
||||
serializer->serialize(stream, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stream->writeCharSimple('}');
|
||||
|
||||
}
|
||||
|
||||
void Serializer2::serialize(data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph)
|
||||
{
|
||||
auto id = polymorph.valueType->classId.id;
|
||||
auto& method = m_methods[id];
|
||||
if(method) {
|
||||
(*method)(this, stream, polymorph);
|
||||
} else {
|
||||
throw std::runtime_error("[oatpp::parser::json::mapping::Serializer::serialize()]: "
|
||||
"Error. No serialize method for type '" + std::string(polymorph.valueType->classId.name) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
const std::shared_ptr<Serializer2::Config>& Serializer2::getConfig() {
|
||||
return m_config;
|
||||
}
|
||||
|
||||
}}}}
|
@ -1,166 +0,0 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 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_Serializer2_hpp
|
||||
#define oatpp_parser_json_mapping_Serializer2_hpp
|
||||
|
||||
#include "oatpp/parser/json/Beautifier.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/data/stream/ChunkedBuffer.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 Serializer.
|
||||
* Serializes oatpp DTO object to json. See [Data Transfer Object(DTO) component](https://oatpp.io/docs/components/dto/).
|
||||
*/
|
||||
class Serializer2 {
|
||||
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:
|
||||
/**
|
||||
* Serializer 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>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Include fields with value == nullptr into serialized json.
|
||||
*/
|
||||
bool includeNullFields = true;
|
||||
|
||||
/**
|
||||
* If `true` - insert string `"<unknown-type>"` in json field value in case unknown field found.
|
||||
* Fail if `false`.
|
||||
* Known types for this serializer are:<br>
|
||||
* (String, Int8, Int16, Int32, Int64, Float32, Float64, Boolean, DTOs, List, Fields).
|
||||
*/
|
||||
bool throwOnUnknownTypes = true;
|
||||
|
||||
/**
|
||||
* Use JSON Beautifier.
|
||||
*/
|
||||
bool useBeautifier = false;
|
||||
|
||||
/**
|
||||
* Beautifier Indent.
|
||||
*/
|
||||
oatpp::String beautifierIndent = " ";
|
||||
|
||||
/**
|
||||
* Beautifier new line.
|
||||
*/
|
||||
oatpp::String beautifierNewLine = "\n";
|
||||
|
||||
};
|
||||
public:
|
||||
typedef void (*SerializerMethod)(Serializer2*,
|
||||
data::stream::ConsistentOutputStream*,
|
||||
const data::mapping::type::AbstractObjectWrapper&);
|
||||
private:
|
||||
|
||||
template<class T>
|
||||
static void serializePrimitive(Serializer2* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph){
|
||||
if(polymorph){
|
||||
stream->writeAsString(static_cast<typename T::ObjectType*>(polymorph.get())->getValue());
|
||||
} else {
|
||||
stream->writeSimple("null", 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void serializeString(oatpp::data::stream::ConsistentOutputStream* stream, p_char8 data, v_buff_size size);
|
||||
static void serializeString(Serializer2* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
|
||||
static void serializeList(Serializer2* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
|
||||
static void serializeFieldsMap(Serializer2* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
|
||||
static void serializeObject(Serializer2* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
private:
|
||||
std::vector<SerializerMethod> m_methods;
|
||||
std::shared_ptr<Config> m_config;
|
||||
public:
|
||||
|
||||
Serializer2(const std::shared_ptr<Config>& config = std::make_shared<Config>());
|
||||
|
||||
void setSerializerMethod(const data::mapping::type::ClassId& classId, SerializerMethod method);
|
||||
|
||||
void serialize(data::stream::ConsistentOutputStream* stream, const data::mapping::type::AbstractObjectWrapper& polymorph);
|
||||
|
||||
const std::shared_ptr<Config>& getConfig();
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /* oatpp_parser_json_mapping_Serializer2_hpp */
|
@ -25,7 +25,7 @@
|
||||
#include "DTOMapperPerfTest.hpp"
|
||||
|
||||
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
|
||||
#include "oatpp/parser/json/mapping/Serializer2.hpp"
|
||||
#include "oatpp/parser/json/mapping/Serializer.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
|
||||
@ -38,7 +38,7 @@ namespace oatpp { namespace test { namespace parser { namespace json { namespace
|
||||
|
||||
namespace {
|
||||
|
||||
typedef oatpp::parser::json::mapping::Serializer2 Serializer;
|
||||
typedef oatpp::parser::json::mapping::Serializer Serializer;
|
||||
typedef oatpp::parser::json::mapping::Deserializer Deserializer;
|
||||
|
||||
#include OATPP_CODEGEN_BEGIN(DTO)
|
||||
@ -72,7 +72,7 @@ void DTOMapperPerfTest::onRun() {
|
||||
|
||||
v_int32 numIterations = 1000000;
|
||||
|
||||
auto serializer2 = std::make_shared<oatpp::parser::json::mapping::Serializer2>();
|
||||
auto serializer2 = std::make_shared<oatpp::parser::json::mapping::Serializer>();
|
||||
auto mapper = oatpp::parser::json::mapping::ObjectMapper::createShared();
|
||||
|
||||
auto test1 = Test1::createTestInstance();
|
||||
@ -80,7 +80,7 @@ void DTOMapperPerfTest::onRun() {
|
||||
OATPP_LOGV(TAG, "json='%s'", (const char*) test1_Text->getData());
|
||||
|
||||
{
|
||||
PerformanceChecker checker("Serializer2");
|
||||
PerformanceChecker checker("Serializer");
|
||||
for(v_int32 i = 0; i < numIterations; i ++) {
|
||||
oatpp::data::stream::BufferOutputStream stream;
|
||||
serializer2->serialize(&stream, test1);
|
||||
|
@ -35,7 +35,7 @@ namespace {
|
||||
|
||||
typedef oatpp::data::mapping::type::Object DTO;
|
||||
typedef oatpp::parser::Caret ParsingCaret;
|
||||
typedef oatpp::parser::json::mapping::Serializer2 Serializer;
|
||||
typedef oatpp::parser::json::mapping::Serializer Serializer;
|
||||
typedef oatpp::parser::json::mapping::Deserializer Deserializer;
|
||||
|
||||
class EmptyDto : public DTO {
|
||||
|
Loading…
Reference in New Issue
Block a user