json::ObjectMapper: use mapping::Tree

This commit is contained in:
Leonid Stryzhevskyi 2024-05-01 03:56:03 +03:00
parent 77ca525d2c
commit b890a15840
8 changed files with 228 additions and 414 deletions

View File

@ -120,11 +120,6 @@ void ObjectToTreeMapper::mapAny(const ObjectToTreeMapper* mapper, MappingState&
void ObjectToTreeMapper::mapEnum(const ObjectToTreeMapper* mapper, MappingState& state, const oatpp::Void& polymorph) {
if(!polymorph) {
state.tree->setNull();
return;
}
auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::PolymorphicDispatcher*>(
polymorph.getValueType()->polymorphicDispatcher
);

View File

@ -26,34 +26,39 @@
namespace oatpp { namespace json {
ObjectMapper::ObjectMapper(const std::shared_ptr<Serializer::Config>& serializerConfig,
ObjectMapper::ObjectMapper(const std::shared_ptr<SerializerConfig>& serializerConfig,
const std::shared_ptr<DeserializerConfig>& deserializerConfig)
: data::mapping::ObjectMapper(getMapperInfo())
, m_serializer(std::make_shared<Serializer>(serializerConfig))
, m_serializerConfig(serializerConfig)
, m_deserializerConfig(deserializerConfig)
{}
ObjectMapper::ObjectMapper(const std::shared_ptr<Serializer>& serializer)
: data::mapping::ObjectMapper(getMapperInfo())
, m_serializer(serializer)
, m_deserializerConfig(std::make_shared<DeserializerConfig>())
{}
std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<Serializer::Config>& serializerConfig,
std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<SerializerConfig>& serializerConfig,
const std::shared_ptr<DeserializerConfig>& deserializerConfig)
{
return std::make_shared<ObjectMapper>(serializerConfig, deserializerConfig);
}
std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<Serializer>& serializer,
const std::shared_ptr<Deserializer>& deserializer)
{
return std::make_shared<ObjectMapper>(serializer);
}
void ObjectMapper::write(data::stream::ConsistentOutputStream* stream, const oatpp::Void& variant) const {
data::mapping::Tree tree;
{
data::mapping::ObjectToTreeMapper::MappingState state;
state.config = m_serializerConfig.get();
state.tree = &tree;
m_objectToTreeMapper.map(state, variant);
if(!state.errorStack.empty()) {
throw std::runtime_error(state.errorStacktrace());
}
}
{
Serializer::MappingState state;
state.config = m_serializerConfig.get();
state.tree = &tree;
Serializer::serializeToStream(stream, state);
}
void ObjectMapper::write(data::stream::ConsistentOutputStream* stream,
const oatpp::Void& variant) const {
m_serializer->serializeToStream(stream, variant);
}
oatpp::Void ObjectMapper::read(oatpp::utils::parser::Caret& caret, const oatpp::data::mapping::type::Type* const type) const {
@ -90,8 +95,8 @@ oatpp::Void ObjectMapper::read(oatpp::utils::parser::Caret& caret, const oatpp::
}
std::shared_ptr<Serializer> ObjectMapper::getSerializer() {
return m_serializer;
std::shared_ptr<ObjectMapper::SerializerConfig> ObjectMapper::getSerializerConfig() {
return m_serializerConfig;
}
std::shared_ptr<ObjectMapper::DeserializerConfig> ObjectMapper::getDeserializerConfig() {

View File

@ -28,6 +28,7 @@
#include "./Serializer.hpp"
#include "./Deserializer.hpp"
#include "oatpp/data/mapping/ObjectToTreeMapper.hpp"
#include "oatpp/data/mapping/TreeToObjectMapper.hpp"
#include "oatpp/data/mapping/ObjectMapper.hpp"
@ -50,51 +51,31 @@ public:
class DeserializerConfig : public data::mapping::TreeToObjectMapper::Config, public Deserializer::Config {
public:
};
public:
class SerializerConfig : public data::mapping::ObjectToTreeMapper::Config, public Serializer::Config {
public:
};
private:
std::shared_ptr<Serializer> m_serializer;
std::shared_ptr<SerializerConfig> m_serializerConfig;
std::shared_ptr<DeserializerConfig> m_deserializerConfig;
private:
data::mapping::ObjectToTreeMapper m_objectToTreeMapper;
data::mapping::TreeToObjectMapper m_treeToObjectMapper;
public:
/**
* Constructor.
* @param serializerConfig - &id:oatpp::json::Serializer::Config;.
* @param deserializerConfig - &id:oatpp::json::Deserializer::Config;.
*/
ObjectMapper(const std::shared_ptr<Serializer::Config>& serializerConfig,
const std::shared_ptr<DeserializerConfig>& deserializerConfig);
/**
* Constructor.
* @param serializer
* @param deserializer
*/
ObjectMapper(const std::shared_ptr<Serializer>& serializer = std::make_shared<Serializer>());
ObjectMapper(const std::shared_ptr<SerializerConfig>& serializerConfig = std::make_shared<SerializerConfig>(),
const std::shared_ptr<DeserializerConfig>& deserializerConfig = std::make_shared<DeserializerConfig>());
public:
/**
* Create shared ObjectMapper.
* @param serializerConfig - &id:oatpp::json::Serializer::Config;.
* @param deserializerConfig - &id:oatpp::json::Deserializer::Config;.
* @return - `std::shared_ptr` to ObjectMapper.
*/
static std::shared_ptr<ObjectMapper>
createShared(const std::shared_ptr<Serializer::Config>& serializerConfig,
const std::shared_ptr<DeserializerConfig>& deserializerConfig);
/**
* Create shared ObjectMapper.
* @param serializer
* @param deserializer
* @return
*/
static std::shared_ptr<ObjectMapper>
createShared(const std::shared_ptr<Serializer>& serializer = std::make_shared<Serializer>(),
const std::shared_ptr<Deserializer>& deserializer = std::make_shared<Deserializer>());
createShared(const std::shared_ptr<SerializerConfig>& serializerConfig = std::make_shared<SerializerConfig>(),
const std::shared_ptr<DeserializerConfig>& deserializerConfig = std::make_shared<DeserializerConfig>());
/**
* Implementation of &id:oatpp::data::mapping::ObjectMapper::write;.
@ -112,16 +93,8 @@ public:
oatpp::Void read(oatpp::utils::parser::Caret& caret, const oatpp::data::mapping::type::Type* const type) const override;
/**
* Get serializer.
* @return
*/
std::shared_ptr<Serializer> getSerializer();
std::shared_ptr<ObjectMapper::SerializerConfig> getSerializerConfig();
/**
* Get deserializer.
* @return
*/
std::shared_ptr<DeserializerConfig> getDeserializerConfig();
};

View File

@ -25,53 +25,17 @@
#include "Serializer.hpp"
#include "./Utils.hpp"
#include "oatpp/data/mapping/type/Any.hpp"
#include "oatpp/data/stream/BufferStream.hpp"
#include "oatpp/utils/Conversion.hpp"
namespace oatpp { namespace json {
Serializer::Serializer(const std::shared_ptr<Config>& config)
: m_config(config)
{
m_methods.resize(static_cast<size_t>(data::mapping::type::ClassId::getClassCount()), nullptr);
setSerializerMethod(data::mapping::type::__class::String::CLASS_ID, &Serializer::serializeString);
setSerializerMethod(data::mapping::type::__class::Any::CLASS_ID, &Serializer::serializeAny);
setSerializerMethod(data::mapping::type::__class::Int8::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int8>);
setSerializerMethod(data::mapping::type::__class::UInt8::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt8>);
setSerializerMethod(data::mapping::type::__class::Int16::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int16>);
setSerializerMethod(data::mapping::type::__class::UInt16::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt16>);
setSerializerMethod(data::mapping::type::__class::Int32::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int32>);
setSerializerMethod(data::mapping::type::__class::UInt32::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt32>);
setSerializerMethod(data::mapping::type::__class::Int64::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int64>);
setSerializerMethod(data::mapping::type::__class::UInt64::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt64>);
setSerializerMethod(data::mapping::type::__class::Float32::CLASS_ID, &Serializer::serializePrimitive<oatpp::Float32>);
setSerializerMethod(data::mapping::type::__class::Float64::CLASS_ID, &Serializer::serializePrimitive<oatpp::Float64>);
setSerializerMethod(data::mapping::type::__class::Boolean::CLASS_ID, &Serializer::serializePrimitive<oatpp::Boolean>);
setSerializerMethod(data::mapping::type::__class::AbstractObject::CLASS_ID, &Serializer::serializeObject);
setSerializerMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Serializer::serializeEnum);
setSerializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::serializeCollection);
setSerializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::serializeCollection);
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Serializer::serializeCollection);
setSerializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Serializer::serializeMap);
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Serializer::serializeMap);
}
void Serializer::setSerializerMethod(const data::mapping::type::ClassId& classId, SerializerMethod method) {
const v_uint32 id = static_cast<v_uint32>(classId.id);
if(id >= m_methods.size()) {
m_methods.resize(id + 1, nullptr);
oatpp::String Serializer::MappingState::errorStacktrace() const {
data::stream::BufferOutputStream ss;
for(auto& s : errorStack) {
ss << s << "\n";
}
m_methods[id] = method;
return ss.toString();
}
void Serializer::serializeString(data::stream::ConsistentOutputStream* stream, const char* data, v_buff_size size, v_uint32 escapeFlags) {
@ -81,222 +45,188 @@ void Serializer::serializeString(data::stream::ConsistentOutputStream* stream, c
stream->writeCharSimple('\"');
}
void Serializer::serializeString(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
void Serializer::serializeNull(MappingState& state) {
state.stream->writeSimple("null");
}
void Serializer::serializeString(MappingState& state) {
const auto& str = state.tree->getString();
serializeString(state.stream, str->data(), static_cast<v_buff_size>(str->size()), state.config->escapeFlags);
}
void Serializer::serializeArray(MappingState& state) {
state.stream->writeCharSimple('[');
MappingState nestedState;
nestedState.stream = state.stream;
nestedState.config = state.config;
auto& vector = state.tree->getVector();
v_int64 index = 0;
for(auto& tree : vector) {
nestedState.tree = &tree;
if(!tree.isNull() || state.config->includeNullElements) {
if(index > 0) state.stream->writeSimple(",", 1);
serialize(nestedState);
if(!nestedState.errorStack.empty()) {
state.errorStack.splice(state.errorStack.end(), nestedState.errorStack);
state.errorStack.emplace_back("[oatpp::json::Serializer::serializeArray()]: index=" + utils::Conversion::int64ToStr(index));
return;
}
}
index ++;
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
auto str = static_cast<std::string*>(polymorph.get());
serializeString(stream, str->data(), static_cast<v_buff_size>(str->size()), serializer->m_config->escapeFlags);
state.stream->writeCharSimple(']');
}
void Serializer::serializeAny(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
void Serializer::serializeMap(MappingState& state) {
state.stream->writeCharSimple('{');
MappingState nestedState;
nestedState.stream = state.stream;
nestedState.config = state.config;
auto& map = state.tree->getMap();
auto mapSize = map.size();
for(v_uint64 index = 0; index < mapSize; index ++) {
const auto& pair = map[index];
nestedState.tree = &pair.second.get();
if(!nestedState.tree->isNull() || state.config->includeNullElements) {
if(index > 0) state.stream->writeSimple(",", 1);
const auto& str = pair.first;
serializeString(state.stream, str->data(), static_cast<v_buff_size>(str->size()), state.config->escapeFlags);
state.stream->writeCharSimple(':');
serialize(nestedState);
if(!nestedState.errorStack.empty()) {
state.errorStack.splice(state.errorStack.end(), nestedState.errorStack);
state.errorStack.emplace_back("[oatpp::json::Serializer::serializeMap()]: key='" + pair.first + "'");
return;
}
}
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
auto anyHandle = static_cast<data::mapping::type::AnyHandle*>(polymorph.get());
serializer->serialize(stream, oatpp::Void(anyHandle->ptr, anyHandle->type));
state.stream->writeCharSimple('}');
}
void Serializer::serializeEnum(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::PolymorphicDispatcher*>(
polymorph.getValueType()->polymorphicDispatcher
);
void Serializer::serializePairs(MappingState& state) {
data::mapping::type::EnumInterpreterError e = data::mapping::type::EnumInterpreterError::OK;
serializer->serialize(stream, polymorphicDispatcher->toInterpretation(polymorph, e));
state.stream->writeCharSimple('{');
MappingState nestedState;
nestedState.stream = state.stream;
nestedState.config = state.config;
auto& map = state.tree->getPairs();
auto mapSize = map.size();
for(v_uint64 index = 0; index < mapSize; index ++) {
const auto& pair = map[index];
nestedState.tree = &pair.second;
if(!nestedState.tree->isNull() || state.config->includeNullElements) {
if(index > 0) state.stream->writeSimple(",", 1);
const auto& str = pair.first;
serializeString(state.stream, str->data(), static_cast<v_buff_size>(str->size()), state.config->escapeFlags);
state.stream->writeCharSimple(':');
serialize(nestedState);
if(!nestedState.errorStack.empty()) {
state.errorStack.splice(state.errorStack.end(), nestedState.errorStack);
state.errorStack.emplace_back("[oatpp::json::Serializer::serializeMap()]: key='" + pair.first + "'");
return;
}
}
if(e == data::mapping::type::EnumInterpreterError::OK) {
return;
}
switch(e) {
case data::mapping::type::EnumInterpreterError::CONSTRAINT_NOT_NULL:
throw std::runtime_error("[oatpp::json::Serializer::serializeEnum()]: Error. Enum constraint violated - 'NotNull'.");
case data::mapping::type::EnumInterpreterError::OK:
case data::mapping::type::EnumInterpreterError::TYPE_MISMATCH_ENUM:
case data::mapping::type::EnumInterpreterError::TYPE_MISMATCH_ENUM_VALUE:
case data::mapping::type::EnumInterpreterError::ENTRY_NOT_FOUND:
state.stream->writeCharSimple('}');
}
void Serializer::serialize(MappingState& state) {
switch (state.tree->getType()) {
case data::mapping::Tree::Type::UNDEFINED: break;
case data::mapping::Tree::Type::NULL_VALUE: serializeNull(state); return;
case data::mapping::Tree::Type::INTEGER: state.stream->writeAsString(state.tree->getInteger()); return;
case data::mapping::Tree::Type::FLOAT: state.stream->writeAsString(state.tree->getFloat()); return;
case data::mapping::Tree::Type::BOOL: state.stream->writeAsString(state.tree->getValue<bool>()); return;
case data::mapping::Tree::Type::INT_8: state.stream->writeAsString(state.tree->getValue<v_int8>()); return;
case data::mapping::Tree::Type::UINT_8: state.stream->writeAsString(state.tree->getValue<v_uint8>()); return;
case data::mapping::Tree::Type::INT_16: state.stream->writeAsString(state.tree->getValue<v_int16>()); return;
case data::mapping::Tree::Type::UINT_16: state.stream->writeAsString(state.tree->getValue<v_uint16>()); return;
case data::mapping::Tree::Type::INT_32: state.stream->writeAsString(state.tree->getValue<v_int32>()); return;
case data::mapping::Tree::Type::UINT_32: state.stream->writeAsString(state.tree->getValue<v_uint32>()); return;
case data::mapping::Tree::Type::INT_64: state.stream->writeAsString(state.tree->getValue<v_int64>()); return;
case data::mapping::Tree::Type::UINT_64: state.stream->writeAsString(state.tree->getValue<v_uint64>()); return;
case data::mapping::Tree::Type::FLOAT_32: state.stream->writeAsString(state.tree->getValue<v_float32>()); return;
case data::mapping::Tree::Type::FLOAT_64: state.stream->writeAsString(state.tree->getValue<v_float64>()); return;
case data::mapping::Tree::Type::STRING: serializeString(state); return;
case data::mapping::Tree::Type::VECTOR: serializeArray(state); return;
case data::mapping::Tree::Type::MAP: serializeMap(state); return;
case data::mapping::Tree::Type::PAIRS: serializePairs(state); return;
default:
throw std::runtime_error("[oatpp::json::Serializer::serializeEnum()]: Error. Can't serialize Enum.");
break;
}
state.errorStack.emplace_back("[oatpp::json::Serializer::serialize()]: Unknown node type");
}
void Serializer::serializeCollection(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
void Serializer::serializeToStream(data::stream::ConsistentOutputStream* stream, MappingState& state) {
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
if(state.config->useBeautifier) {
auto dispatcher = static_cast<const data::mapping::type::__class::Collection::PolymorphicDispatcher*>(
polymorph.getValueType()->polymorphicDispatcher
);
stream->writeCharSimple('[');
bool first = true;
auto iterator = dispatcher->beginIteration(polymorph);
while (!iterator->finished()) {
const auto& value = iterator->get();
if(value || serializer->getConfig()->includeNullFields || serializer->getConfig()->alwaysIncludeNullCollectionElements) {
(first) ? first = false : stream->writeSimple(",", 1);
serializer->serialize(stream, value);
}
iterator->next();
}
stream->writeCharSimple(']');
}
void Serializer::serializeMap(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
auto dispatcher = static_cast<const data::mapping::type::__class::Map::PolymorphicDispatcher*>(
polymorph.getValueType()->polymorphicDispatcher
);
auto keyType = dispatcher->getKeyType();
if(keyType->classId != oatpp::String::Class::CLASS_ID){
throw std::runtime_error("[oatpp::json::Serializer::serializeMap()]: Invalid json map key. Key should be String");
}
stream->writeCharSimple('{');
bool first = true;
auto iterator = dispatcher->beginIteration(polymorph);
while (!iterator->finished()) {
const auto& value = iterator->getValue();
if(value || serializer->m_config->includeNullFields || serializer->m_config->alwaysIncludeNullCollectionElements) {
(first) ? first = false : stream->writeSimple(",", 1);
const auto& untypedKey = iterator->getKey();
const auto& key = oatpp::String(std::static_pointer_cast<std::string>(untypedKey.getPtr()));
serializeString(stream, key->data(), static_cast<v_buff_size>(key->size()), serializer->m_config->escapeFlags);
stream->writeSimple(":", 1);
serializer->serialize(stream, value);
}
iterator->next();
}
stream->writeCharSimple('}');
}
void Serializer::serializeObject(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
stream->writeCharSimple('{');
bool first = true;
auto type = polymorph.getValueType();
auto dispatcher = static_cast<const oatpp::data::mapping::type::__class::AbstractObject::PolymorphicDispatcher*>(
type->polymorphicDispatcher
);
auto fields = dispatcher->getProperties()->getList();
auto object = static_cast<oatpp::BaseObject*>(polymorph.get());
auto config = serializer->m_config;
for (auto const& field : fields) {
oatpp::Void value;
if(field->info.typeSelector && field->type == oatpp::Any::Class::getType()) {
const auto& any = field->get(object).cast<oatpp::Any>();
value = any.retrieve(field->info.typeSelector->selectType(object));
} else {
value = field->get(object);
}
if(field->info.required && value == nullptr) {
throw std::runtime_error("[oatpp::json::Serializer::serialize()]: "
"Error. " + std::string(type->nameQualifier) + "::"
+ std::string(field->name) + " is required!");
}
if (value || config->includeNullFields || (field->info.required && config->alwaysIncludeRequired)) {
(first) ? first = false : stream->writeSimple(",", 1);
serializeString(stream, field->name, static_cast<v_buff_size>(std::strlen(field->name)), serializer->m_config->escapeFlags);
stream->writeSimple(":", 1);
serializer->serialize(stream, value);
}
}
stream->writeCharSimple('}');
}
void Serializer::serialize(data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
auto id = static_cast<v_uint32>(polymorph.getValueType()->classId.id);
auto& method = m_methods[id];
if(method) {
(*method)(this, stream, polymorph);
} else {
auto* interpretation = polymorph.getValueType()->findInterpretation(m_config->enabledInterpretations);
if(interpretation) {
serialize(stream, interpretation->toInterpretation(polymorph));
} else {
throw std::runtime_error("[oatpp::json::Serializer::serialize()]: "
"Error. No serialize method for type '" +
std::string(polymorph.getValueType()->classId.name) + "'");
}
}
}
void Serializer::serializeToStream(data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
if(m_config->useBeautifier) {
json::Beautifier beautifier(stream, " ", "\n");
serialize(&beautifier, polymorph);
} else {
serialize(stream, polymorph);
}
}
const std::shared_ptr<Serializer::Config>& Serializer::getConfig() {
return m_config;
MappingState beautifulState;
beautifulState.stream = &beautifier;
beautifulState.tree = state.tree;
beautifulState.config = state.config;
serialize(beautifulState);
state.errorStack = std::move(beautifulState.errorStack);
} else {
state.stream = stream;
serialize(state);
}
}
}}

View File

@ -27,8 +27,8 @@
#include "./Utils.hpp"
#include "./Beautifier.hpp"
#include "oatpp/data/mapping/Tree.hpp"
#include "oatpp/Types.hpp"
#include <vector>
namespace oatpp { namespace json {
@ -38,55 +38,18 @@ namespace oatpp { namespace json {
*/
class Serializer {
public:
typedef oatpp::data::mapping::type::Type Type;
typedef oatpp::data::mapping::type::BaseObject::Property Property;
typedef oatpp::data::mapping::type::BaseObject::Properties Properties;
typedef oatpp::String String;
public:
/**
* 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.
* Field will still be included when field-info `required` is set to true and &id:alwaysIncludeRequired is set to true.
*/
bool includeNullFields = true;
/**
* Always include required fields (set in in DTO_FIELD_INFO) even if they are `value == nullptr`
*/
bool alwaysIncludeRequired = false;
/**
* Always include array or map elements, even if their value is `nullptr`.
*/
bool alwaysIncludeNullCollectionElements = false;
/**
* 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;
bool includeNullElements = true;
/**
* Use JSON Beautifier.
@ -103,97 +66,45 @@ public:
*/
oatpp::String beautifierNewLine = "\n";
/**
* Enable type interpretations.
*/
std::vector<std::string> enabledInterpretations = {};
/**
* Escape flags.
*/
v_uint32 escapeFlags = json::Utils::FLAG_ESCAPE_ALL;
};
public:
typedef void (*SerializerMethod)(Serializer*,
data::stream::ConsistentOutputStream*,
const oatpp::Void&);
struct MappingState {
Config* config;
const data::mapping::Tree* tree;
data::stream::ConsistentOutputStream* stream;
std::list<oatpp::String> errorStack;
oatpp::String errorStacktrace() const;
};
private:
template<class T>
static void serializePrimitive(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph){
(void) serializer;
if(polymorph){
stream->writeAsString(* static_cast<typename T::ObjectType*>(polymorph.get()));
} else {
stream->writeSimple("null", 4);
}
}
static void serializeString(oatpp::data::stream::ConsistentOutputStream* stream,
const char* data,
v_buff_size size,
v_uint32 escapeFlags);
static void serializeString(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);
static void serializeNull(MappingState& state);
static void serializeString(MappingState& state);
static void serializeArray(MappingState& state);
static void serializeMap(MappingState& state);
static void serializePairs(MappingState& state);
static void serializeAny(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);
static void serialize(MappingState& state);
static void serializeEnum(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);
static void serializeCollection(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);
static void serializeMap(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);
static void serializeObject(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);
void serialize(data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph);
private:
std::shared_ptr<Config> m_config;
std::vector<SerializerMethod> m_methods;
public:
/**
* Constructor.
* @param config - serializer config.
*/
Serializer(const std::shared_ptr<Config>& config = std::make_shared<Config>());
/**
* Set serializer method for type.
* @param classId - &id:oatpp::data::mapping::type::ClassId;.
* @param method - `typedef void (*SerializerMethod)(Serializer*, data::stream::ConsistentOutputStream*, const oatpp::Void&)`.
*/
void setSerializerMethod(const data::mapping::type::ClassId& classId, SerializerMethod method);
/**
* Serialize object to stream.
* @param stream - &id:oatpp::data::stream::ConsistentOutputStream;.
* @param polymorph - DTO as &id:oatpp::Void;.
*/
void serializeToStream(data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph);
/**
* Get serializer config.
* @return
*/
const std::shared_ptr<Config>& getConfig();
static void serializeToStream(data::stream::ConsistentOutputStream* stream, MappingState& state);
};

View File

@ -69,8 +69,8 @@ class TestDto1 : public oatpp::DTO {
void TreeToObjectMapperTest::onRun() {
json::ObjectMapper jsonMapper;
jsonMapper.getSerializer()->getConfig()->useBeautifier = true;
jsonMapper.getSerializer()->getConfig()->includeNullFields = false;
jsonMapper.getSerializerConfig()->useBeautifier = true;
jsonMapper.getSerializerConfig()->includeNullFields = false;
TreeToObjectMapper mapper;
TreeToObjectMapper::Config config;

View File

@ -176,7 +176,7 @@ void InterpretationTest::onRun() {
oatpp::json::ObjectMapper mapper;
{
auto config = mapper.getSerializer()->getConfig();
auto config = mapper.getSerializerConfig();
config->enabledInterpretations = {"test"};
config->useBeautifier = false;
}

View File

@ -165,7 +165,7 @@ class TestAnyNested : public oatpp::DTO {
void DTOMapperTest::onRun(){
auto mapper = oatpp::json::ObjectMapper::createShared();
mapper->getSerializer()->getConfig()->useBeautifier = true;
mapper->getSerializerConfig()->useBeautifier = true;
{
auto test1 = Test::createShared();