From 1564eba64bf11ce4b4c9c8008eecb531732849a3 Mon Sep 17 00:00:00 2001 From: doufu3344 Date: Mon, 31 Oct 2022 09:50:42 +0800 Subject: [PATCH] remove float format info in serializing stream --- src/oatpp/core/data/mapping/type/Object.hpp | 2 +- src/oatpp/core/data/stream/Stream.cpp | 20 +++++-- src/oatpp/core/data/stream/Stream.hpp | 11 ++-- src/oatpp/core/utils/ConversionUtils.cpp | 6 +++ src/oatpp/parser/json/mapping/Serializer.cpp | 56 +++++++++++++++----- src/oatpp/parser/json/mapping/Serializer.hpp | 32 ++++++++++- test/oatpp/parser/json/mapping/FloatTest.cpp | 43 ++++++++++++--- 7 files changed, 141 insertions(+), 29 deletions(-) diff --git a/src/oatpp/core/data/mapping/type/Object.hpp b/src/oatpp/core/data/mapping/type/Object.hpp index 6aae76f9..f3aa5ad9 100644 --- a/src/oatpp/core/data/mapping/type/Object.hpp +++ b/src/oatpp/core/data/mapping/type/Object.hpp @@ -105,7 +105,7 @@ public: /** * Format. */ - std::string format = OATPP_FLOAT_STRING_FORMAT; + std::string format = ""; /** * Required. */ diff --git a/src/oatpp/core/data/stream/Stream.cpp b/src/oatpp/core/data/stream/Stream.cpp index 180b00c3..3bc18248 100644 --- a/src/oatpp/core/data/stream/Stream.cpp +++ b/src/oatpp/core/data/stream/Stream.cpp @@ -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, floatFormat->c_str()); + 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, floatFormat->c_str()); + 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 diff --git a/src/oatpp/core/data/stream/Stream.hpp b/src/oatpp/core/data/stream/Stream.hpp index a7068205..6162e15d 100644 --- a/src/oatpp/core/data/stream/Stream.hpp +++ b/src/oatpp/core/data/stream/Stream.hpp @@ -405,7 +405,6 @@ public: */ class ConsistentOutputStream : public OutputStream { public: - String floatFormat = OATPP_FLOAT_STRING_FORMAT; /** * Convert value to string and write to stream. @@ -468,14 +467,14 @@ public: * @param value * @return - actual number of bytes written. &id:oatpp::v_io_size;.
*/ - 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;.
*/ - 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. @@ -507,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. */ diff --git a/src/oatpp/core/utils/ConversionUtils.cpp b/src/oatpp/core/utils/ConversionUtils.cpp index a5ef0134..8485a9e9 100644 --- a/src/oatpp/core/utils/ConversionUtils.cpp +++ b/src/oatpp/core/utils/ConversionUtils.cpp @@ -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); } diff --git a/src/oatpp/parser/json/mapping/Serializer.cpp b/src/oatpp/parser/json/mapping/Serializer.cpp index 8a8b1515..fc469a59 100644 --- a/src/oatpp/parser/json/mapping/Serializer.cpp +++ b/src/oatpp/parser/json/mapping/Serializer.cpp @@ -64,6 +64,7 @@ Serializer::Serializer(const std::shared_ptr& config) setSerializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Serializer::serializeMap); setSerializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Serializer::serializeMap); + m_context = std::unique_ptr(new Context()); } void Serializer::setSerializerMethod(const data::mapping::type::ClassId& classId, SerializerMethod method) { @@ -74,6 +75,46 @@ void Serializer::setSerializerMethod(const data::mapping::type::ClassId& classId m_methods[id] = method; } +template<> +void Serializer::serializePrimitive(Serializer* serializer, + data::stream::ConsistentOutputStream* stream, + const oatpp::Void& polymorph){ + if (polymorph) { + std::string format; + if (!serializer->m_context->info.format.empty()) { + format = serializer->m_context->info.format; + } + else if (!serializer->m_config->floatStringFormat->empty()) { + format = serializer->m_config->floatStringFormat; + } + stream->writeAsString(*static_cast(polymorph.get()), + format.c_str()); + } + else { + stream->writeSimple("null", 4); + } +} + +template<> +void Serializer::serializePrimitive(Serializer* serializer, + data::stream::ConsistentOutputStream* stream, + const oatpp::Void& polymorph) { + if (polymorph) { + std::string format; + if (!serializer->m_context->info.format.empty()) { + format = serializer->m_context->info.format; + } + else if (!serializer->m_config->floatStringFormat->empty()) { + format = serializer->m_config->floatStringFormat; + } + stream->writeAsString(*static_cast(polymorph.get()), + format.c_str()); + } + else { + 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('\"'); @@ -228,6 +269,7 @@ void Serializer::serializeObject(Serializer* serializer, auto fields = dispatcher->getProperties()->getList(); auto object = static_cast(polymorph.get()); auto config = serializer->m_config; + auto &context = serializer->m_context; for (auto const& field : fields) { @@ -243,17 +285,9 @@ void Serializer::serializeObject(Serializer* serializer, (first) ? first = false : stream->writeSimple(",", 1); serializeString(stream, field->name, std::strlen(field->name), serializer->m_config->escapeFlags); stream->writeSimple(":", 1); - auto streamFloatFormat = stream->floatFormat; - if (config->floatStringFormat != OATPP_FLOAT_STRING_FORMAT) { - stream->floatFormat = config->floatStringFormat; - } - if (field->info.format != OATPP_FLOAT_STRING_FORMAT) { - stream->floatFormat = field->info.format; - } + + context->info = field->info; serializer->serialize(stream, value); - if (stream->floatFormat != streamFloatFormat) { - stream->floatFormat = streamFloatFormat; - } } } @@ -286,8 +320,6 @@ void Serializer::serialize(data::stream::ConsistentOutputStream* stream, void Serializer::serializeToStream(data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph) { - if(m_config->floatStringFormat != stream->floatFormat) - stream->floatFormat = m_config->floatStringFormat; if(m_config->useBeautifier) { json::Beautifier beautifier(stream, " ", "\n"); serialize(&beautifier, polymorph); diff --git a/src/oatpp/parser/json/mapping/Serializer.hpp b/src/oatpp/parser/json/mapping/Serializer.hpp index db531dd5..b40bef74 100644 --- a/src/oatpp/parser/json/mapping/Serializer.hpp +++ b/src/oatpp/parser/json/mapping/Serializer.hpp @@ -116,9 +116,26 @@ public: /** * Format of float string. */ - oatpp::String floatStringFormat = OATPP_FLOAT_STRING_FORMAT; + oatpp::String floatStringFormat = ""; }; + +private: + /** + * Serializer context. + */ + class Context : public oatpp::base::Countable { + public: + /** + * Constructor. + */ + Context() + {} + public: + + data::mapping::type::BaseObject::Property::Info info; + }; + public: typedef void (*SerializerMethod)(Serializer*, data::stream::ConsistentOutputStream*, @@ -137,7 +154,7 @@ private: stream->writeSimple("null", 4); } } - + static void serializeString(oatpp::data::stream::ConsistentOutputStream* stream, const char* data, v_buff_size size, @@ -171,6 +188,7 @@ private: private: std::shared_ptr m_config; + std::unique_ptr m_context; std::vector m_methods; public: @@ -202,6 +220,16 @@ public: }; +template<> +void Serializer::serializePrimitive(Serializer* serializer, + data::stream::ConsistentOutputStream* stream, + const oatpp::Void& polymorph); + +template<> +void Serializer::serializePrimitive(Serializer* serializer, + data::stream::ConsistentOutputStream* stream, + const oatpp::Void& polymorph); + }}}} #endif /* oatpp_parser_json_mapping_Serializer_hpp */ diff --git a/test/oatpp/parser/json/mapping/FloatTest.cpp b/test/oatpp/parser/json/mapping/FloatTest.cpp index bb10928f..2230c7b3 100644 --- a/test/oatpp/parser/json/mapping/FloatTest.cpp +++ b/test/oatpp/parser/json/mapping/FloatTest.cpp @@ -54,19 +54,36 @@ class DTO_32_1 : public oatpp::DTO { class DTO_64_0 : public oatpp::DTO { - DTO_INIT(DTO_64_0, DTO) + DTO_INIT(DTO_64_0, DTO) - DTO_FIELD(Float64, f64); + DTO_FIELD(Float64, f64); }; class DTO_64_1 : public oatpp::DTO { - DTO_INIT(DTO_64_1, DTO) + DTO_INIT(DTO_64_1, DTO) - DTO_FIELD_INFO(f64) { - info->format = "%.2f"; - } - DTO_FIELD(Float64, f64); + 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) @@ -120,6 +137,18 @@ void FloatTest::onRun() { 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;