mirror of
https://gitee.com/zyjblog/oatpp.git
synced 2024-12-22 22:16:37 +08:00
mapping::type: Better containers hierarchy
This commit is contained in:
parent
11e80b8a4a
commit
512769c5ce
@ -82,10 +82,12 @@ add_library(oatpp
|
||||
oatpp/core/data/mapping/TypeResolver.hpp
|
||||
oatpp/core/data/mapping/type/Any.cpp
|
||||
oatpp/core/data/mapping/type/Any.hpp
|
||||
oatpp/core/data/mapping/type/Collection.hpp
|
||||
oatpp/core/data/mapping/type/Enum.cpp
|
||||
oatpp/core/data/mapping/type/Enum.hpp
|
||||
oatpp/core/data/mapping/type/List.cpp
|
||||
oatpp/core/data/mapping/type/List.hpp
|
||||
oatpp/core/data/mapping/type/Map.hpp
|
||||
oatpp/core/data/mapping/type/PairList.cpp
|
||||
oatpp/core/data/mapping/type/PairList.hpp
|
||||
oatpp/core/data/mapping/type/Object.cpp
|
||||
|
@ -187,7 +187,7 @@ namespace oatpp {
|
||||
/**
|
||||
* Abstract Fields
|
||||
*/
|
||||
typedef data::mapping::type::PairListObjectWrapper<oatpp::String, oatpp::Void, data::mapping::type::__class::AbstractPairList> AbstractFields;
|
||||
typedef Fields<oatpp::Void> AbstractFields;
|
||||
|
||||
/**
|
||||
* Mapping-Enabled UnorderedMap<Key, Value>. &id:oatpp::data::mapping::type::UnorderedMap;.
|
||||
@ -204,7 +204,7 @@ namespace oatpp {
|
||||
/**
|
||||
* Abstract UnorderedFields
|
||||
*/
|
||||
typedef data::mapping::type::UnorderedMapObjectWrapper<oatpp::String, oatpp::Void, data::mapping::type::__class::AbstractUnorderedMap> AbstractUnorderedFields;
|
||||
typedef UnorderedFields<oatpp::Void> AbstractUnorderedFields;
|
||||
|
||||
}
|
||||
|
||||
|
@ -68,13 +68,13 @@ public:
|
||||
"Error. Data not found for key '" + *key + "'.");
|
||||
}
|
||||
|
||||
if(it->second.getValueType() != WrapperType::Class::getType()) {
|
||||
if(!WrapperType::Class::getType()->extends(it->second.getValueType())) {
|
||||
throw std::runtime_error("[oatpp::data::Bundle::get()]: Error. Type mismatch for key '" + *key +
|
||||
"'. Stored '" +
|
||||
std::string(it->second.getValueType()->classId.name) +
|
||||
"' vs requested '" + std::string(WrapperType::Class::getType()->classId.name) + "'.");
|
||||
}
|
||||
return it->second.template staticCast<WrapperType>();
|
||||
return it->second.template cast<WrapperType>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,7 +110,7 @@ public:
|
||||
template<class Wrapper>
|
||||
Wrapper readFromCaret(oatpp::parser::Caret& caret) const {
|
||||
auto type = Wrapper::Class::getType();
|
||||
return read(caret, type).template staticCast<Wrapper>();
|
||||
return read(caret, type).template cast<Wrapper>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,7 +125,7 @@ public:
|
||||
Wrapper readFromString(const oatpp::String& str) const {
|
||||
auto type = Wrapper::Class::getType();
|
||||
oatpp::parser::Caret caret(str);
|
||||
auto result = read(caret, type).template staticCast<Wrapper>();
|
||||
auto result = read(caret, type).template cast<Wrapper>();
|
||||
if(!result) {
|
||||
throw oatpp::parser::ParsingError(caret.getErrorMessage(), caret.getErrorCode(), caret.getPosition());
|
||||
}
|
||||
|
189
src/oatpp/core/data/mapping/type/Collection.hpp
Normal file
189
src/oatpp/core/data/mapping/type/Collection.hpp
Normal file
@ -0,0 +1,189 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 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_data_mapping_type_Collection_hpp
|
||||
#define oatpp_data_mapping_type_Collection_hpp
|
||||
|
||||
#include "./Type.hpp"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace oatpp { namespace data { namespace mapping { namespace type {
|
||||
|
||||
namespace __class {
|
||||
|
||||
/**
|
||||
* Abstract Collection. <br>
|
||||
* Ex.: Vector, List, Set.
|
||||
*/
|
||||
class Collection {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Iterator.
|
||||
*/
|
||||
struct Iterator {
|
||||
|
||||
/**
|
||||
* Default virtual destructor.
|
||||
*/
|
||||
virtual ~Iterator() = default;
|
||||
|
||||
/**
|
||||
* Get current item.
|
||||
* @return
|
||||
*/
|
||||
virtual type::Void get() = 0;
|
||||
|
||||
/**
|
||||
* Iterate to next item.
|
||||
*/
|
||||
virtual void next() = 0;
|
||||
|
||||
/**
|
||||
* Check if iterator finished.
|
||||
* @return
|
||||
*/
|
||||
virtual bool finished() = 0;
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Polymorphic Dispatcher
|
||||
*/
|
||||
class PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Virtual destructor.
|
||||
*/
|
||||
virtual ~PolymorphicDispatcher() = default;
|
||||
|
||||
/**
|
||||
* Create Collection.
|
||||
* @return
|
||||
*/
|
||||
virtual type::Void createObject() const = 0;
|
||||
|
||||
/**
|
||||
* Get type of collection items.
|
||||
* @return
|
||||
*/
|
||||
virtual const type::Type* getItemType() const = 0;
|
||||
|
||||
/**
|
||||
* Add item.
|
||||
* @param object - Collection.
|
||||
* @param item - Item to add.
|
||||
*/
|
||||
virtual void addItem(const type::Void& object, const type::Void& item) const = 0;
|
||||
|
||||
/**
|
||||
* Begin collection iteration.
|
||||
* @param object - Collection.
|
||||
* @return
|
||||
*/
|
||||
virtual std::unique_ptr<Iterator> beginIteration(const type::Void& object) const = 0;
|
||||
|
||||
};
|
||||
|
||||
template<class ContainerType, class ItemType>
|
||||
struct Inserter {
|
||||
|
||||
static void insert(ContainerType* c, const ItemType& i) {
|
||||
c->emplace_back(i);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<class ContainerType, class ItemType, class Clazz>
|
||||
class StandardCollection {
|
||||
public:
|
||||
|
||||
struct Iterator : public Collection::Iterator {
|
||||
|
||||
typename ContainerType::iterator iterator;
|
||||
typename ContainerType::iterator end;
|
||||
|
||||
type::Void get() override {
|
||||
return *iterator;
|
||||
}
|
||||
|
||||
void next() override {
|
||||
std::advance(iterator, 1);
|
||||
}
|
||||
|
||||
bool finished() override {
|
||||
return iterator == end;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
class PolymorphicDispatcher : public Collection::PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
type::Void createObject() const override {
|
||||
return type::Void(std::make_shared<ContainerType>(), Clazz::getType());
|
||||
}
|
||||
|
||||
const type::Type* getItemType() const override {
|
||||
const type::Type* collectionType = Clazz::getType();
|
||||
return collectionType->params[0];
|
||||
}
|
||||
|
||||
void addItem(const type::Void& object, const type::Void& item) const override {
|
||||
ContainerType* collection = static_cast<ContainerType*>(object.get());
|
||||
const auto& collectionItem = item.template cast<ItemType>();
|
||||
Collection::Inserter<ContainerType, ItemType>::insert(collection, collectionItem);
|
||||
}
|
||||
|
||||
std::unique_ptr<Collection::Iterator> beginIteration(const type::Void& object) const override {
|
||||
ContainerType* collection = static_cast<ContainerType*>(object.get());
|
||||
auto iterator = new Iterator();
|
||||
iterator->iterator = collection->begin();
|
||||
iterator->end = collection->end();
|
||||
return std::unique_ptr<Collection::Iterator>(iterator);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<class ItemType>
|
||||
struct Collection::Inserter<std::unordered_set<ItemType>, ItemType> {
|
||||
static void insert(std::unordered_set<ItemType>* c, const ItemType& i) {
|
||||
c->template emplace(i);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
#endif //oatpp_data_mapping_type_Collection_hpp
|
@ -472,7 +472,7 @@ Void EnumInterpreterAsString<T, notnull>::toInterpretation(const Void& enumValue
|
||||
return Void(nullptr, String::Class::getType());
|
||||
}
|
||||
|
||||
const auto& ow = enumValue.staticCast<EnumOW>();
|
||||
const auto& ow = enumValue.template cast<EnumOW>();
|
||||
const auto& entry = EnumOW::getEntryByValue(*ow);
|
||||
return entry.name.toString();
|
||||
}
|
||||
@ -495,7 +495,7 @@ Void EnumInterpreterAsString<T, notnull>::fromInterpretation(const Void& interVa
|
||||
}
|
||||
|
||||
try {
|
||||
const auto &entry = EnumOW::getEntryByName(interValue.staticCast<String>());
|
||||
const auto &entry = EnumOW::getEntryByName(interValue.template cast<String>());
|
||||
return EnumOW(entry.value);
|
||||
} catch (const std::runtime_error&) { // TODO - add a specific error for this.
|
||||
error = EnumInterpreterError::ENTRY_NOT_FOUND;
|
||||
@ -528,7 +528,7 @@ Void EnumInterpreterAsNumber<T, notnull>::toInterpretation(const Void& enumValue
|
||||
return Void(nullptr, UTOW::Class::getType());
|
||||
}
|
||||
|
||||
const auto& ow = enumValue.staticCast<EnumOW>();
|
||||
const auto& ow = enumValue.template cast<EnumOW>();
|
||||
return UTOW(static_cast<EnumUT>(*ow));
|
||||
|
||||
}
|
||||
@ -555,7 +555,7 @@ Void EnumInterpreterAsNumber<T, notnull>::fromInterpretation(const Void& interVa
|
||||
|
||||
try{
|
||||
const auto& entry = EnumOW::getEntryByUnderlyingValue(
|
||||
interValue.staticCast<OW>()
|
||||
interValue.template cast<OW>()
|
||||
);
|
||||
return EnumOW(entry.value);
|
||||
} catch (const std::runtime_error&) { // TODO - add a specific error for this.
|
||||
|
@ -25,6 +25,7 @@
|
||||
#ifndef oatpp_data_mapping_type_List_hpp
|
||||
#define oatpp_data_mapping_type_List_hpp
|
||||
|
||||
#include "./Collection.hpp"
|
||||
#include "./Type.hpp"
|
||||
|
||||
#include <list>
|
||||
@ -39,29 +40,11 @@ namespace __class {
|
||||
*/
|
||||
class AbstractList {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Class Id.
|
||||
*/
|
||||
static const ClassId CLASS_ID;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Polymorphic Dispatcher
|
||||
*/
|
||||
class PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
virtual ~PolymorphicDispatcher() = default;
|
||||
|
||||
virtual type::Void createObject() const = 0;
|
||||
|
||||
/**
|
||||
* Add item.
|
||||
* @param object - List to add item to.
|
||||
* @param item - Item to add.
|
||||
*/
|
||||
virtual void addPolymorphicItem(const type::Void& object, const type::Void& item) const = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@ -115,35 +98,19 @@ public:
|
||||
template<class T>
|
||||
using List = ListObjectWrapper<T, __class::List<T>>;
|
||||
|
||||
typedef ListObjectWrapper<type::Void, __class::AbstractList> AbstractList;
|
||||
typedef List<Void> AbstractList;
|
||||
|
||||
namespace __class {
|
||||
|
||||
template<class T>
|
||||
class List : public AbstractList {
|
||||
public:
|
||||
|
||||
class PolymorphicDispatcher : public AbstractList::PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
type::Void createObject() const override {
|
||||
return type::Void(std::make_shared<std::list<T>>(), getType());
|
||||
}
|
||||
|
||||
void addPolymorphicItem(const type::Void& object, const type::Void& item) const override {
|
||||
const auto& list = object.staticCast<type::List<T>>();
|
||||
const auto& listItem = item.staticCast<T>();
|
||||
list->push_back(listItem);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static Type createType() {
|
||||
Type::Info info;
|
||||
info.params.push_back(T::Class::getType());
|
||||
info.polymorphicDispatcher = new PolymorphicDispatcher();
|
||||
info.polymorphicDispatcher = new typename StandardCollection<std::list<T>, T, List>::PolymorphicDispatcher();
|
||||
info.isCollection = true;
|
||||
return Type(__class::AbstractList::CLASS_ID, info);
|
||||
}
|
||||
|
||||
|
212
src/oatpp/core/data/mapping/type/Map.hpp
Normal file
212
src/oatpp/core/data/mapping/type/Map.hpp
Normal file
@ -0,0 +1,212 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 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_data_mapping_type_Map_hpp
|
||||
#define oatpp_data_mapping_type_Map_hpp
|
||||
|
||||
#include "./Type.hpp"
|
||||
#include <list>
|
||||
|
||||
namespace oatpp { namespace data { namespace mapping { namespace type {
|
||||
|
||||
namespace __class {
|
||||
|
||||
/**
|
||||
* Abstract Map. <br>
|
||||
* Ex.: UnorderedMap, Fields.
|
||||
*/
|
||||
class Map {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Iterator.
|
||||
*/
|
||||
struct Iterator {
|
||||
|
||||
/**
|
||||
* Default virtual destructor.
|
||||
*/
|
||||
virtual ~Iterator() = default;
|
||||
|
||||
/**
|
||||
* Get current item key.
|
||||
* @return
|
||||
*/
|
||||
virtual type::Void getKey() = 0;
|
||||
|
||||
/**
|
||||
* Get current item value.
|
||||
* @return
|
||||
*/
|
||||
virtual type::Void getValue() = 0;
|
||||
|
||||
/**
|
||||
* Iterate to next item.
|
||||
*/
|
||||
virtual void next() = 0;
|
||||
|
||||
/**
|
||||
* Check if iterator finished.
|
||||
* @return
|
||||
*/
|
||||
virtual bool finished() = 0;
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Polymorphic Dispatcher
|
||||
*/
|
||||
class PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Virtual destructor.
|
||||
*/
|
||||
virtual ~PolymorphicDispatcher() = default;
|
||||
|
||||
/**
|
||||
* Create Map.
|
||||
* @return
|
||||
*/
|
||||
virtual type::Void createObject() const = 0;
|
||||
|
||||
/**
|
||||
* Get type of map keys.
|
||||
* @return
|
||||
*/
|
||||
virtual const type::Type* getKeyType() const = 0;
|
||||
|
||||
/**
|
||||
* Get type of map values.
|
||||
* @return
|
||||
*/
|
||||
virtual const type::Type* getValueType() const = 0;
|
||||
|
||||
/**
|
||||
* Add item.
|
||||
* @param object - Map.
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
virtual void addItem(const type::Void& object, const type::Void& key, const type::Void& value) const = 0;
|
||||
|
||||
/**
|
||||
* Begin map iteration.
|
||||
* @param object - Map.
|
||||
* @return
|
||||
*/
|
||||
virtual std::unique_ptr<Iterator> beginIteration(const type::Void& object) const = 0;
|
||||
|
||||
};
|
||||
|
||||
template<class ContainerType, class KeyType, class ValueType>
|
||||
struct Inserter {
|
||||
|
||||
static void insert(ContainerType* c, const KeyType& k, const ValueType& v) {
|
||||
(*c)[k] = v;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<class ContainerType, class KeyType, class ValueType, class Clazz>
|
||||
class StandardMap {
|
||||
public:
|
||||
|
||||
struct Iterator : public Map::Iterator {
|
||||
|
||||
typename ContainerType::iterator iterator;
|
||||
typename ContainerType::iterator end;
|
||||
|
||||
type::Void getKey() override {
|
||||
return iterator->first;
|
||||
}
|
||||
|
||||
type::Void getValue() override {
|
||||
return iterator->second;
|
||||
}
|
||||
|
||||
void next() override {
|
||||
std::advance(iterator, 1);
|
||||
}
|
||||
|
||||
bool finished() override {
|
||||
return iterator == end;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
class PolymorphicDispatcher : public Map::PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
type::Void createObject() const override {
|
||||
return type::Void(std::make_shared<ContainerType>(), Clazz::getType());
|
||||
}
|
||||
|
||||
const type::Type* getKeyType() const override {
|
||||
const type::Type* mapType = Clazz::getType();
|
||||
return mapType->params[0];
|
||||
}
|
||||
|
||||
const type::Type* getValueType() const override {
|
||||
const type::Type* mapType = Clazz::getType();
|
||||
return mapType->params[1];
|
||||
}
|
||||
|
||||
void addItem(const type::Void& object, const type::Void& key, const type::Void& value) const override {
|
||||
ContainerType* map = static_cast<ContainerType*>(object.get());
|
||||
const auto& mapKey = key.template cast<KeyType>();
|
||||
const auto& mapValue = value.template cast<ValueType>();
|
||||
Map::Inserter<ContainerType, KeyType, ValueType>::insert(map, mapKey, mapValue);
|
||||
}
|
||||
|
||||
std::unique_ptr<Map::Iterator> beginIteration(const type::Void& object) const override {
|
||||
ContainerType* map = static_cast<ContainerType*>(object.get());
|
||||
auto iterator = new Iterator();
|
||||
iterator->iterator = map->begin();
|
||||
iterator->end = map->end();
|
||||
return std::unique_ptr<Map::Iterator>(iterator);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<class KeyType, class ValueType>
|
||||
struct Map::Inserter<std::list<std::pair<KeyType, ValueType>>, KeyType, ValueType> {
|
||||
static void insert(std::list<std::pair<KeyType, ValueType>>* c, const KeyType& k, const ValueType& v) {
|
||||
c->push_back({k, v});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
#endif //oatpp_data_mapping_type_Map_hpp
|
@ -25,6 +25,7 @@
|
||||
#ifndef oatpp_data_mapping_type_PairList_hpp
|
||||
#define oatpp_data_mapping_type_PairList_hpp
|
||||
|
||||
#include "./Map.hpp"
|
||||
#include "./Type.hpp"
|
||||
|
||||
#include <list>
|
||||
@ -44,27 +45,6 @@ namespace __class {
|
||||
* Class id.
|
||||
*/
|
||||
static const ClassId CLASS_ID;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Polymorphic Dispatcher.
|
||||
*/
|
||||
class PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
virtual ~PolymorphicDispatcher() = default;
|
||||
|
||||
virtual type::Void createObject() const = 0;
|
||||
|
||||
/**
|
||||
* Add key-value pair to pair-list.
|
||||
* @param object - pair list.
|
||||
* @param key - key.
|
||||
* @param value - value.
|
||||
*/
|
||||
virtual void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<class Key, class Value>
|
||||
@ -147,31 +127,15 @@ namespace __class {
|
||||
|
||||
template<class Key, class Value>
|
||||
class PairList : public AbstractPairList {
|
||||
public:
|
||||
|
||||
class PolymorphicDispatcher : public AbstractPairList::PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
type::Void createObject() const override {
|
||||
return type::Void(std::make_shared<std::list<std::pair<Key, Value>>>(), getType());
|
||||
}
|
||||
|
||||
void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const override {
|
||||
const auto& map = object.staticCast<type::PairList<Key, Value>>();
|
||||
const auto& k = key.staticCast<Key>();
|
||||
const auto& v = value.staticCast<Value>();
|
||||
map->push_back({k, v});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static Type createType() {
|
||||
Type::Info info;
|
||||
info.params.push_back(Key::Class::getType());
|
||||
info.params.push_back(Value::Class::getType());
|
||||
info.polymorphicDispatcher = new PolymorphicDispatcher();
|
||||
info.polymorphicDispatcher = info.polymorphicDispatcher =
|
||||
new typename __class::StandardMap<std::list<std::pair<Key, Value>>, Key, Value, PairList>::PolymorphicDispatcher();
|
||||
info.isMap = true;
|
||||
return Type(__class::AbstractPairList::CLASS_ID, info);
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,8 @@ Type::Type(const ClassId& pClassId, const Info& typeInfo)
|
||||
, polymorphicDispatcher(typeInfo.polymorphicDispatcher)
|
||||
, interpretationMap(typeInfo.interpretationMap)
|
||||
, parent(typeInfo.parent)
|
||||
, isCollection(typeInfo.isCollection)
|
||||
, isMap(typeInfo.isMap)
|
||||
{}
|
||||
|
||||
const Type::AbstractInterpretation* Type::findInterpretation(const std::vector<std::string>& names) const {
|
||||
|
@ -217,9 +217,7 @@ public:
|
||||
}
|
||||
|
||||
template<class Wrapper>
|
||||
Wrapper staticCast() const {
|
||||
return Wrapper(std::static_pointer_cast<typename Wrapper::ObjectType>(m_ptr), m_valueType);
|
||||
}
|
||||
Wrapper cast() const;
|
||||
|
||||
inline T* operator->() const {
|
||||
return m_ptr.operator->();
|
||||
@ -413,11 +411,11 @@ public:
|
||||
public:
|
||||
|
||||
Void toInterpretation(const Void& originalValue) const override {
|
||||
return interpret(originalValue.staticCast<OriginalWrapper>());
|
||||
return interpret(originalValue.template cast<OriginalWrapper>());
|
||||
}
|
||||
|
||||
Void fromInterpretation(const Void& interValue) const override {
|
||||
return reproduce(interValue.staticCast<InterWrapper>());
|
||||
return reproduce(interValue.template cast<InterWrapper>());
|
||||
}
|
||||
|
||||
const Type* getInterpretationType() const override {
|
||||
@ -472,6 +470,16 @@ public:
|
||||
* statically casted to parent type without any violations.
|
||||
*/
|
||||
const Type* parent = nullptr;
|
||||
|
||||
/**
|
||||
* polymorphicDispatcher extends &id:oatpp::data::mapping::type::__class::Collection::PolymorphicDispatcher;.
|
||||
*/
|
||||
bool isCollection = false;
|
||||
|
||||
/**
|
||||
* polymorphicDispatcher extends &id:oatpp::data::mapping::type::__class::Map::PolymorphicDispatcher;.
|
||||
*/
|
||||
bool isMap = false;
|
||||
};
|
||||
|
||||
public:
|
||||
@ -516,6 +524,16 @@ public:
|
||||
*/
|
||||
const Type* const parent;
|
||||
|
||||
/**
|
||||
* polymorphicDispatcher extends &id:oatpp::data::mapping::type::__class::Collection::PolymorphicDispatcher;.
|
||||
*/
|
||||
const bool isCollection;
|
||||
|
||||
/**
|
||||
* polymorphicDispatcher extends &id:oatpp::data::mapping::type::__class::Map::PolymorphicDispatcher;.
|
||||
*/
|
||||
const bool isMap;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -535,6 +553,19 @@ public:
|
||||
|
||||
};
|
||||
|
||||
template <class T, class Clazz>
|
||||
template<class Wrapper>
|
||||
Wrapper ObjectWrapper<T, Clazz>::cast() const {
|
||||
if(!Wrapper::Class::getType()->extends(m_valueType)) {
|
||||
if(Wrapper::Class::getType() != __class::Void::getType() && m_valueType != __class::Void::getType()) {
|
||||
throw std::runtime_error("[oatpp::data::mapping::type::ObjectWrapper::cast()]: Error. Invalid cast "
|
||||
"from '" + std::string(m_valueType->classId.name) + "' to '" +
|
||||
std::string(Wrapper::Class::getType()->classId.name) + "'.");
|
||||
}
|
||||
}
|
||||
return Wrapper(std::static_pointer_cast<typename Wrapper::ObjectType>(m_ptr), Wrapper::Class::getType());
|
||||
}
|
||||
|
||||
template <class T, class Clazz>
|
||||
void ObjectWrapper<T, Clazz>::checkType(const Type* _this, const Type* other) {
|
||||
if(!_this->extends(other)) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#ifndef oatpp_data_mapping_type_UnorderedMap_hpp
|
||||
#define oatpp_data_mapping_type_UnorderedMap_hpp
|
||||
|
||||
#include "./Map.hpp"
|
||||
#include "./Type.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
@ -44,27 +45,6 @@ namespace __class {
|
||||
* Class Id.
|
||||
*/
|
||||
static const ClassId CLASS_ID;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Polymorphic Dispatcher.
|
||||
*/
|
||||
class PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
virtual ~PolymorphicDispatcher() = default;
|
||||
|
||||
virtual type::Void createObject() const = 0;
|
||||
|
||||
/**
|
||||
* Add item.
|
||||
* @param object - Unordered Map.
|
||||
* @param key - Key.
|
||||
* @param value - Value.
|
||||
*/
|
||||
virtual void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<class Key, class Value>
|
||||
@ -120,31 +100,15 @@ namespace __class {
|
||||
|
||||
template<class Key, class Value>
|
||||
class UnorderedMap : public AbstractUnorderedMap {
|
||||
public:
|
||||
|
||||
class PolymorphicDispatcher : public AbstractUnorderedMap::PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
type::Void createObject() const override {
|
||||
return type::Void(std::make_shared<std::unordered_map<Key, Value>>(), getType());
|
||||
}
|
||||
|
||||
void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const override {
|
||||
const auto& map = object.staticCast<type::UnorderedMap<Key, Value>>();
|
||||
const auto& k = key.staticCast<Key>();
|
||||
const auto& v = value.staticCast<Value>();
|
||||
map[k] = v;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static Type createType() {
|
||||
Type::Info info;
|
||||
info.params.push_back(Key::Class::getType());
|
||||
info.params.push_back(Value::Class::getType());
|
||||
info.polymorphicDispatcher = new PolymorphicDispatcher();
|
||||
info.polymorphicDispatcher =
|
||||
new typename __class::StandardMap<std::unordered_map<Key, Value>, Key, Value, UnorderedMap>::PolymorphicDispatcher();
|
||||
info.isMap = true;
|
||||
return Type(__class::AbstractUnorderedMap::CLASS_ID, info);
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#ifndef oatpp_data_mapping_type_UnorderedSet_hpp
|
||||
#define oatpp_data_mapping_type_UnorderedSet_hpp
|
||||
|
||||
#include "./Collection.hpp"
|
||||
#include "./Type.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
@ -43,26 +44,6 @@ namespace __class {
|
||||
* Class Id.
|
||||
*/
|
||||
static const ClassId CLASS_ID;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Polymorphic Dispatcher.
|
||||
*/
|
||||
class PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
virtual ~PolymorphicDispatcher() = default;
|
||||
|
||||
virtual type::Void createObject() const = 0;
|
||||
|
||||
/**
|
||||
* Add Item.
|
||||
* @param object - UnorderedSet.
|
||||
* @param item - Item.
|
||||
*/
|
||||
virtual void addPolymorphicItem(const type::Void& object, const type::Void& item) const = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<class T>
|
||||
@ -117,35 +98,19 @@ public:
|
||||
template<class T>
|
||||
using UnorderedSet = UnorderedSetObjectWrapper<T, __class::UnorderedSet<T>>;
|
||||
|
||||
typedef UnorderedSetObjectWrapper<type::Void, __class::AbstractUnorderedSet> AbstractUnorderedSet;
|
||||
typedef UnorderedSet<Void> AbstractUnorderedSet;
|
||||
|
||||
namespace __class {
|
||||
|
||||
template<class T>
|
||||
class UnorderedSet : public AbstractUnorderedSet {
|
||||
public:
|
||||
|
||||
class PolymorphicDispatcher : public AbstractUnorderedSet::PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
type::Void createObject() const override {
|
||||
return type::Void(std::make_shared<std::unordered_set<T>>(), getType());
|
||||
}
|
||||
|
||||
void addPolymorphicItem(const type::Void& object, const type::Void& item) const override {
|
||||
const auto& set = object.staticCast<type::UnorderedSet<T>>();
|
||||
const auto& setItem = item.staticCast<T>();
|
||||
set->insert(setItem);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static Type createType() {
|
||||
Type::Info info;
|
||||
info.params.push_back(T::Class::getType());
|
||||
info.polymorphicDispatcher = new PolymorphicDispatcher();
|
||||
info.polymorphicDispatcher = new typename StandardCollection<std::unordered_set<T>, T, UnorderedSet>::PolymorphicDispatcher();
|
||||
info.isCollection = true;
|
||||
return Type(__class::AbstractUnorderedSet::CLASS_ID, info);
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#ifndef oatpp_data_mapping_type_Vector_hpp
|
||||
#define oatpp_data_mapping_type_Vector_hpp
|
||||
|
||||
#include "./Collection.hpp"
|
||||
#include "./Type.hpp"
|
||||
|
||||
#include <vector>
|
||||
@ -43,26 +44,6 @@ namespace __class {
|
||||
* Class Id.
|
||||
*/
|
||||
static const ClassId CLASS_ID;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Polymorphic Dispatcher.
|
||||
*/
|
||||
class PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
virtual ~PolymorphicDispatcher() = default;
|
||||
|
||||
virtual type::Void createObject() const = 0;
|
||||
|
||||
/**
|
||||
* Add Item.
|
||||
* @param object - Vector.
|
||||
* @param item - Item to add.
|
||||
*/
|
||||
virtual void addPolymorphicItem(const type::Void& object, const type::Void& item) const = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<class T>
|
||||
@ -113,35 +94,19 @@ public:
|
||||
template<class T>
|
||||
using Vector = VectorObjectWrapper<T, __class::Vector<T>>;
|
||||
|
||||
typedef VectorObjectWrapper<type::Void, __class::AbstractVector> AbstractVector;
|
||||
typedef Vector<Void> AbstractVector;
|
||||
|
||||
namespace __class {
|
||||
|
||||
template<class T>
|
||||
class Vector : public AbstractVector {
|
||||
public:
|
||||
|
||||
class PolymorphicDispatcher : public AbstractVector::PolymorphicDispatcher {
|
||||
public:
|
||||
|
||||
type::Void createObject() const override {
|
||||
return type::Void(std::make_shared<std::vector<T>>(), getType());
|
||||
}
|
||||
|
||||
void addPolymorphicItem(const type::Void& object, const type::Void& item) const override {
|
||||
const auto& vector = object.staticCast<type::Vector<T>>();
|
||||
const auto& vectorItem = item.staticCast<T>();
|
||||
vector->push_back(vectorItem);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static Type createType() {
|
||||
Type::Info info;
|
||||
info.params.push_back(T::Class::getType());
|
||||
info.polymorphicDispatcher = new PolymorphicDispatcher();
|
||||
info.polymorphicDispatcher = new typename StandardCollection<std::vector<T>, T, Vector>::PolymorphicDispatcher();
|
||||
info.isCollection = true;
|
||||
return Type(__class::AbstractVector::CLASS_ID, info);
|
||||
}
|
||||
|
||||
|
@ -56,12 +56,12 @@ Deserializer::Deserializer(const std::shared_ptr<Config>& config)
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractObject::CLASS_ID, &Deserializer::deserializeObject);
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Deserializer::deserializeEnum);
|
||||
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Deserializer::deserializeList<oatpp::AbstractVector>);
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Deserializer::deserializeList<oatpp::AbstractList>);
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Deserializer::deserializeList<oatpp::AbstractUnorderedSet>);
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Deserializer::deserializeCollection);
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Deserializer::deserializeCollection);
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Deserializer::deserializeCollection);
|
||||
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Deserializer::deserializeKeyValue<oatpp::AbstractFields>);
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Deserializer::deserializeKeyValue<oatpp::AbstractUnorderedFields>);
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Deserializer::deserializeMap);
|
||||
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Deserializer::deserializeMap);
|
||||
|
||||
}
|
||||
|
||||
@ -287,6 +287,115 @@ oatpp::Void Deserializer::deserializeEnum(Deserializer* deserializer, parser::Ca
|
||||
|
||||
}
|
||||
|
||||
oatpp::Void Deserializer::deserializeCollection(Deserializer* deserializer, parser::Caret& caret, const Type* type) {
|
||||
|
||||
if(caret.isAtText("null", true)){
|
||||
return oatpp::Void(type);
|
||||
}
|
||||
|
||||
if(caret.canContinueAtChar('[', 1)) {
|
||||
|
||||
auto dispatcher = static_cast<const data::mapping::type::__class::Collection::PolymorphicDispatcher*>(type->polymorphicDispatcher);
|
||||
auto collection = dispatcher->createObject();
|
||||
|
||||
auto itemType = dispatcher->getItemType();
|
||||
|
||||
caret.skipBlankChars();
|
||||
|
||||
while(!caret.isAtChar(']') && caret.canContinue()){
|
||||
|
||||
caret.skipBlankChars();
|
||||
auto item = deserializer->deserialize(caret, itemType);
|
||||
if(caret.hasError()){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
dispatcher->addItem(collection, item);
|
||||
caret.skipBlankChars();
|
||||
|
||||
caret.canContinueAtChar(',', 1);
|
||||
|
||||
}
|
||||
|
||||
if(!caret.canContinueAtChar(']', 1)){
|
||||
if(!caret.hasError()){
|
||||
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeCollection()]: Error. ']' - expected", ERROR_CODE_ARRAY_SCOPE_CLOSE);
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
return collection;
|
||||
|
||||
} else {
|
||||
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeCollection()]: Error. '[' - expected", ERROR_CODE_ARRAY_SCOPE_OPEN);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
oatpp::Void Deserializer::deserializeMap(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
|
||||
|
||||
if(caret.isAtText("null", true)){
|
||||
return oatpp::Void(type);
|
||||
}
|
||||
|
||||
if(caret.canContinueAtChar('{', 1)) {
|
||||
|
||||
auto dispatcher = static_cast<const data::mapping::type::__class::Map::PolymorphicDispatcher*>(type->polymorphicDispatcher);
|
||||
auto map = dispatcher->createObject();
|
||||
|
||||
auto keyType = dispatcher->getKeyType();
|
||||
if(keyType->classId != oatpp::String::Class::CLASS_ID){
|
||||
throw std::runtime_error("[oatpp::parser::json::mapping::Deserializer::deserializeMap()]: Invalid json map key. Key should be String");
|
||||
}
|
||||
auto valueType = dispatcher->getValueType();
|
||||
|
||||
caret.skipBlankChars();
|
||||
|
||||
while (!caret.isAtChar('}') && caret.canContinue()) {
|
||||
|
||||
caret.skipBlankChars();
|
||||
auto key = Utils::parseString(caret);
|
||||
if(caret.hasError()){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
caret.skipBlankChars();
|
||||
if(!caret.canContinueAtChar(':', 1)){
|
||||
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeMap()]: Error. ':' - expected", ERROR_CODE_OBJECT_SCOPE_COLON_MISSING);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
caret.skipBlankChars();
|
||||
|
||||
auto item = deserializer->deserialize(caret, valueType);
|
||||
if(caret.hasError()){
|
||||
return nullptr;
|
||||
}
|
||||
dispatcher->addItem(map, key, item);
|
||||
|
||||
caret.skipBlankChars();
|
||||
caret.canContinueAtChar(',', 1);
|
||||
|
||||
}
|
||||
|
||||
if(!caret.canContinueAtChar('}', 1)){
|
||||
if(!caret.hasError()){
|
||||
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeMap()]: Error. '}' - expected", ERROR_CODE_OBJECT_SCOPE_CLOSE);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return map;
|
||||
|
||||
} else {
|
||||
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeMap()]: Error. '{' - expected", ERROR_CODE_OBJECT_SCOPE_OPEN);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
oatpp::Void Deserializer::deserializeObject(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
|
||||
|
||||
if(caret.isAtText("null", true)){
|
||||
|
@ -163,53 +163,6 @@ private:
|
||||
|
||||
}
|
||||
|
||||
template<class Collection>
|
||||
static oatpp::Void deserializeList(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
|
||||
|
||||
if(caret.isAtText("null", true)){
|
||||
return oatpp::Void(type);
|
||||
}
|
||||
|
||||
if(caret.canContinueAtChar('[', 1)) {
|
||||
|
||||
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
|
||||
auto listWrapper = polymorphicDispatcher->createObject();
|
||||
const auto& list = listWrapper.template staticCast<Collection>();
|
||||
|
||||
auto itemType = *type->params.begin();
|
||||
|
||||
caret.skipBlankChars();
|
||||
|
||||
while(!caret.isAtChar(']') && caret.canContinue()){
|
||||
|
||||
caret.skipBlankChars();
|
||||
auto item = deserializer->deserialize(caret, itemType);
|
||||
if(caret.hasError()){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
polymorphicDispatcher->addPolymorphicItem(listWrapper, item);
|
||||
caret.skipBlankChars();
|
||||
|
||||
caret.canContinueAtChar(',', 1);
|
||||
|
||||
}
|
||||
|
||||
if(!caret.canContinueAtChar(']', 1)){
|
||||
if(!caret.hasError()){
|
||||
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeList()]: Error. ']' - expected", ERROR_CODE_ARRAY_SCOPE_CLOSE);
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
return oatpp::Void(list.getPtr(), list.getValueType());
|
||||
} else {
|
||||
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeList()]: Error. '[' - expected", ERROR_CODE_ARRAY_SCOPE_OPEN);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<class Collection>
|
||||
static oatpp::Void deserializeKeyValue(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
|
||||
|
||||
@ -221,7 +174,7 @@ private:
|
||||
|
||||
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
|
||||
auto mapWrapper = polymorphicDispatcher->createObject();
|
||||
const auto& map = mapWrapper.template staticCast<Collection>();
|
||||
const auto& map = mapWrapper.template cast<Collection>();
|
||||
|
||||
auto it = type->params.begin();
|
||||
auto keyType = *it ++;
|
||||
@ -282,6 +235,10 @@ private:
|
||||
static oatpp::Void deserializeString(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
|
||||
static oatpp::Void deserializeAny(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
|
||||
static oatpp::Void deserializeEnum(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
|
||||
|
||||
static oatpp::Void deserializeCollection(Deserializer* deserializer, parser::Caret& caret, const Type* type);
|
||||
static oatpp::Void deserializeMap(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
|
||||
|
||||
static oatpp::Void deserializeObject(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
|
||||
|
||||
private:
|
||||
|
@ -57,12 +57,12 @@ Serializer::Serializer(const std::shared_ptr<Config>& config)
|
||||
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::serializeList<oatpp::AbstractVector>);
|
||||
setSerializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::serializeList<oatpp::AbstractList>);
|
||||
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Serializer::serializeList<oatpp::AbstractUnorderedSet>);
|
||||
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::serializeKeyValue<oatpp::AbstractFields>);
|
||||
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Serializer::serializeKeyValue<oatpp::AbstractUnorderedFields>);
|
||||
setSerializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Serializer::serializeMap);
|
||||
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Serializer::serializeMap);
|
||||
|
||||
}
|
||||
|
||||
@ -136,6 +136,79 @@ void Serializer::serializeEnum(Serializer* serializer,
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializeCollection(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::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::parser::json::mapping::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(), 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)
|
||||
|
@ -132,58 +132,6 @@ private:
|
||||
stream->writeSimple("null", 4);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Collection>
|
||||
static void serializeList(Serializer* serializer, data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph) {
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& list = polymorph.staticCast<Collection>();
|
||||
|
||||
stream->writeCharSimple('[');
|
||||
bool first = true;
|
||||
|
||||
for(auto& value : *list) {
|
||||
if(value || serializer->getConfig()->includeNullFields || serializer->getConfig()->alwaysIncludeNullCollectionElements) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
serializer->serialize(stream, value);
|
||||
}
|
||||
}
|
||||
|
||||
stream->writeCharSimple(']');
|
||||
|
||||
}
|
||||
|
||||
template<class Collection>
|
||||
static void serializeKeyValue(Serializer* serializer, data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph) {
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& map = polymorph.staticCast<Collection>();
|
||||
|
||||
stream->writeCharSimple('{');
|
||||
bool first = true;
|
||||
|
||||
for(auto& pair : *map) {
|
||||
const auto& value = pair.second;
|
||||
if(value || serializer->m_config->includeNullFields || serializer->m_config->alwaysIncludeNullCollectionElements) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
const auto& key = pair.first;
|
||||
serializeString(stream, key->data(), key->size(), serializer->m_config->escapeFlags);
|
||||
stream->writeSimple(":", 1);
|
||||
serializer->serialize(stream, value);
|
||||
}
|
||||
}
|
||||
|
||||
stream->writeCharSimple('}');
|
||||
|
||||
}
|
||||
|
||||
static void serializeString(oatpp::data::stream::ConsistentOutputStream* stream,
|
||||
const char* data,
|
||||
@ -202,6 +150,14 @@ private:
|
||||
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);
|
||||
|
@ -391,7 +391,7 @@ struct ApiClient::TypeInterpretation<data::mapping::type::EnumObjectWrapper<T, I
|
||||
);
|
||||
}
|
||||
|
||||
return ApiClient::TypeInterpretation<UTOW>::toString(typeName, value.template staticCast<UTOW>());
|
||||
return ApiClient::TypeInterpretation<UTOW>::toString(typeName, value.template cast<UTOW>());
|
||||
|
||||
}
|
||||
|
||||
|
@ -562,7 +562,7 @@ struct ApiController::TypeInterpretation <data::mapping::type::EnumObjectWrapper
|
||||
data::mapping::type::EnumInterpreterError error = data::mapping::type::EnumInterpreterError::OK;
|
||||
const auto& result = I::fromInterpretation(parsedValue, error);
|
||||
if(error == data::mapping::type::EnumInterpreterError::OK) {
|
||||
return result.template staticCast<EnumOW>();
|
||||
return result.template cast<EnumOW>();
|
||||
}
|
||||
success = false;
|
||||
}
|
||||
|
@ -169,14 +169,14 @@ void EnumTest::onRun() {
|
||||
OATPP_ASSERT(inter.getValueType() == oatpp::String::Class::getType());
|
||||
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
|
||||
|
||||
auto interValue = inter.staticCast<oatpp::String>();
|
||||
auto interValue = inter.cast<oatpp::String>();
|
||||
OATPP_ASSERT(interValue == "name-1");
|
||||
|
||||
oatpp::Void voidValue = oatpp::Enum<Enum2>::AsString::Interpreter::fromInterpretation(interValue, e);
|
||||
OATPP_ASSERT(voidValue.getValueType() == oatpp::Enum<Enum2>::AsString::Class::getType());
|
||||
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
|
||||
|
||||
auto value = voidValue.staticCast<oatpp::Enum<Enum2>::AsString>();
|
||||
auto value = voidValue.cast<oatpp::Enum<Enum2>::AsString>();
|
||||
OATPP_ASSERT(value == Enum2::NAME_1);
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
@ -188,14 +188,14 @@ void EnumTest::onRun() {
|
||||
OATPP_ASSERT(inter.getValueType() == oatpp::Int32::Class::getType());
|
||||
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
|
||||
|
||||
auto interValue = inter.staticCast<oatpp::Int32>();
|
||||
auto interValue = inter.cast<oatpp::Int32>();
|
||||
OATPP_ASSERT(interValue == static_cast<v_int32>(Enum2::NAME_1));
|
||||
|
||||
oatpp::Void voidValue = oatpp::Enum<Enum2>::AsNumber::Interpreter::fromInterpretation(interValue, e);
|
||||
OATPP_ASSERT(voidValue.getValueType() == oatpp::Enum<Enum2>::AsNumber::Class::getType());
|
||||
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
|
||||
|
||||
auto value = voidValue.staticCast<oatpp::Enum<Enum2>::AsNumber>();
|
||||
auto value = voidValue.cast<oatpp::Enum<Enum2>::AsNumber>();
|
||||
OATPP_ASSERT(value == Enum2::NAME_1);
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ void InterpretationTest::onRun() {
|
||||
auto v = tr.resolveObjectPropertyValue(l, {"p1", "x"}, cache);
|
||||
OATPP_ASSERT(v);
|
||||
OATPP_ASSERT(v.getValueType() == oatpp::Int32::Class::getType());
|
||||
OATPP_ASSERT(v.staticCast<oatpp::Int32>() == 1);
|
||||
OATPP_ASSERT(v.cast<oatpp::Int32>() == 1);
|
||||
}
|
||||
|
||||
{
|
||||
@ -226,7 +226,7 @@ void InterpretationTest::onRun() {
|
||||
auto v = tr.resolveObjectPropertyValue(l, {"p1", "y"}, cache);
|
||||
OATPP_ASSERT(v);
|
||||
OATPP_ASSERT(v.getValueType() == oatpp::Int32::Class::getType());
|
||||
OATPP_ASSERT(v.staticCast<oatpp::Int32>() == 2);
|
||||
OATPP_ASSERT(v.cast<oatpp::Int32>() == 2);
|
||||
}
|
||||
|
||||
{
|
||||
@ -238,7 +238,7 @@ void InterpretationTest::onRun() {
|
||||
auto v = tr.resolveObjectPropertyValue(l, {"p1", "z"}, cache);
|
||||
OATPP_ASSERT(v);
|
||||
OATPP_ASSERT(v.getValueType() == oatpp::Int32::Class::getType());
|
||||
OATPP_ASSERT(v.staticCast<oatpp::Int32>() == 3);
|
||||
OATPP_ASSERT(v.cast<oatpp::Int32>() == 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -140,11 +140,11 @@ void ListTest::onRun() {
|
||||
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
|
||||
oatpp::List<oatpp::String> list = {"a", "b", "c"};
|
||||
|
||||
auto polymorphicDispatcher = static_cast<const typename oatpp::List<oatpp::String>::Class::PolymorphicDispatcher*>(
|
||||
auto polymorphicDispatcher = static_cast<const oatpp::data::mapping::type::__class::Collection::PolymorphicDispatcher*>(
|
||||
list.getValueType()->polymorphicDispatcher
|
||||
);
|
||||
|
||||
polymorphicDispatcher->addPolymorphicItem(list, oatpp::String("d"));
|
||||
polymorphicDispatcher->addItem(list, oatpp::String("d"));
|
||||
|
||||
OATPP_ASSERT(list->size() == 4);
|
||||
|
||||
|
@ -146,6 +146,21 @@ class PolymorphicDto2 : public oatpp::DTO {
|
||||
|
||||
};
|
||||
|
||||
class PolymorphicDto3 : public oatpp::DTO {
|
||||
|
||||
DTO_INIT(PolymorphicDto3, DTO)
|
||||
|
||||
DTO_FIELD(String, type);
|
||||
DTO_FIELD(Void, polymorph);
|
||||
|
||||
DTO_FIELD_TYPE_SELECTOR(polymorph) {
|
||||
if(self->type == "str") return String::Class::getType();
|
||||
if(self->type == "int") return Int32::Class::getType();
|
||||
return Void::Class::getType();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#include OATPP_CODEGEN_END(DTO)
|
||||
|
||||
void runDtoInitializations() {
|
||||
@ -484,13 +499,45 @@ void ObjectTest::onRun() {
|
||||
OATPP_ASSERT(dtoClone->polymorph)
|
||||
OATPP_ASSERT(dtoClone->polymorph.getValueType() == oatpp::Object<oatpp::DTO>::Class::getType())
|
||||
|
||||
auto polymorphClone = dtoClone->polymorph.staticCast<oatpp::Object<DtoTypeA>>();
|
||||
auto polymorphClone = dtoClone->polymorph.cast<oatpp::Object<DtoTypeA>>();
|
||||
|
||||
OATPP_ASSERT(polymorphClone->fieldA == "type-A")
|
||||
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
OATPP_LOGI(TAG, "Test 17...");
|
||||
|
||||
oatpp::parser::json::mapping::ObjectMapper mapper;
|
||||
|
||||
auto dto = PolymorphicDto3::createShared();
|
||||
|
||||
dto->type = "str";
|
||||
dto->polymorph = oatpp::String("Hello World!");
|
||||
|
||||
OATPP_ASSERT(dto->polymorph.getValueType() == oatpp::String::Class::getType())
|
||||
|
||||
auto json = mapper.writeToString(dto);
|
||||
OATPP_LOGD(TAG, "json0='%s'", json->c_str())
|
||||
|
||||
auto dtoClone = mapper.readFromString<oatpp::Object<PolymorphicDto3>>(json);
|
||||
|
||||
auto jsonClone = mapper.writeToString(dtoClone);
|
||||
OATPP_LOGD(TAG, "json1='%s'", jsonClone->c_str())
|
||||
|
||||
OATPP_ASSERT(json == jsonClone)
|
||||
|
||||
OATPP_ASSERT(dtoClone->polymorph)
|
||||
OATPP_ASSERT(dtoClone->polymorph.getValueType() == oatpp::Void::Class::getType())
|
||||
|
||||
auto polymorphClone = dtoClone->polymorph.cast<oatpp::String>();
|
||||
|
||||
OATPP_ASSERT(polymorphClone == "Hello World!")
|
||||
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}}}}}}
|
||||
|
@ -83,8 +83,14 @@ void ObjectWrapperTest::onRun() {
|
||||
OATPP_LOGI(TAG, "Check valueType is NOT assigned from copy-assign operator...");
|
||||
ObjectWrapper<std::string> pw1(oatpp::data::mapping::type::__class::String::getType());
|
||||
ObjectWrapper<std::string> pw2;
|
||||
pw2 = pw1;
|
||||
bool throws = false;
|
||||
try {
|
||||
pw2 = pw1;
|
||||
} catch (std::runtime_error& e) {
|
||||
throws = true;
|
||||
}
|
||||
OATPP_ASSERT(pw2.getValueType() == oatpp::data::mapping::type::__class::Void::getType());
|
||||
OATPP_ASSERT(throws)
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
@ -92,8 +98,14 @@ void ObjectWrapperTest::onRun() {
|
||||
OATPP_LOGI(TAG, "Check valueType is NOT assigned from move-assign operator...");
|
||||
ObjectWrapper<std::string> pw1(oatpp::data::mapping::type::__class::String::getType());
|
||||
ObjectWrapper<std::string> pw2;
|
||||
pw2 = std::move(pw1);
|
||||
bool throws = false;
|
||||
try {
|
||||
pw2 = std::move(pw1);
|
||||
} catch (std::runtime_error& e) {
|
||||
throws = true;
|
||||
}
|
||||
OATPP_ASSERT(pw2.getValueType() == oatpp::data::mapping::type::__class::Void::getType());
|
||||
OATPP_ASSERT(throws)
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
@ -176,7 +188,7 @@ void ObjectWrapperTest::onRun() {
|
||||
|
||||
OATPP_ASSERT(v.getValueType() == oatpp::Int32::Class::getType());
|
||||
|
||||
oatpp::Int32 i = v.staticCast<oatpp::Int32>();
|
||||
oatpp::Int32 i = v.cast<oatpp::Int32>();
|
||||
|
||||
OATPP_ASSERT(i.getValueType() == oatpp::Int32::Class::getType());
|
||||
OATPP_ASSERT(i == 32);
|
||||
|
@ -148,11 +148,11 @@ void PairListTest::onRun() {
|
||||
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
|
||||
oatpp::Fields<String> map = {{"key1", "a"}, {"key2", "b"}, {"key3", "c"}};
|
||||
|
||||
auto polymorphicDispatcher = static_cast<const typename oatpp::Fields<String>::Class::PolymorphicDispatcher*>(
|
||||
auto polymorphicDispatcher = static_cast<const typename oatpp::data::mapping::type::__class::Map::PolymorphicDispatcher*>(
|
||||
map.getValueType()->polymorphicDispatcher
|
||||
);
|
||||
|
||||
polymorphicDispatcher->addPolymorphicItem(map, oatpp::String("key1"), oatpp::String("d"));
|
||||
polymorphicDispatcher->addItem(map, oatpp::String("key1"), oatpp::String("d"));
|
||||
|
||||
OATPP_ASSERT(map->size() == 4);
|
||||
|
||||
|
@ -144,11 +144,11 @@ void UnorderedMapTest::onRun() {
|
||||
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
|
||||
oatpp::UnorderedFields<String> map = {{"key1", "a"}, {"key2", "b"}, {"key3", "c"}};
|
||||
|
||||
auto polymorphicDispatcher = static_cast<const typename oatpp::UnorderedFields<String>::Class::PolymorphicDispatcher*>(
|
||||
auto polymorphicDispatcher = static_cast<const typename oatpp::data::mapping::type::__class::Map::PolymorphicDispatcher*>(
|
||||
map.getValueType()->polymorphicDispatcher
|
||||
);
|
||||
|
||||
polymorphicDispatcher->addPolymorphicItem(map, oatpp::String("key1"), oatpp::String("d"));
|
||||
polymorphicDispatcher->addItem(map, oatpp::String("key1"), oatpp::String("d"));
|
||||
|
||||
OATPP_ASSERT(map->size() == 3);
|
||||
|
||||
|
@ -120,15 +120,15 @@ void UnorderedSetTest::onRun() {
|
||||
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
|
||||
oatpp::UnorderedSet<oatpp::String> set = {"a", "b", "c"};
|
||||
|
||||
auto polymorphicDispatcher = static_cast<const typename oatpp::UnorderedSet<oatpp::String>::Class::PolymorphicDispatcher*>(
|
||||
auto polymorphicDispatcher = static_cast<const typename oatpp::data::mapping::type::__class::Collection::PolymorphicDispatcher*>(
|
||||
set.getValueType()->polymorphicDispatcher
|
||||
);
|
||||
|
||||
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("a"));
|
||||
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("b"));
|
||||
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("c"));
|
||||
polymorphicDispatcher->addItem(set, oatpp::String("a"));
|
||||
polymorphicDispatcher->addItem(set, oatpp::String("b"));
|
||||
polymorphicDispatcher->addItem(set, oatpp::String("c"));
|
||||
|
||||
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("d"));
|
||||
polymorphicDispatcher->addItem(set, oatpp::String("d"));
|
||||
|
||||
OATPP_ASSERT(set->size() == 4);
|
||||
|
||||
|
@ -140,11 +140,11 @@ void VectorTest::onRun() {
|
||||
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
|
||||
oatpp::Vector<oatpp::String> vector = {"a", "b", "c"};
|
||||
|
||||
auto polymorphicDispatcher = static_cast<const typename oatpp::Vector<oatpp::String>::Class::PolymorphicDispatcher*>(
|
||||
auto polymorphicDispatcher = static_cast<const oatpp::data::mapping::type::__class::Collection::PolymorphicDispatcher*>(
|
||||
vector.getValueType()->polymorphicDispatcher
|
||||
);
|
||||
|
||||
polymorphicDispatcher->addPolymorphicItem(vector, oatpp::String("d"));
|
||||
polymorphicDispatcher->addItem(vector, oatpp::String("d"));
|
||||
|
||||
OATPP_ASSERT(vector->size() == 4);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user