diff options
author | hrustyashko <hrustyashko@yandex-team.ru> | 2022-02-25 16:05:47 +0300 |
---|---|---|
committer | hrustyashko <hrustyashko@yandex-team.ru> | 2022-02-25 16:05:47 +0300 |
commit | 797beae740bb6bafe9fe620409af9f8af30548c1 (patch) | |
tree | 7753fff29c30e1cda904a0b82a631db33049bf79 | |
parent | 338fc2631cd04be6d5fa5d72efec0cb3078c30c8 (diff) | |
download | ydb-797beae740bb6bafe9fe620409af9f8af30548c1.tar.gz |
YQ-418 Дополнить политику конвертации в json новыми правилами
ref:6db01b780daa657314673fbc150eb7ae4150f957
5 files changed, 229 insertions, 76 deletions
diff --git a/ydb/library/yql/providers/common/codec/CMakeLists.txt b/ydb/library/yql/providers/common/codec/CMakeLists.txt index 31abb052329..91ceeabbd8f 100644 --- a/ydb/library/yql/providers/common/codec/CMakeLists.txt +++ b/ydb/library/yql/providers/common/codec/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(providers-common-codec PUBLIC cpp-yson-node library-cpp-yson library-cpp-json + library-cpp-enumbitset tools-enum_parser-enum_serialization_runtime ) target_sources(providers-common-codec PRIVATE diff --git a/ydb/library/yql/providers/common/codec/ya.make b/ydb/library/yql/providers/common/codec/ya.make index 0c44e3fdc2b..161c13682bb 100644 --- a/ydb/library/yql/providers/common/codec/ya.make +++ b/ydb/library/yql/providers/common/codec/ya.make @@ -23,6 +23,7 @@ PEERDIR( library/cpp/yson/node library/cpp/yson library/cpp/json + library/cpp/enumbitset ) YQL_LAST_ABI_VERSION() diff --git a/ydb/library/yql/providers/common/codec/yql_json_codec.cpp b/ydb/library/yql/providers/common/codec/yql_json_codec.cpp index cad700b4495..300fdf55d47 100644 --- a/ydb/library/yql/providers/common/codec/yql_json_codec.cpp +++ b/ydb/library/yql/providers/common/codec/yql_json_codec.cpp @@ -8,8 +8,11 @@ #include <library/cpp/string_utils/base64/base64.h> #include <util/string/join.h> +#include <cmath> + namespace NYql { namespace NCommon { +namespace NJsonCodec { using namespace NKikimr; using namespace NKikimr::NMiniKQL; @@ -34,13 +37,13 @@ TJsonWriterConfig MakeJsonConfig() { config.SortKeys = false; config.ValidateUtf8 = false; config.DontEscapeStrings = true; - config.WriteNanAsString = false; + config.WriteNanAsString = true; return config; } void WriteValueToJson(TJsonWriter& writer, const NKikimr::NUdf::TUnboxedValuePod& value, - NKikimr::NMiniKQL::TType* type, std::set<EValueConvertPolicy> convertPolicy) { + NKikimr::NMiniKQL::TType* type, TValueConvertPolicy convertPolicy) { switch (type->GetKind()) { case TType::EKind::Void: @@ -54,12 +57,18 @@ void WriteValueToJson(TJsonWriter& writer, const NKikimr::NUdf::TUnboxedValuePod break; case TType::EKind::Data: { - bool numberToStr = convertPolicy.contains(EValueConvertPolicy::WriteNumberString); + bool numberToStr = convertPolicy.Test(EValueConvertPolicy::NUMBER_AS_STRING); auto dataType = AS_TYPE(TDataType, type); switch (dataType->GetSchemeType()) { - case NUdf::TDataType<bool>::Id: - writer.Write(value.Get<bool>()); + case NUdf::TDataType<bool>::Id: { + auto boolValue = value.Get<bool>(); + if (convertPolicy.Test(EValueConvertPolicy::BOOL_AS_STRING)) { + writer.Write(boolValue ? "true" : "false"); + } else { + writer.Write(boolValue); + } break; + } case NUdf::TDataType<i32>::Id: { auto number = value.Get<i32>(); if (numberToStr) { @@ -82,7 +91,7 @@ void WriteValueToJson(TJsonWriter& writer, const NKikimr::NUdf::TUnboxedValuePod auto number = value.Get<i64>(); if (numberToStr) { writer.Write(ToString(number)); - } else if (convertPolicy.contains(EValueConvertPolicy::WriteUnsafeNumberString)) { + } else if (convertPolicy.Test(EValueConvertPolicy::UNSAFE_NUMBER_AS_STRING)) { if (number > MAX_JS_SAFE_INTEGER || number < MIN_JS_SAFE_INTEGER) { writer.Write(ToString(number)); } else { @@ -97,7 +106,7 @@ void WriteValueToJson(TJsonWriter& writer, const NKikimr::NUdf::TUnboxedValuePod auto number = value.Get<ui64>(); if (numberToStr) { writer.Write(ToString(number)); - } else if (convertPolicy.contains(EValueConvertPolicy::WriteUnsafeNumberString)) { + } else if (convertPolicy.Test(EValueConvertPolicy::UNSAFE_NUMBER_AS_STRING)) { if (number > MAX_JS_SAFE_INTEGER) { writer.Write(ToString(number)); } else { @@ -144,25 +153,37 @@ void WriteValueToJson(TJsonWriter& writer, const NKikimr::NUdf::TUnboxedValuePod } break; } - case NUdf::TDataType<float>::Id: + case NUdf::TDataType<float>::Id: { + auto floatValue = value.Get<float>(); + bool isUndetermined = std::isnan(floatValue) || std::isinf(floatValue); + if (convertPolicy.Test(EValueConvertPolicy::DISALLOW_NaN) && isUndetermined) { + YQL_ENSURE(false, "NaN and Inf aren't allowed"); + } + if (numberToStr) { - TString number = FloatToString(value.Get<float>(), FLOAT_MODE, FLOAT_N_DIGITS); + TString number = FloatToString(floatValue, FLOAT_MODE, FLOAT_N_DIGITS); writer.Write(number); } else { - writer.Write(value.Get<float>()); + writer.Write(floatValue); } break; - case NUdf::TDataType<double>::Id: + } + case NUdf::TDataType<double>::Id: { + auto doubleValue = value.Get<double>(); + bool isUndetermined = std::isnan(doubleValue) || std::isinf(doubleValue); + if (convertPolicy.Test(EValueConvertPolicy::DISALLOW_NaN) && isUndetermined) { + YQL_ENSURE(false, "NaN and Inf aren't allowed"); + } + if (numberToStr) { - TString number = FloatToString(value.Get<double>(), FLOAT_MODE, DOUBLE_N_DIGITS); + TString number = FloatToString(doubleValue, FLOAT_MODE, DOUBLE_N_DIGITS); writer.Write(number); } else { - writer.Write(value.Get<double>()); + writer.Write(doubleValue); } break; + } case NUdf::TDataType<NUdf::TJson>::Id: - writer.UnsafeWrite(value.AsStringRef()); - break; case NUdf::TDataType<NUdf::TUtf8>::Id: writer.Write(value.AsStringRef()); break; @@ -225,9 +246,7 @@ void WriteValueToJson(TJsonWriter& writer, const NKikimr::NUdf::TUnboxedValuePod case TType::EKind::Optional: { writer.OpenArray(); - if (!value.GetOptionalValue()) { - writer.WriteNull(); - } else { + if (value.GetOptionalValue()) { auto optionalType = AS_TYPE(TOptionalType, type); WriteValueToJson(writer, value.GetOptionalValue(), optionalType->GetItemType(), convertPolicy); } @@ -239,11 +258,18 @@ void WriteValueToJson(TJsonWriter& writer, const NKikimr::NUdf::TUnboxedValuePod writer.OpenArray(); auto dictType = AS_TYPE(TDictType, type); const auto it = value.GetDictIterator(); - for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) { - writer.OpenArray(); - WriteValueToJson(writer, key, dictType->GetKeyType(), convertPolicy); - WriteValueToJson(writer, payload, dictType->GetPayloadType(), convertPolicy); - writer.CloseArray(); + // is Set<> + if (dictType->GetPayloadType()->GetKind() == TType::EKind::Void) { + for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) { + WriteValueToJson(writer, key, dictType->GetKeyType(), convertPolicy); + } + } else { + for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) { + writer.OpenArray(); + WriteValueToJson(writer, key, dictType->GetKeyType(), convertPolicy); + WriteValueToJson(writer, payload, dictType->GetPayloadType(), convertPolicy); + writer.CloseArray(); + } } writer.CloseArray(); break; @@ -262,15 +288,15 @@ void WriteValueToJson(TJsonWriter& writer, const NKikimr::NUdf::TUnboxedValuePod { writer.OpenArray(); auto index = value.GetVariantIndex(); - writer.Write(index); - auto underlyingType = AS_TYPE(TVariantType, type)->GetUnderlyingType(); if (underlyingType->IsTuple()) { + writer.Write(index); WriteValueToJson(writer, value.GetVariantItem(), AS_TYPE(TTupleType, underlyingType)->GetElementType(index), convertPolicy); } else { - WriteValueToJson(writer, value.GetVariantItem(), - AS_TYPE(TStructType, underlyingType)->GetMemberType(index), convertPolicy); + auto structType = AS_TYPE(TStructType, underlyingType); + writer.Write(structType->GetMemberName(index)); + WriteValueToJson(writer, value.GetVariantItem(), structType->GetMemberType(index), convertPolicy); } writer.CloseArray(); break; @@ -351,11 +377,16 @@ NKikimr::NUdf::TUnboxedValue ReadJsonValue(TJsonValue& json, NKikimr::NMiniKQL:: } case TType::EKind::Optional: { - if (json.IsNull()) { - return NUdf::TUnboxedValuePod(); + YQL_ENSURE(json.IsArray() + && json.GetArray().size() <= 1 + , "Unexpected json type (expected array no more than one element, but got " << jsonType << ")"); + + auto array = json.GetArray(); + if (array.empty()) { + return NUdf::TUnboxedValuePod().MakeOptional(); } auto optionalType = AS_TYPE(TOptionalType, type); - auto value = ReadJsonValue(json, optionalType->GetItemType(), holderFactory); + auto value = ReadJsonValue(array.front(), optionalType->GetItemType(), holderFactory); return value.Release().MakeOptional(); } case TType::EKind::Data: @@ -444,15 +475,6 @@ NKikimr::NUdf::TUnboxedValue ReadJsonValue(TJsonValue& json, NKikimr::NMiniKQL:: return NKikimr::NUdf::TUnboxedValuePod(); } -NKikimr::NUdf::TUnboxedValue ReadJsonValue(IInputStream* in, NKikimr::NMiniKQL::TType* type, - const NMiniKQL::THolderFactory& holderFactory) -{ - TJsonValue json; - if (!ReadJsonTree(in, &json, false)) { - YQL_ENSURE(false, "Error parse json"); - } - return ReadJsonValue(json, type, holderFactory); } - } } diff --git a/ydb/library/yql/providers/common/codec/yql_json_codec.h b/ydb/library/yql/providers/common/codec/yql_json_codec.h index e541c3eef24..23d917290e3 100644 --- a/ydb/library/yql/providers/common/codec/yql_json_codec.h +++ b/ydb/library/yql/providers/common/codec/yql_json_codec.h @@ -4,27 +4,59 @@ #include <library/cpp/json/json_reader.h> #include <ydb/library/yql/minikql/mkql_node.h> #include <ydb/library/yql/minikql/computation/mkql_computation_node_holders.h> - -using namespace NKikimr; +#include <library/cpp/enumbitset/enumbitset.h> namespace NYql { namespace NCommon { +namespace NJsonCodec { + +using namespace NKikimr; -enum class EValueConvertPolicy : ui8 { - WriteNumberString = 1, - WriteUnsafeNumberString = 2, - //WriteNumberAsString = 4, - //WriteNumberAsString = 8, +enum EValueConvertPolicy { + CONVERT_POLICY_BEGIN, + NUMBER_AS_STRING = CONVERT_POLICY_BEGIN, + UNSAFE_NUMBER_AS_STRING, + BOOL_AS_STRING, + DISALLOW_NaN, + CONVERT_POLICY_END }; +using TValueConvertPolicy = TEnumBitSet<EValueConvertPolicy, EValueConvertPolicy::CONVERT_POLICY_BEGIN, EValueConvertPolicy::CONVERT_POLICY_END>; + +class DefaultPolicy { +public: + static DefaultPolicy& getInstance() { + static DefaultPolicy instance; + return instance; + } + +private: + DefaultPolicy() {} + +public: + DefaultPolicy(DefaultPolicy &) = delete; + void operator=(const DefaultPolicy &) = delete; + + TValueConvertPolicy CloudFunction() const { + return CloudFunctionPolicy; + } + + TValueConvertPolicy Export() const { + return ExportPolicy; + } + +private: + TValueConvertPolicy CloudFunctionPolicy = TValueConvertPolicy{NUMBER_AS_STRING, BOOL_AS_STRING}; + TValueConvertPolicy ExportPolicy = TValueConvertPolicy{DISALLOW_NaN}; +}; + + NJson::TJsonWriterConfig MakeJsonConfig(); void WriteValueToJson(NJson::TJsonWriter& writer, const NUdf::TUnboxedValuePod& value, - NMiniKQL::TType* type, std::set<EValueConvertPolicy> convertPolicy = {}); + NMiniKQL::TType* type, TValueConvertPolicy convertPolicy = {}); NUdf::TUnboxedValue ReadJsonValue(NJson::TJsonValue& json, NMiniKQL::TType* type, const NMiniKQL::THolderFactory& holderFactory); - -NUdf::TUnboxedValue ReadJsonValue(IInputStream* in, NMiniKQL::TType* type, const NMiniKQL::THolderFactory& holderFactory); - -} -} +} // NJsonCodec +} // NCommon +} // NYql diff --git a/ydb/library/yql/providers/common/codec/yql_json_codec_ut.cpp b/ydb/library/yql/providers/common/codec/yql_json_codec_ut.cpp index 3a6fed2953a..1d89b7c705a 100644 --- a/ydb/library/yql/providers/common/codec/yql_json_codec_ut.cpp +++ b/ydb/library/yql/providers/common/codec/yql_json_codec_ut.cpp @@ -2,12 +2,15 @@ #include <ydb/library/yql/minikql/computation/mkql_value_builder.h> #include <ydb/library/yql/minikql/mkql_type_ops.h> +#include <ydb/library/yql/utils/yql_panic.h> #include <library/cpp/testing/unittest/registar.h> +#include <library/cpp/json/json_reader.h> #include <util/string/cast.h> namespace NYql { namespace NCommon { +namespace NJsonCodec { using namespace NYql::NCommon; using namespace NKikimr; @@ -33,10 +36,10 @@ struct TTestContext { } }; -TString WriteValueToExportJsonStr(const NUdf::TUnboxedValuePod& value, NMiniKQL::TType* type) { +TString WriteValueToExportJsonStr(const NUdf::TUnboxedValuePod& value, NMiniKQL::TType* type, TValueConvertPolicy policy = {}) { TStringStream out; NJson::TJsonWriter jsonWriter(&out, MakeJsonConfig()); - WriteValueToJson(jsonWriter,value, type, {}); + WriteValueToJson(jsonWriter,value, type, policy); jsonWriter.Flush(); return out.Str(); } @@ -44,10 +47,21 @@ TString WriteValueToExportJsonStr(const NUdf::TUnboxedValuePod& value, NMiniKQL: TString WriteValueToFuncJsonStr(const NUdf::TUnboxedValuePod& value, NMiniKQL::TType* type) { TStringStream out; NJson::TJsonWriter jsonWriter(&out, MakeJsonConfig()); - WriteValueToJson(jsonWriter,value, type, {EValueConvertPolicy::WriteNumberString}); + TValueConvertPolicy policy; + policy.Set(EValueConvertPolicy::NUMBER_AS_STRING); + WriteValueToJson(jsonWriter,value, type, policy); jsonWriter.Flush(); return out.Str(); } + +NUdf::TUnboxedValue ReadJsonStrValue(IInputStream* in, NMiniKQL::TType* type, const NMiniKQL::THolderFactory& holderFactory) +{ + NJson::TJsonValue json; + if (!NJson::ReadJsonTree(in, &json, false)) { + YQL_ENSURE(false, "Error parse json"); + } + return ReadJsonValue(json, type, holderFactory); +} } Y_UNIT_TEST_SUITE(SerializeVoid) { @@ -72,6 +86,14 @@ Y_UNIT_TEST_SUITE(SerializeBool) { auto json2 = WriteValueToFuncJsonStr(NUdf::TUnboxedValuePod(false), type); UNIT_ASSERT_VALUES_EQUAL(json2, "false"); } + + Y_UNIT_TEST(StringBool) { + TTestContext ctx; + auto type = TDataType::Create(NUdf::TDataType<bool>::Id, ctx.TypeEnv); + TValueConvertPolicy policy{EValueConvertPolicy::BOOL_AS_STRING}; + auto json = WriteValueToExportJsonStr(NUdf::TUnboxedValuePod(true), type, policy); + UNIT_ASSERT_VALUES_EQUAL(json, "\"true\""); + } } Y_UNIT_TEST_SUITE(SerializeUuid) { @@ -90,7 +112,7 @@ Y_UNIT_TEST_SUITE(SerializeJson) { auto type = TDataType::Create(NUdf::TDataType<NUdf::TJson>::Id, ctx.TypeEnv); auto value = ctx.Vb.NewString("\"some string с русскими йЁ\""); auto json = WriteValueToFuncJsonStr(value, type); - UNIT_ASSERT_VALUES_EQUAL(json, "\"some string с русскими йЁ\""); + UNIT_ASSERT_VALUES_EQUAL(json, "\"\"some string с русскими йЁ\"\""); } Y_UNIT_TEST(ComplexJson) { @@ -107,7 +129,7 @@ Y_UNIT_TEST_SUITE(SerializeJson) { items[1] = NUdf::TUnboxedValuePod(ui32(73)); auto json = WriteValueToExportJsonStr(value, type); - UNIT_ASSERT_VALUES_EQUAL(json, "{\"X\":{\"a\":500,\"b\":[1,2,3]},\"Y\":73}"); + UNIT_ASSERT_VALUES_EQUAL(json, "{\"X\":\"{\"a\":500,\"b\":[1,2,3]}\",\"Y\":73}"); } } @@ -196,6 +218,20 @@ Y_UNIT_TEST_SUITE(SerializeContainers) { UNIT_ASSERT_VALUES_EQUAL(json, "[[\"key_b\",-500],[\"key_a\",781]]"); } + Y_UNIT_TEST(SetType) { + TTestContext ctx; + auto type = TDictType::Create( + TDataType::Create(NUdf::TDataType<NUdf::TUtf8>::Id, ctx.TypeEnv), + ctx.TypeEnv.GetTypeOfVoid(), + ctx.TypeEnv + ); + auto dictBuilder = ctx.Vb.NewDict(type, NUdf::TDictFlags::EDictKind::Hashed); + dictBuilder->Add(ctx.Vb.NewString("key_a"), NUdf::TUnboxedValuePod()); + dictBuilder->Add(ctx.Vb.NewString("key_b"), NUdf::TUnboxedValuePod()); + auto json = WriteValueToExportJsonStr(dictBuilder->Build(), type); + UNIT_ASSERT_VALUES_EQUAL(json, "[\"key_b\",\"key_a\"]"); + } + Y_UNIT_TEST(Tagged) { TTestContext ctx; auto type = TTaggedType::Create(TDataType::Create(NUdf::TDataType<NUdf::TDatetime>::Id, ctx.TypeEnv), @@ -236,11 +272,11 @@ Y_UNIT_TEST_SUITE(SerializeContainers) { auto value0 = ctx.HolderFactory.CreateVariantHolder(NUdf::TUnboxedValuePod(true), 0); auto json0 = WriteValueToExportJsonStr(value0, type); - UNIT_ASSERT_VALUES_EQUAL(json0, "[0,true]"); + UNIT_ASSERT_VALUES_EQUAL(json0, "[\"A\",true]"); auto value1 = ctx.HolderFactory.CreateVariantHolder(NUdf::TUnboxedValuePod(200), 1); auto json1 = WriteValueToExportJsonStr(value1, type); - UNIT_ASSERT_VALUES_EQUAL(json1, "[1,200]"); + UNIT_ASSERT_VALUES_EQUAL(json1, "[\"B\",200]"); } Y_UNIT_TEST(StructType) { @@ -276,15 +312,25 @@ Y_UNIT_TEST_SUITE(SerializeOptional) { UNIT_ASSERT_VALUES_EQUAL(json, "[[0,67,4]]"); } + Y_UNIT_TEST(SimpleJust) { + TTestContext ctx; + auto elementType = TDataType::Create(NUdf::TDataType<ui32>::Id, ctx.TypeEnv); + TType* type = TOptionalType::Create(elementType, ctx.TypeEnv); + auto value = NUdf::TUnboxedValuePod(ui32(6641)).MakeOptional(); + auto json = WriteValueToExportJsonStr(value, type); + UNIT_ASSERT_VALUES_EQUAL(json, "[6641]"); + } + Y_UNIT_TEST(NothingOptional) { TTestContext ctx; auto value = NUdf::TUnboxedValuePod().MakeOptional(); auto elementType = TListType::Create(TDataType::Create(NUdf::TDataType<ui8>::Id, ctx.TypeEnv), ctx.TypeEnv); auto type = TOptionalType::Create(elementType, ctx.TypeEnv); auto json = WriteValueToFuncJsonStr(value, type); - UNIT_ASSERT_VALUES_EQUAL(json, "[null]"); + UNIT_ASSERT_VALUES_EQUAL(json, "[]"); } + Y_UNIT_TEST(SeveralOptionals) { TTestContext ctx; auto elementType = TDataType::Create(NUdf::TDataType<ui8>::Id, ctx.TypeEnv); @@ -294,7 +340,7 @@ Y_UNIT_TEST_SUITE(SerializeOptional) { auto value1 = NUdf::TUnboxedValuePod().MakeOptional().MakeOptional().MakeOptional(); auto json1 = WriteValueToFuncJsonStr(value1, type); - UNIT_ASSERT_VALUES_EQUAL(json1, "[[[null]]]"); + UNIT_ASSERT_VALUES_EQUAL(json1, "[[[]]]"); auto value2 = NUdf::TUnboxedValuePod(ui8(120)).MakeOptional().MakeOptional().MakeOptional(); auto json2 = WriteValueToExportJsonStr(value2, type); @@ -390,8 +436,58 @@ Y_UNIT_TEST_SUITE(SerializeNumbers) { auto json1 = WriteValueToFuncJsonStr(value, type); UNIT_ASSERT_VALUES_EQUAL(json1, "\"788765.43\""); } + + Y_UNIT_TEST(InfValue) { + TTestContext ctx; + auto value = NUdf::TUnboxedValuePod(std::numeric_limits<float>::infinity()); + auto json1 = WriteValueToExportJsonStr(value, TDataType::Create(NUdf::TDataType<float>::Id, ctx.TypeEnv)); + UNIT_ASSERT_VALUES_EQUAL(json1, "\"inf\""); + + auto json2 = WriteValueToFuncJsonStr(value, TDataType::Create(NUdf::TDataType<float>::Id, ctx.TypeEnv)); + UNIT_ASSERT_VALUES_EQUAL(json2, "\"inf\""); + } + + Y_UNIT_TEST(NaNValue) { + TTestContext ctx; + auto value = NUdf::TUnboxedValuePod(std::numeric_limits<double>::quiet_NaN()); + auto json1 = WriteValueToExportJsonStr(value, TDataType::Create(NUdf::TDataType<double>::Id, ctx.TypeEnv)); + UNIT_ASSERT_VALUES_EQUAL(json1, "\"nan\""); + + auto json2 = WriteValueToFuncJsonStr(value, TDataType::Create(NUdf::TDataType<double>::Id, ctx.TypeEnv)); + UNIT_ASSERT_VALUES_EQUAL(json2, "\"nan\""); + } + + Y_UNIT_TEST(DisallowNaN) { + TTestContext ctx; + auto valueNan = NUdf::TUnboxedValuePod(std::numeric_limits<float>::quiet_NaN()); + TValueConvertPolicy policy{EValueConvertPolicy::DISALLOW_NaN}; + + UNIT_ASSERT_EXCEPTION_CONTAINS( + WriteValueToExportJsonStr(valueNan, TDataType::Create(NUdf::TDataType<float>::Id, ctx.TypeEnv), policy), + yexception, + "NaN and Inf aren't allowed" + ); + + auto valueInf = NUdf::TUnboxedValuePod(std::numeric_limits<double>::infinity()); + UNIT_ASSERT_EXCEPTION_CONTAINS( + WriteValueToExportJsonStr(valueInf, TDataType::Create(NUdf::TDataType<double>::Id, ctx.TypeEnv), policy), + yexception, + "NaN and Inf aren't allowed" + ); + } } +Y_UNIT_TEST_SUITE(DefaultPolicy) { + Y_UNIT_TEST(CloudFunction) { + TTestContext ctx; + auto value = NUdf::TUnboxedValuePod(i64(540138)); + auto policy = DefaultPolicy::getInstance().CloudFunction(); + auto json = WriteValueToExportJsonStr(value, TDataType::Create(NUdf::TDataType<i64>::Id, ctx.TypeEnv), policy); + UNIT_ASSERT_VALUES_EQUAL(json, "\"540138\""); + } +} + + Y_UNIT_TEST_SUITE(DeserializeNumbers) { #define TEST_DESERIALIZE_NUMBER_TYPE(type, wideType) \ @@ -400,18 +496,18 @@ Y_UNIT_TEST_SUITE(DeserializeNumbers) { \ TStringStream maxJson; \ maxJson << ToString(std::numeric_limits<type>::max()); \ - auto maxValue = ReadJsonValue(&maxJson, TDataType::Create(NUdf::TDataType<type>::Id, ctx.TypeEnv), ctx.HolderFactory); \ + auto maxValue = ReadJsonStrValue(&maxJson, TDataType::Create(NUdf::TDataType<type>::Id, ctx.TypeEnv), ctx.HolderFactory); \ UNIT_ASSERT_VALUES_EQUAL(maxValue.Get<type>(), std::numeric_limits<type>::max()); \ \ TStringStream minJson; \ minJson << ToString(std::numeric_limits<type>::min()); \ - auto minValue = ReadJsonValue(&minJson, TDataType::Create(NUdf::TDataType<type>::Id, ctx.TypeEnv), ctx.HolderFactory); \ + auto minValue = ReadJsonStrValue(&minJson, TDataType::Create(NUdf::TDataType<type>::Id, ctx.TypeEnv), ctx.HolderFactory); \ UNIT_ASSERT_VALUES_EQUAL(minValue.Get<type>(), std::numeric_limits<type>::min()); \ \ TStringStream exceededJson; \ exceededJson << ToString(wideType(std::numeric_limits<type>::max() + wideType(1))); \ UNIT_ASSERT_EXCEPTION_CONTAINS( \ - ReadJsonValue(&exceededJson, TDataType::Create(NUdf::TDataType<type>::Id, ctx.TypeEnv), ctx.HolderFactory), \ + ReadJsonStrValue(&exceededJson, TDataType::Create(NUdf::TDataType<type>::Id, ctx.TypeEnv), ctx.HolderFactory), \ yexception, \ "Exceeded the range" \ ); \ @@ -431,13 +527,13 @@ Y_UNIT_TEST_SUITE(DeserializeNumbers) { TTestContext ctx; TStringStream json; json << "0.0431"; - auto value = ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<float>::Id, ctx.TypeEnv), ctx.HolderFactory); + auto value = ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<float>::Id, ctx.TypeEnv), ctx.HolderFactory); UNIT_ASSERT_VALUES_EQUAL(value.Get<float>(), 0.0431f); TStringStream exceededJson; exceededJson << ToString(std::numeric_limits<double>::max()); UNIT_ASSERT_EXCEPTION_CONTAINS( - ReadJsonValue(&exceededJson, TDataType::Create(NUdf::TDataType<float>::Id, ctx.TypeEnv), ctx.HolderFactory), + ReadJsonStrValue(&exceededJson, TDataType::Create(NUdf::TDataType<float>::Id, ctx.TypeEnv), ctx.HolderFactory), yexception, "Exceeded the range" ); @@ -447,7 +543,7 @@ Y_UNIT_TEST_SUITE(DeserializeNumbers) { TTestContext ctx; TStringStream json; json << "1766718243"; - auto value = ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<float>::Id, ctx.TypeEnv), ctx.HolderFactory); + auto value = ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<float>::Id, ctx.TypeEnv), ctx.HolderFactory); UNIT_ASSERT_VALUES_EQUAL(value.Get<float>(), 1766718243.0f); } @@ -455,7 +551,7 @@ Y_UNIT_TEST_SUITE(DeserializeNumbers) { TTestContext ctx; TStringStream json; json << "7773.13"; - auto value = ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<double>::Id, ctx.TypeEnv), ctx.HolderFactory); + auto value = ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<double>::Id, ctx.TypeEnv), ctx.HolderFactory); UNIT_ASSERT_VALUES_EQUAL(value.Get<double>(), 7773.13); } @@ -463,7 +559,7 @@ Y_UNIT_TEST_SUITE(DeserializeNumbers) { TTestContext ctx; TStringStream json; json << "-667319001"; - auto value = ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<double>::Id, ctx.TypeEnv), ctx.HolderFactory); + auto value = ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<double>::Id, ctx.TypeEnv), ctx.HolderFactory); UNIT_ASSERT_VALUES_EQUAL(value.Get<double>(), -667319001.0l); } @@ -497,7 +593,7 @@ Y_UNIT_TEST_SUITE(DeserializeStringTypes) { TTestContext ctx; TStringStream json; json << "\"fffaaae423\""; - auto value = ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TUtf8>::Id, ctx.TypeEnv), ctx.HolderFactory); + auto value = ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TUtf8>::Id, ctx.TypeEnv), ctx.HolderFactory); UNIT_ASSERT_VALUES_EQUAL(TStringBuf("fffaaae423"), TStringBuf(value.AsStringRef())); } } @@ -570,7 +666,7 @@ Y_UNIT_TEST_SUITE(DeserializeDateTypes) { TTestContext ctx; TStringStream json; json << "\"2020-09-11\""; - auto value = ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TDate>::Id, ctx.TypeEnv), ctx.HolderFactory); + auto value = ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TDate>::Id, ctx.TypeEnv), ctx.HolderFactory); ui16 date; ctx.Vb.MakeDate(2020, 9, 11, date); UNIT_ASSERT_VALUES_EQUAL(value.Get<ui16>(), date); @@ -580,7 +676,7 @@ Y_UNIT_TEST_SUITE(DeserializeDateTypes) { TTestContext ctx; TStringStream json; json << "\"2021-07-14T00:00:43Z\""; - auto value = ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TDatetime>::Id, ctx.TypeEnv), ctx.HolderFactory); + auto value = ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TDatetime>::Id, ctx.TypeEnv), ctx.HolderFactory); ui32 datetime; ctx.Vb.MakeDatetime(2021, 7, 14, 0, 0, 43, datetime); UNIT_ASSERT_VALUES_EQUAL(value.Get<ui32>(), datetime); @@ -590,7 +686,7 @@ Y_UNIT_TEST_SUITE(DeserializeDateTypes) { TTestContext ctx; TStringStream json; json << "\"2020-09-11,Europe/Moscow\""; // timeZoneId == 1 - auto value = ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TTzDate>::Id, ctx.TypeEnv), ctx.HolderFactory); + auto value = ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TTzDate>::Id, ctx.TypeEnv), ctx.HolderFactory); ui16 date; ctx.Vb.MakeDate(2020, 9, 10, date); UNIT_ASSERT_VALUES_EQUAL(value.GetTimezoneId(), 1); @@ -601,7 +697,7 @@ Y_UNIT_TEST_SUITE(DeserializeDateTypes) { TTestContext ctx; TStringStream json; json << "\"2020-09-11T01:11:05,Europe/Moscow\""; // timeZoneId == 1 - auto value = ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TTzDatetime>::Id, ctx.TypeEnv), ctx.HolderFactory); + auto value = ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TTzDatetime>::Id, ctx.TypeEnv), ctx.HolderFactory); ui32 datetime; ctx.Vb.MakeDatetime(2020, 9, 11, 1, 11, 5, datetime, 1); UNIT_ASSERT_VALUES_EQUAL(value.GetTimezoneId(), 1); @@ -613,7 +709,7 @@ Y_UNIT_TEST_SUITE(DeserializeDateTypes) { TStringStream json; json << "[\"2020-22-12\"]"; UNIT_ASSERT_EXCEPTION_CONTAINS( - ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TDate>::Id, ctx.TypeEnv), ctx.HolderFactory), + ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TDate>::Id, ctx.TypeEnv), ctx.HolderFactory), yexception, "Unexpected json type (expected string" ); @@ -624,7 +720,7 @@ Y_UNIT_TEST_SUITE(DeserializeDateTypes) { TStringStream json; json << "\"2020-18-43\""; UNIT_ASSERT_EXCEPTION_CONTAINS( - ReadJsonValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TDate>::Id, ctx.TypeEnv), ctx.HolderFactory), + ReadJsonStrValue(&json, TDataType::Create(NUdf::TDataType<NUdf::TDate>::Id, ctx.TypeEnv), ctx.HolderFactory), yexception, "Invalid date format" ); @@ -633,4 +729,5 @@ Y_UNIT_TEST_SUITE(DeserializeDateTypes) { } // namespace } // namespace +} // namespace |