aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhrustyashko <hrustyashko@yandex-team.ru>2022-02-25 16:05:47 +0300
committerhrustyashko <hrustyashko@yandex-team.ru>2022-02-25 16:05:47 +0300
commit797beae740bb6bafe9fe620409af9f8af30548c1 (patch)
tree7753fff29c30e1cda904a0b82a631db33049bf79
parent338fc2631cd04be6d5fa5d72efec0cb3078c30c8 (diff)
downloadydb-797beae740bb6bafe9fe620409af9f8af30548c1.tar.gz
YQ-418 Дополнить политику конвертации в json новыми правилами
ref:6db01b780daa657314673fbc150eb7ae4150f957
-rw-r--r--ydb/library/yql/providers/common/codec/CMakeLists.txt1
-rw-r--r--ydb/library/yql/providers/common/codec/ya.make1
-rw-r--r--ydb/library/yql/providers/common/codec/yql_json_codec.cpp100
-rw-r--r--ydb/library/yql/providers/common/codec/yql_json_codec.h58
-rw-r--r--ydb/library/yql/providers/common/codec/yql_json_codec_ut.cpp145
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