mirror of
https://github.com/oatpp/oatpp.git
synced 2024-11-27 08:30:07 +08:00
Merge pull request #642 from doufu3344/DTO_float_fmt
Supported for specifying float value format on serializing DTO to JSON
This commit is contained in:
commit
6dd493ca5f
@ -102,6 +102,10 @@ public:
|
||||
*/
|
||||
std::string pattern = "";
|
||||
|
||||
/**
|
||||
* Format.
|
||||
*/
|
||||
std::string format = "";
|
||||
/**
|
||||
* Required.
|
||||
*/
|
||||
|
@ -397,18 +397,18 @@ v_io_size ConsistentOutputStream::writeAsString(v_uint64 value){
|
||||
return 0;
|
||||
}
|
||||
|
||||
v_io_size ConsistentOutputStream::writeAsString(v_float32 value){
|
||||
v_io_size ConsistentOutputStream::writeAsString(v_float32 value, const char* format){
|
||||
v_char8 a[100];
|
||||
auto size = utils::conversion::float32ToCharSequence(value, &a[0], 100);
|
||||
auto size = utils::conversion::float32ToCharSequence(value, &a[0], 100, format);
|
||||
if(size > 0){
|
||||
return writeSimple(&a[0], size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
v_io_size ConsistentOutputStream::writeAsString(v_float64 value){
|
||||
v_io_size ConsistentOutputStream::writeAsString(v_float64 value, const char* format){
|
||||
v_char8 a[100];
|
||||
auto size = utils::conversion::float64ToCharSequence(value, &a[0], 100);
|
||||
auto size = utils::conversion::float64ToCharSequence(value, &a[0], 100, format);
|
||||
if(size > 0){
|
||||
return writeSimple(&a[0], size);
|
||||
}
|
||||
@ -533,6 +533,18 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const char* str)
|
||||
return s;
|
||||
}
|
||||
|
||||
template<>
|
||||
ConsistentOutputStream& operator << (ConsistentOutputStream& s, v_float32 value) {
|
||||
s.writeAsString(value, "");
|
||||
return s;
|
||||
}
|
||||
|
||||
template<>
|
||||
ConsistentOutputStream& operator << (ConsistentOutputStream& s, v_float64 value) {
|
||||
s.writeAsString(value, "");
|
||||
return s;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DataTransferProcessor
|
||||
|
||||
|
@ -467,14 +467,14 @@ public:
|
||||
* @param value
|
||||
* @return - actual number of bytes written. &id:oatpp::v_io_size;. <br>
|
||||
*/
|
||||
v_io_size writeAsString(v_float32 value);
|
||||
v_io_size writeAsString(v_float32 value, const char* format);
|
||||
|
||||
/**
|
||||
* Convert value to string and write to stream.
|
||||
* @param value
|
||||
* @return - actual number of bytes written. &id:oatpp::v_io_size;. <br>
|
||||
*/
|
||||
v_io_size writeAsString(v_float64 value);
|
||||
v_io_size writeAsString(v_float64 value, const char* format);
|
||||
|
||||
/**
|
||||
* Convert value to string and write to stream.
|
||||
@ -506,6 +506,12 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, T value) {
|
||||
return s;
|
||||
}
|
||||
|
||||
template<>
|
||||
ConsistentOutputStream& operator << (ConsistentOutputStream& s, v_float32 value);
|
||||
|
||||
template<>
|
||||
ConsistentOutputStream& operator << (ConsistentOutputStream& s, v_float64 value);
|
||||
|
||||
/**
|
||||
* Error of Asynchronous stream transfer.
|
||||
*/
|
||||
|
@ -189,10 +189,16 @@ namespace oatpp { namespace utils { namespace conversion {
|
||||
}
|
||||
|
||||
v_buff_size float32ToCharSequence(v_float32 value, p_char8 data, v_buff_size n, const char* format) {
|
||||
if(std::strlen(format) <= 0){
|
||||
format = OATPP_FLOAT_STRING_FORMAT;
|
||||
}
|
||||
return snprintf((char*)data, n, format, value);
|
||||
}
|
||||
|
||||
v_buff_size float64ToCharSequence(v_float64 value, p_char8 data, v_buff_size n, const char* format) {
|
||||
if(std::strlen(format) <= 0){
|
||||
format = OATPP_FLOAT_STRING_FORMAT;
|
||||
}
|
||||
return snprintf((char*)data, n, format, value);
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,44 @@ void Serializer::setSerializerMethod(const data::mapping::type::ClassId& classId
|
||||
m_methods[id] = method;
|
||||
}
|
||||
|
||||
template<>
|
||||
void Serializer::serializePrimitive<Float32>(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph){
|
||||
if (polymorph) {
|
||||
std::string format;
|
||||
if (!context->info.format.empty()) {
|
||||
format = context->info.format;
|
||||
}
|
||||
else if (!context->serializer->m_config->floatStringFormat->empty()) {
|
||||
format = context->serializer->m_config->floatStringFormat;
|
||||
}
|
||||
context->stream->writeAsString(*static_cast<v_float32*>(polymorph.get()),
|
||||
format.c_str());
|
||||
}
|
||||
else {
|
||||
context->stream->writeSimple("null", 4);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void Serializer::serializePrimitive<Float64>(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph) {
|
||||
if (polymorph) {
|
||||
std::string format;
|
||||
if (!context->info.format.empty()) {
|
||||
format = context->info.format;
|
||||
}
|
||||
else if (!context->serializer->m_config->floatStringFormat->empty()) {
|
||||
format = context->serializer->m_config->floatStringFormat;
|
||||
}
|
||||
context->stream->writeAsString(*static_cast<v_float64*>(polymorph.get()),
|
||||
format.c_str());
|
||||
}
|
||||
else {
|
||||
context->stream->writeSimple("null", 4);
|
||||
}
|
||||
}
|
||||
|
||||
void Serializer::serializeString(data::stream::ConsistentOutputStream* stream, const char* data, v_buff_size size, v_uint32 escapeFlags) {
|
||||
auto encodedValue = Utils::escapeString(data, size, escapeFlags);
|
||||
stream->writeCharSimple('\"');
|
||||
@ -81,39 +119,36 @@ void Serializer::serializeString(data::stream::ConsistentOutputStream* stream, c
|
||||
stream->writeCharSimple('\"');
|
||||
}
|
||||
|
||||
void Serializer::serializeString(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
void Serializer::serializeString(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
context->stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
auto str = static_cast<std::string*>(polymorph.get());
|
||||
|
||||
serializeString(stream, str->data(), str->size(), serializer->m_config->escapeFlags);
|
||||
serializeString(context->stream, str->data(), str->size(), context->serializer->m_config->escapeFlags);
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializeAny(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
void Serializer::serializeAny(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
context->stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
auto anyHandle = static_cast<data::mapping::type::AnyHandle*>(polymorph.get());
|
||||
serializer->serialize(stream, oatpp::Void(anyHandle->ptr, anyHandle->type));
|
||||
context->serializer->serialize(context, oatpp::Void(anyHandle->ptr, anyHandle->type));
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializeEnum(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
void Serializer::serializeEnum(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph)
|
||||
{
|
||||
auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::PolymorphicDispatcher*>(
|
||||
@ -121,7 +156,7 @@ void Serializer::serializeEnum(Serializer* serializer,
|
||||
);
|
||||
|
||||
data::mapping::type::EnumInterpreterError e = data::mapping::type::EnumInterpreterError::OK;
|
||||
serializer->serialize(stream, polymorphicDispatcher->toInterpretation(polymorph, e));
|
||||
context->serializer->serialize(context, polymorphicDispatcher->toInterpretation(polymorph, e));
|
||||
|
||||
if(e == data::mapping::type::EnumInterpreterError::OK) {
|
||||
return;
|
||||
@ -136,13 +171,12 @@ void Serializer::serializeEnum(Serializer* serializer,
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializeCollection(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
void Serializer::serializeCollection(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
context->stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -150,31 +184,32 @@ void Serializer::serializeCollection(Serializer* serializer,
|
||||
polymorph.getValueType()->polymorphicDispatcher
|
||||
);
|
||||
|
||||
stream->writeCharSimple('[');
|
||||
context->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);
|
||||
if(value ||
|
||||
context->serializer->getConfig()->includeNullFields ||
|
||||
context->serializer->getConfig()->alwaysIncludeNullCollectionElements) {
|
||||
(first) ? first = false : context->stream->writeSimple(",", 1);
|
||||
context->serializer->serialize(context, value);
|
||||
}
|
||||
iterator->next();
|
||||
}
|
||||
|
||||
stream->writeCharSimple(']');
|
||||
context->stream->writeCharSimple(']');
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializeMap(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
void Serializer::serializeMap(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
context->stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -187,39 +222,40 @@ void Serializer::serializeMap(Serializer* serializer,
|
||||
throw std::runtime_error("[oatpp::parser::json::mapping::Serializer::serializeMap()]: Invalid json map key. Key should be String");
|
||||
}
|
||||
|
||||
stream->writeCharSimple('{');
|
||||
context->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);
|
||||
if(value ||
|
||||
context->serializer->m_config->includeNullFields ||
|
||||
context->serializer->m_config->alwaysIncludeNullCollectionElements) {
|
||||
(first) ? first = false : context->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);
|
||||
serializeString(context->stream, key->data(), key->size(), context->serializer->m_config->escapeFlags);
|
||||
context->stream->writeSimple(":", 1);
|
||||
context->serializer->serialize(context, value);
|
||||
}
|
||||
iterator->next();
|
||||
}
|
||||
|
||||
stream->writeCharSimple('}');
|
||||
context->stream->writeCharSimple('}');
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serializeObject(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
const oatpp::Void& polymorph)
|
||||
void Serializer::serializeObject(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph)
|
||||
{
|
||||
|
||||
if(!polymorph) {
|
||||
stream->writeSimple("null", 4);
|
||||
context->stream->writeSimple("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
stream->writeCharSimple('{');
|
||||
context->stream->writeCharSimple('{');
|
||||
|
||||
bool first = true;
|
||||
auto dispatcher = static_cast<const oatpp::data::mapping::type::__class::AbstractObject::PolymorphicDispatcher*>(
|
||||
@ -227,7 +263,7 @@ void Serializer::serializeObject(Serializer* serializer,
|
||||
);
|
||||
auto fields = dispatcher->getProperties()->getList();
|
||||
auto object = static_cast<oatpp::BaseObject*>(polymorph.get());
|
||||
auto config = serializer->m_config;
|
||||
auto config = context->serializer->m_config;
|
||||
|
||||
for (auto const& field : fields) {
|
||||
|
||||
@ -240,30 +276,31 @@ void Serializer::serializeObject(Serializer* serializer,
|
||||
}
|
||||
|
||||
if (value || config->includeNullFields || (field->info.required && config->alwaysIncludeRequired)) {
|
||||
(first) ? first = false : stream->writeSimple(",", 1);
|
||||
serializeString(stream, field->name, std::strlen(field->name), serializer->m_config->escapeFlags);
|
||||
stream->writeSimple(":", 1);
|
||||
serializer->serialize(stream, value);
|
||||
(first) ? first = false : context->stream->writeSimple(",", 1);
|
||||
serializeString(context->stream, field->name, std::strlen(field->name), context->serializer->m_config->escapeFlags);
|
||||
context->stream->writeSimple(":", 1);
|
||||
context->info = field->info;
|
||||
context->serializer->serialize(context, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stream->writeCharSimple('}');
|
||||
context->stream->writeCharSimple('}');
|
||||
|
||||
}
|
||||
|
||||
void Serializer::serialize(data::stream::ConsistentOutputStream* stream,
|
||||
void Serializer::serialize(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph)
|
||||
{
|
||||
auto id = polymorph.getValueType()->classId.id;
|
||||
auto& method = m_methods[id];
|
||||
if(method) {
|
||||
(*method)(this, stream, polymorph);
|
||||
(*method)(context, polymorph);
|
||||
} else {
|
||||
|
||||
auto* interpretation = polymorph.getValueType()->findInterpretation(m_config->enabledInterpretations);
|
||||
if(interpretation) {
|
||||
serialize(stream, interpretation->toInterpretation(polymorph));
|
||||
serialize(context, interpretation->toInterpretation(polymorph));
|
||||
} else {
|
||||
throw std::runtime_error("[oatpp::parser::json::mapping::Serializer::serialize()]: "
|
||||
"Error. No serialize method for type '" +
|
||||
@ -278,9 +315,11 @@ void Serializer::serializeToStream(data::stream::ConsistentOutputStream* stream,
|
||||
{
|
||||
if(m_config->useBeautifier) {
|
||||
json::Beautifier beautifier(stream, " ", "\n");
|
||||
serialize(&beautifier, polymorph);
|
||||
auto context = std::unique_ptr<Context>(new Context(this, &beautifier));
|
||||
serialize(context, polymorph);
|
||||
} else {
|
||||
serialize(stream, polymorph);
|
||||
auto context = std::unique_ptr<Context>(new Context(this,stream));
|
||||
serialize(context, polymorph);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,56 +113,72 @@ public:
|
||||
*/
|
||||
v_uint32 escapeFlags = json::Utils::FLAG_ESCAPE_ALL;
|
||||
|
||||
/**
|
||||
* Format of float string.
|
||||
*/
|
||||
oatpp::String floatStringFormat = "";
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
/**
|
||||
* Serializer context.
|
||||
*/
|
||||
class Context : public oatpp::base::Countable {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Context(Serializer *serializer, data::stream::ConsistentOutputStream* stream)
|
||||
: serializer(serializer), stream(stream)
|
||||
{}
|
||||
public:
|
||||
|
||||
Serializer* serializer;
|
||||
data::stream::ConsistentOutputStream* stream;
|
||||
|
||||
data::mapping::type::BaseObject::Property::Info info;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef void (*SerializerMethod)(Serializer*,
|
||||
data::stream::ConsistentOutputStream*,
|
||||
typedef void (*SerializerMethod)(const std::unique_ptr<Context>&,
|
||||
const oatpp::Void&);
|
||||
private:
|
||||
|
||||
template<class T>
|
||||
static void serializePrimitive(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
static void serializePrimitive(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph){
|
||||
(void) serializer;
|
||||
|
||||
if(polymorph){
|
||||
stream->writeAsString(* static_cast<typename T::ObjectType*>(polymorph.get()));
|
||||
context->stream->writeAsString(* static_cast<typename T::ObjectType*>(polymorph.get()));
|
||||
} else {
|
||||
stream->writeSimple("null", 4);
|
||||
context->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,
|
||||
static void serializeString(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph);
|
||||
|
||||
static void serializeAny(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
static void serializeAny(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph);
|
||||
|
||||
static void serializeEnum(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
static void serializeEnum(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph);
|
||||
|
||||
static void serializeCollection(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
static void serializeCollection(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph);
|
||||
|
||||
static void serializeMap(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
static void serializeMap(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph);
|
||||
|
||||
static void serializeObject(Serializer* serializer,
|
||||
data::stream::ConsistentOutputStream* stream,
|
||||
static void serializeObject(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph);
|
||||
|
||||
void serialize(data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph);
|
||||
void serialize(const std::unique_ptr<Context>& context, const oatpp::Void& polymorph);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Config> m_config;
|
||||
@ -197,6 +213,14 @@ public:
|
||||
|
||||
};
|
||||
|
||||
template<>
|
||||
void Serializer::serializePrimitive<Float32>(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph);
|
||||
|
||||
template<>
|
||||
void Serializer::serializePrimitive<Float64>(const std::unique_ptr<Context>& context,
|
||||
const oatpp::Void& polymorph);
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /* oatpp_parser_json_mapping_Serializer_hpp */
|
||||
|
@ -75,6 +75,8 @@ add_executable(oatppAllTests
|
||||
oatpp/parser/json/mapping/DeserializerTest.hpp
|
||||
oatpp/parser/json/mapping/EnumTest.cpp
|
||||
oatpp/parser/json/mapping/EnumTest.hpp
|
||||
oatpp/parser/json/mapping/FloatTest.cpp
|
||||
oatpp/parser/json/mapping/FloatTest.hpp
|
||||
oatpp/parser/json/mapping/UnorderedSetTest.cpp
|
||||
oatpp/parser/json/mapping/UnorderedSetTest.hpp
|
||||
oatpp/web/protocol/http/encoding/ChunkedTest.cpp
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "oatpp/parser/json/mapping/DTOMapperPerfTest.hpp"
|
||||
#include "oatpp/parser/json/mapping/DTOMapperTest.hpp"
|
||||
#include "oatpp/parser/json/mapping/EnumTest.hpp"
|
||||
#include "oatpp/parser/json/mapping/FloatTest.hpp"
|
||||
#include "oatpp/parser/json/mapping/UnorderedSetTest.hpp"
|
||||
|
||||
#include "oatpp/encoding/UnicodeTest.hpp"
|
||||
@ -123,6 +124,8 @@ void runTests() {
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::parser::json::mapping::EnumTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::parser::json::mapping::FloatTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::parser::json::mapping::UnorderedSetTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::parser::json::mapping::DeserializerTest);
|
||||
|
236
test/oatpp/parser/json/mapping/FloatTest.cpp
Normal file
236
test/oatpp/parser/json/mapping/FloatTest.cpp
Normal file
@ -0,0 +1,236 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 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 <thread>
|
||||
|
||||
#include "FloatTest.hpp"
|
||||
|
||||
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
|
||||
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
|
||||
namespace oatpp { namespace test { namespace parser { namespace json { namespace mapping {
|
||||
|
||||
namespace {
|
||||
|
||||
#include OATPP_CODEGEN_BEGIN(DTO)
|
||||
|
||||
|
||||
class DTO_32_0 : public oatpp::DTO {
|
||||
|
||||
DTO_INIT(DTO_32_0, DTO)
|
||||
|
||||
DTO_FIELD(Float32, f32);
|
||||
};
|
||||
|
||||
class DTO_32_1 : public oatpp::DTO {
|
||||
|
||||
DTO_INIT(DTO_32_1, DTO)
|
||||
|
||||
DTO_FIELD_INFO(f32) {
|
||||
info->format = "%.2f";
|
||||
}
|
||||
DTO_FIELD(Float32, f32);
|
||||
};
|
||||
|
||||
class DTO_64_0 : public oatpp::DTO {
|
||||
|
||||
DTO_INIT(DTO_64_0, DTO)
|
||||
|
||||
DTO_FIELD(Float64, f64);
|
||||
};
|
||||
|
||||
class DTO_64_1 : public oatpp::DTO {
|
||||
|
||||
DTO_INIT(DTO_64_1, DTO)
|
||||
|
||||
DTO_FIELD_INFO(f64) {
|
||||
info->format = "%.2f";
|
||||
}
|
||||
DTO_FIELD(Float64, f64);
|
||||
};
|
||||
|
||||
class DTO_64_2 : public oatpp::DTO {
|
||||
|
||||
DTO_INIT(DTO_64_2, DTO)
|
||||
|
||||
DTO_FIELD_INFO(f64_1) {
|
||||
info->format = "%.1f";
|
||||
}
|
||||
DTO_FIELD(Float64, f64_1);
|
||||
|
||||
DTO_FIELD_INFO(f64_2) {
|
||||
info->format = "%.2f";
|
||||
}
|
||||
DTO_FIELD(Float64, f64_2);
|
||||
|
||||
DTO_FIELD(Int32, i);
|
||||
};
|
||||
|
||||
#include OATPP_CODEGEN_END(DTO)
|
||||
|
||||
}
|
||||
|
||||
void FloatTest::onRun() {
|
||||
|
||||
oatpp::parser::json::mapping::ObjectMapper mapper;
|
||||
oatpp::parser::json::mapping::ObjectMapper mapperFmt;
|
||||
mapperFmt.getSerializer()->getConfig()->floatStringFormat = "%.1f";
|
||||
|
||||
OATPP_LOGI(TAG, "Serialize float: 123456.123456");
|
||||
{
|
||||
auto test = DTO_32_0::createShared();
|
||||
test->f32 = 123456.123456;
|
||||
OATPP_LOGI(TAG, "using default format...");
|
||||
auto json = mapper.writeToString(test);
|
||||
OATPP_LOGD(TAG, "json='%s'", json->c_str());
|
||||
OATPP_ASSERT(json != "{\"f32\":123456.123456}");
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
auto test = DTO_32_1::createShared();
|
||||
test->f32 = 123456.123456;
|
||||
OATPP_LOGI(TAG, "using \"%%.2f\" format...");
|
||||
auto json = mapper.writeToString(test);
|
||||
OATPP_LOGD(TAG, "json='%s'", json->c_str());
|
||||
OATPP_ASSERT(json == "{\"f32\":123456.12}");
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
auto test = DTO_64_0::createShared();
|
||||
test->f64 = 123456.123456;// +0.2;
|
||||
OATPP_LOGI(TAG, "using default format...");
|
||||
auto json = mapper.writeToString(test);
|
||||
OATPP_LOGD(TAG, "json='%s'", json->c_str());
|
||||
OATPP_ASSERT(json == "{\"f64\":123456.123456}");
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
auto test = DTO_64_1::createShared();
|
||||
test->f64 = 123456.123456;
|
||||
OATPP_LOGI(TAG, "using \"%%.2f\" format...");
|
||||
auto json = mapper.writeToString(test);
|
||||
OATPP_LOGD(TAG, "json='%s'", json->c_str());
|
||||
OATPP_ASSERT(json == "{\"f64\":123456.12}");
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
auto test = DTO_64_2::createShared();
|
||||
test->f64_1 = 123456.123456;
|
||||
test->f64_2 = 123456.123456;
|
||||
test->i = 10;
|
||||
OATPP_LOGI(TAG, "using 2 formats...");
|
||||
auto json = mapper.writeToString(test);
|
||||
OATPP_LOGD(TAG, "json='%s'", json->c_str());
|
||||
OATPP_ASSERT(json == "{\"f64_1\":123456.1,\"f64_2\":123456.12,\"i\":10}");
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
auto test = DTO_32_0::createShared();
|
||||
test->f32 = 123456.123456;
|
||||
OATPP_LOGI(TAG, "using config's \"%%.1f\" format...");
|
||||
auto json = mapperFmt.writeToString(test);
|
||||
OATPP_LOGD(TAG, "json='%s'", json->c_str());
|
||||
OATPP_ASSERT(json == "{\"f32\":123456.1}");
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
auto test = DTO_64_0::createShared();
|
||||
test->f64 = 123456.123456;
|
||||
OATPP_LOGI(TAG, "using config's \"%%.1f\" format...");
|
||||
auto json = mapperFmt.writeToString(test);
|
||||
OATPP_LOGD(TAG, "json='%s'", json->c_str());
|
||||
OATPP_ASSERT(json == "{\"f64\":123456.1}");
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
auto test = DTO_64_1::createShared();
|
||||
test->f64 = 123456.123456;
|
||||
OATPP_LOGI(TAG, "using field's \"%%.2f\" to override config's \"%%.1f\" format...");
|
||||
auto json = mapperFmt.writeToString(test);
|
||||
OATPP_LOGD(TAG, "json='%s'", json->c_str());
|
||||
OATPP_ASSERT(json == "{\"f64\":123456.12}");
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
mapperFmt.getSerializer()->getConfig()->useBeautifier = true;
|
||||
auto test = DTO_64_0::createShared();
|
||||
test->f64 = 123456.123456;
|
||||
OATPP_LOGI(TAG, "using config's \"%%.1f\" format(useBeautifier) ...");
|
||||
auto json = mapperFmt.writeToString(test);
|
||||
OATPP_LOGD(TAG, "json='%s'", json->c_str());
|
||||
OATPP_ASSERT(json == "{\n \"f64\": 123456.1\n}");
|
||||
OATPP_LOGI(TAG, "OK");
|
||||
}
|
||||
|
||||
{
|
||||
int count = 10000;
|
||||
bool parallel_result = true;
|
||||
auto test1 = DTO_64_0::createShared();
|
||||
test1->f64 = 123456.123456;
|
||||
OATPP_LOGI(TAG, "parallel 1: using default format...");
|
||||
OATPP_LOGI(TAG, "expect: json1='%s'", "{\"f64\":123456.123456}");
|
||||
std::thread proc1([&]() {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
auto json = mapper.writeToString(test1);
|
||||
if (json != "{\"f64\":123456.123456}") {
|
||||
OATPP_LOGE(TAG, "json1='%s'", json->c_str());
|
||||
parallel_result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
auto test2 = DTO_64_1::createShared();
|
||||
test2->f64 = 123456.123456;
|
||||
OATPP_LOGI(TAG, "parallel 2: using \"%%.2f\" format...");
|
||||
OATPP_LOGI(TAG, "expect: json2='%s'", "{\"f64\":123456.12}");
|
||||
std::thread proc2([&]() {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
auto json = mapper.writeToString(test2);
|
||||
if (json != "{\"f64\":123456.12}") {
|
||||
OATPP_LOGE(TAG, "json2='%s'", json->c_str());
|
||||
parallel_result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
proc1.join();
|
||||
proc2.join();
|
||||
|
||||
OATPP_ASSERT(parallel_result == true);
|
||||
OATPP_LOGI(TAG, "parallel OK");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}}}}}
|
42
test/oatpp/parser/json/mapping/FloatTest.hpp
Normal file
42
test/oatpp/parser/json/mapping/FloatTest.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 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_test_parser_json_mapping_FloatTest_hpp
|
||||
#define oatpp_test_parser_json_mapping_FloatTest_hpp
|
||||
|
||||
#include "oatpp-test/UnitTest.hpp"
|
||||
|
||||
namespace oatpp { namespace test { namespace parser { namespace json { namespace mapping {
|
||||
|
||||
class FloatTest : public UnitTest{
|
||||
public:
|
||||
|
||||
FloatTest():UnitTest("TEST[parser::json::mapping::FloatTest]"){}
|
||||
void onRun() override;
|
||||
|
||||
};
|
||||
|
||||
}}}}}
|
||||
|
||||
#endif /* oatpp_test_parser_json_mapping_FloatTest_hpp */
|
Loading…
Reference in New Issue
Block a user