yql_json_codec.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. #include "yql_json_codec.h"
  2. #include <yql/essentials/minikql/mkql_node_cast.h>
  3. #include <yql/essentials/minikql/mkql_type_ops.h>
  4. #include <yql/essentials/minikql/mkql_string_util.h>
  5. #include <yql/essentials/utils/yql_panic.h>
  6. #include <library/cpp/string_utils/base64/base64.h>
  7. #include <util/string/join.h>
  8. #include <cmath>
  9. namespace NYql {
  10. namespace NCommon {
  11. namespace NJsonCodec {
  12. using namespace NKikimr;
  13. using namespace NKikimr::NMiniKQL;
  14. using namespace NJson;
  15. namespace {
  16. constexpr i64 MAX_JS_SAFE_INTEGER = 9007199254740991; // 2^53 - 1; JavaScript Number.MAX_SAFE_INTEGER
  17. constexpr i64 MIN_JS_SAFE_INTEGER = -9007199254740991; // -(2^53 - 1); JavaScript Number.MIN_SAFE_INTEGER
  18. constexpr i8 DOUBLE_N_DIGITS = std::numeric_limits<double>::max_digits10;
  19. constexpr i8 FLOAT_N_DIGITS = std::numeric_limits<float>::max_digits10;
  20. constexpr EFloatToStringMode FLOAT_MODE = EFloatToStringMode::PREC_NDIGITS;
  21. }
  22. TJsonWriterConfig MakeJsonConfig() {
  23. TJsonWriterConfig config;
  24. config.DoubleNDigits = DOUBLE_N_DIGITS;
  25. config.FloatNDigits = FLOAT_N_DIGITS;
  26. config.FloatToStringMode = FLOAT_MODE;
  27. config.FormatOutput = false;
  28. config.SortKeys = false;
  29. config.ValidateUtf8 = false;
  30. config.DontEscapeStrings = false;
  31. config.WriteNanAsString = true;
  32. return config;
  33. }
  34. void WriteValueToJson(TJsonWriter& writer, const NKikimr::NUdf::TUnboxedValuePod& value,
  35. NKikimr::NMiniKQL::TType* type, TValueConvertPolicy convertPolicy) {
  36. switch (type->GetKind()) {
  37. case TType::EKind::Void:
  38. case TType::EKind::Null:
  39. writer.WriteNull();
  40. break;
  41. case TType::EKind::EmptyList:
  42. case TType::EKind::EmptyDict:
  43. writer.OpenArray();
  44. writer.CloseArray();
  45. break;
  46. case TType::EKind::Data:
  47. {
  48. bool numberToStr = convertPolicy.Test(EValueConvertPolicy::NUMBER_AS_STRING);
  49. auto dataType = AS_TYPE(TDataType, type);
  50. switch (dataType->GetSchemeType()) {
  51. case NUdf::TDataType<bool>::Id: {
  52. auto boolValue = value.Get<bool>();
  53. if (convertPolicy.Test(EValueConvertPolicy::BOOL_AS_STRING)) {
  54. writer.Write(boolValue ? "true" : "false");
  55. } else {
  56. writer.Write(boolValue);
  57. }
  58. break;
  59. }
  60. case NUdf::TDataType<i32>::Id: {
  61. auto number = value.Get<i32>();
  62. if (numberToStr) {
  63. writer.Write(ToString(number));
  64. } else {
  65. writer.Write(number);
  66. }
  67. break;
  68. }
  69. case NUdf::TDataType<ui32>::Id: {
  70. auto number = value.Get<ui32>();
  71. if (numberToStr) {
  72. writer.Write(ToString(number));
  73. } else {
  74. writer.Write(number);
  75. }
  76. break;
  77. }
  78. case NUdf::TDataType<i64>::Id: {
  79. auto number = value.Get<i64>();
  80. if (numberToStr) {
  81. writer.Write(ToString(number));
  82. } else if (convertPolicy.Test(EValueConvertPolicy::UNSAFE_NUMBER_AS_STRING)) {
  83. if (number > MAX_JS_SAFE_INTEGER || number < MIN_JS_SAFE_INTEGER) {
  84. writer.Write(ToString(number));
  85. } else {
  86. writer.Write(number);
  87. };
  88. } else {
  89. writer.Write(number);
  90. }
  91. break;
  92. }
  93. case NUdf::TDataType<ui64>::Id: {
  94. auto number = value.Get<ui64>();
  95. if (numberToStr) {
  96. writer.Write(ToString(number));
  97. } else if (convertPolicy.Test(EValueConvertPolicy::UNSAFE_NUMBER_AS_STRING)) {
  98. if (number > MAX_JS_SAFE_INTEGER) {
  99. writer.Write(ToString(number));
  100. } else {
  101. writer.Write(number);
  102. };
  103. } else {
  104. writer.Write(number);
  105. }
  106. break;
  107. }
  108. case NUdf::TDataType<ui8>::Id: {
  109. auto number = value.Get<ui8>();
  110. if (numberToStr) {
  111. writer.Write(ToString(number));
  112. } else {
  113. writer.Write(number);
  114. }
  115. break;
  116. }
  117. case NUdf::TDataType<i8>::Id: {
  118. auto number = value.Get<i8>();
  119. if (numberToStr) {
  120. writer.Write(ToString(number));
  121. } else {
  122. writer.Write(number);
  123. }
  124. break;
  125. }
  126. case NUdf::TDataType<ui16>::Id: {
  127. auto number = value.Get<ui16>();
  128. if (numberToStr) {
  129. writer.Write(ToString(number));
  130. } else {
  131. writer.Write(number);
  132. }
  133. break;
  134. }
  135. case NUdf::TDataType<i16>::Id: {
  136. auto number = value.Get<i16>();
  137. if (numberToStr) {
  138. writer.Write(ToString(number));
  139. } else {
  140. writer.Write(number);
  141. }
  142. break;
  143. }
  144. case NUdf::TDataType<float>::Id: {
  145. auto floatValue = value.Get<float>();
  146. bool isUndetermined = std::isnan(floatValue) || std::isinf(floatValue);
  147. if (convertPolicy.Test(EValueConvertPolicy::DISALLOW_NaN) && isUndetermined) {
  148. YQL_ENSURE(false, "NaN and Inf aren't allowed");
  149. }
  150. if (numberToStr) {
  151. TString number = FloatToString(floatValue, FLOAT_MODE, FLOAT_N_DIGITS);
  152. writer.Write(number);
  153. } else {
  154. writer.Write(floatValue);
  155. }
  156. break;
  157. }
  158. case NUdf::TDataType<double>::Id: {
  159. auto doubleValue = value.Get<double>();
  160. bool isUndetermined = std::isnan(doubleValue) || std::isinf(doubleValue);
  161. if (convertPolicy.Test(EValueConvertPolicy::DISALLOW_NaN) && isUndetermined) {
  162. YQL_ENSURE(false, "NaN and Inf aren't allowed");
  163. }
  164. if (numberToStr) {
  165. TString number = FloatToString(doubleValue, FLOAT_MODE, DOUBLE_N_DIGITS);
  166. writer.Write(number);
  167. } else {
  168. writer.Write(doubleValue);
  169. }
  170. break;
  171. }
  172. case NUdf::TDataType<NUdf::TJson>::Id:
  173. case NUdf::TDataType<NUdf::TUtf8>::Id:
  174. writer.Write(value.AsStringRef());
  175. break;
  176. case NUdf::TDataType<char*>::Id: {
  177. TString encoded = Base64Encode(value.AsStringRef());
  178. writer.Write(encoded);
  179. break;
  180. }
  181. case NUdf::TDataType<NUdf::TDecimal>::Id: {
  182. const auto params = static_cast<TDataDecimalType*>(type)->GetParams();
  183. const auto str = NDecimal::ToString(value.GetInt128(), params.first, params.second);
  184. const auto size = str ? std::strlen(str) : 0;
  185. writer.Write(TStringBuf(str, size));
  186. break;
  187. }
  188. case NUdf::TDataType<NUdf::TUuid>::Id:
  189. writer.Write(value.AsStringRef());
  190. break;
  191. case NUdf::TDataType<NUdf::TYson>::Id:
  192. case NUdf::TDataType<NUdf::TDyNumber>::Id:
  193. case NUdf::TDataType<NUdf::TDate>::Id:
  194. case NUdf::TDataType<NUdf::TDatetime>::Id:
  195. case NUdf::TDataType<NUdf::TTimestamp>::Id:
  196. case NUdf::TDataType<NUdf::TInterval>::Id:
  197. case NUdf::TDataType<NUdf::TTzDate>::Id:
  198. case NUdf::TDataType<NUdf::TTzDatetime>::Id:
  199. case NUdf::TDataType<NUdf::TTzTimestamp>::Id:
  200. case NUdf::TDataType<NUdf::TDate32>::Id:
  201. case NUdf::TDataType<NUdf::TDatetime64>::Id:
  202. case NUdf::TDataType<NUdf::TTimestamp64>::Id:
  203. case NUdf::TDataType<NUdf::TInterval64>::Id:
  204. case NUdf::TDataType<NUdf::TJsonDocument>::Id: {
  205. const NUdf::TUnboxedValue out(ValueToString(*dataType->GetDataSlot(), value));
  206. writer.Write(out.AsStringRef());
  207. break;
  208. }
  209. default:
  210. throw yexception() << "Unknown data type: " << dataType->GetSchemeType();
  211. }
  212. }
  213. break;
  214. case TType::EKind::Struct:
  215. {
  216. writer.OpenMap();
  217. auto structType = AS_TYPE(TStructType, type);
  218. for (ui32 i = 0, e = structType->GetMembersCount(); i < e; ++i) {
  219. writer.WriteKey(structType->GetMemberName(i));
  220. WriteValueToJson(writer, value.GetElement(i), structType->GetMemberType(i), convertPolicy);
  221. }
  222. writer.CloseMap();
  223. break;
  224. }
  225. case TType::EKind::List:
  226. {
  227. writer.OpenArray();
  228. auto listType = AS_TYPE(TListType, type);
  229. const auto it = value.GetListIterator();
  230. for (NUdf::TUnboxedValue item; it.Next(item);) {
  231. WriteValueToJson(writer, item, listType->GetItemType(), convertPolicy);
  232. }
  233. writer.CloseArray();
  234. break;
  235. }
  236. case TType::EKind::Optional:
  237. {
  238. writer.OpenArray();
  239. if (value) {
  240. auto optionalType = AS_TYPE(TOptionalType, type);
  241. WriteValueToJson(writer, value.GetOptionalValue(), optionalType->GetItemType(), convertPolicy);
  242. }
  243. writer.CloseArray();
  244. break;
  245. }
  246. case TType::EKind::Dict:
  247. {
  248. writer.OpenArray();
  249. auto dictType = AS_TYPE(TDictType, type);
  250. const auto it = value.GetDictIterator();
  251. // is Set<>
  252. if (dictType->GetPayloadType()->GetKind() == TType::EKind::Void) {
  253. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  254. WriteValueToJson(writer, key, dictType->GetKeyType(), convertPolicy);
  255. }
  256. } else {
  257. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  258. writer.OpenArray();
  259. WriteValueToJson(writer, key, dictType->GetKeyType(), convertPolicy);
  260. WriteValueToJson(writer, payload, dictType->GetPayloadType(), convertPolicy);
  261. writer.CloseArray();
  262. }
  263. }
  264. writer.CloseArray();
  265. break;
  266. }
  267. case TType::EKind::Tuple:
  268. {
  269. writer.OpenArray();
  270. auto tupleType = AS_TYPE(TTupleType, type);
  271. for (ui32 i = 0, e = tupleType->GetElementsCount(); i < e; ++i) {
  272. WriteValueToJson(writer, value.GetElement(i), tupleType->GetElementType(i), convertPolicy);
  273. }
  274. writer.CloseArray();
  275. break;
  276. }
  277. case TType::EKind::Variant:
  278. {
  279. writer.OpenArray();
  280. auto index = value.GetVariantIndex();
  281. auto underlyingType = AS_TYPE(TVariantType, type)->GetUnderlyingType();
  282. if (underlyingType->IsTuple()) {
  283. writer.Write(index);
  284. WriteValueToJson(writer, value.GetVariantItem(),
  285. AS_TYPE(TTupleType, underlyingType)->GetElementType(index), convertPolicy);
  286. } else {
  287. auto structType = AS_TYPE(TStructType, underlyingType);
  288. writer.Write(structType->GetMemberName(index));
  289. WriteValueToJson(writer, value.GetVariantItem(), structType->GetMemberType(index), convertPolicy);
  290. }
  291. writer.CloseArray();
  292. break;
  293. }
  294. case TType::EKind::Tagged:
  295. {
  296. auto underlyingType = AS_TYPE(TTaggedType, type)->GetBaseType();
  297. WriteValueToJson(writer, value, underlyingType, convertPolicy);
  298. break;
  299. }
  300. default:
  301. YQL_ENSURE(false, "doesn't known how to convert type " << type->GetKindAsStr() << " to JSON");
  302. }
  303. }
  304. NKikimr::NUdf::TUnboxedValue ReadJsonValue(TJsonValue& json, NKikimr::NMiniKQL::TType* type,
  305. const NMiniKQL::THolderFactory& holderFactory)
  306. {
  307. auto jsonType = json.GetType();
  308. switch (type->GetKind()) {
  309. case TType::EKind::Void:
  310. case TType::EKind::Null:
  311. YQL_ENSURE(json.IsNull(), "Unexpected json type (expected null value, but got type " << jsonType << ")");
  312. return NKikimr::NUdf::TUnboxedValuePod();
  313. case TType::EKind::EmptyList:
  314. case TType::EKind::EmptyDict:
  315. YQL_ENSURE(json.IsArray(), "Unexpected json type (expected array, but got " << jsonType << ")");
  316. YQL_ENSURE(json.GetArray().size() == 0, "Expected empty array, but got array with " << json.GetArray().size() << " elements");
  317. return holderFactory.GetEmptyContainerLazy();
  318. case TType::EKind::Tuple:
  319. {
  320. YQL_ENSURE(json.IsArray(), "Unexpected json type (expected array, but got " << jsonType << ")");
  321. auto tupleType = AS_TYPE(TTupleType, type);
  322. auto array = json.GetArray();
  323. YQL_ENSURE(array.size() == tupleType->GetElementsCount(),
  324. "Expected " << tupleType->GetElementsCount() << " elements in tuple, but got " << array.size());
  325. NUdf::TUnboxedValue* items;
  326. NUdf::TUnboxedValue tuple = holderFactory.CreateDirectArrayHolder(tupleType->GetElementsCount(), items);
  327. for (ui32 i = 0, e = array.size(); i < e; i++) {
  328. items[i] = ReadJsonValue(array[i], tupleType->GetElementType(i), holderFactory);
  329. }
  330. return tuple;
  331. }
  332. case TType::EKind::Dict:
  333. {
  334. YQL_ENSURE(json.IsArray(), "Unexpected json type (expected array, but got " << jsonType << ")");
  335. auto dictType = AS_TYPE(TDictType, type);
  336. auto array = json.GetArray();
  337. auto builder = holderFactory.NewDict(dictType, NUdf::TDictFlags::EDictKind::Hashed);
  338. // is Set<>
  339. if (dictType->GetPayloadType()->GetKind() == TType::EKind::Void) {
  340. for (ui32 i = 0, e = array.size(); i < e; i++) {
  341. auto value = ReadJsonValue(array[i], dictType->GetKeyType(), holderFactory);
  342. builder->Add(std::move(value), NKikimr::NUdf::TUnboxedValuePod());
  343. }
  344. } else {
  345. for (ui32 i = 0, e = array.size(); i < e; i++) {
  346. auto tuple = array[i];
  347. YQL_ENSURE(tuple.IsArray() && tuple.GetArray().size() == 2,
  348. "Unexpected json type (expected array with 2 elements, but got " << tuple.GetType() << ")");
  349. auto key = ReadJsonValue(tuple[0], dictType->GetKeyType(), holderFactory);
  350. auto value = ReadJsonValue(tuple[1], dictType->GetPayloadType(), holderFactory);
  351. builder->Add(std::move(key), std::move(value));
  352. }
  353. }
  354. return builder->Build();
  355. }
  356. case TType::EKind::Variant:
  357. {
  358. YQL_ENSURE(json.IsArray(), "Unexpected json type (expected array, but got " << jsonType << ")");
  359. auto array = json.GetArray();
  360. YQL_ENSURE(array.size() == 2, "Expected array with 2 elements, but got array with " << array.size() << " elements");
  361. auto underlyingType = AS_TYPE(TVariantType, type)->GetUnderlyingType();
  362. NUdf::TUnboxedValuePod variant;
  363. if (underlyingType->IsTuple()) {
  364. auto indexType = json[0].GetType();
  365. YQL_ENSURE(indexType == EJsonValueType::JSON_INTEGER || indexType == EJsonValueType::JSON_UINTEGER,
  366. "First element of variant has unexpected type(expected integer, but got " << indexType << ")");
  367. ui64 index = indexType == EJsonValueType::JSON_INTEGER ? json[0].GetInteger() : json[0].GetUInteger();
  368. auto tupleType = AS_TYPE(TTupleType, underlyingType);
  369. YQL_ENSURE(index < tupleType->GetElementsCount(), "Member with index " << index << " didn't find in Variant by tuple");
  370. auto value = ReadJsonValue(array[1], tupleType->GetElementType(index), holderFactory);
  371. variant = holderFactory.CreateVariantHolder(value.Release(), index);
  372. } else {
  373. auto structType = AS_TYPE(TStructType, underlyingType);
  374. YQL_ENSURE(json[0].IsString(), "First element of variant has unexpected type(expected string, but got " << json[0].GetType() << ")");
  375. auto index = structType->FindMemberIndex(json[0].GetString());
  376. YQL_ENSURE(index, "Member with name `" << json[0].GetString() << "` didn't find in Variant by struct");
  377. auto value = ReadJsonValue(array[1], structType->GetMemberType(*index), holderFactory);
  378. variant = holderFactory.CreateVariantHolder(value.Release(), *index);
  379. }
  380. return variant;
  381. }
  382. case TType::EKind::Tagged:
  383. {
  384. auto underlyingType = AS_TYPE(TTaggedType, type)->GetBaseType();
  385. return ReadJsonValue(json, underlyingType, holderFactory);
  386. }
  387. case TType::EKind::List:
  388. {
  389. YQL_ENSURE(json.IsArray(), "Unexpected json type (expected array, but got " << jsonType << ")");
  390. auto listType = AS_TYPE(TListType, type);
  391. TDefaultListRepresentation items;
  392. auto array = json.GetArray();
  393. for (ui32 i = 0, e = array.size(); i < e; i++) {
  394. items = items.Append(ReadJsonValue(array[i], listType->GetItemType(), holderFactory));
  395. }
  396. return holderFactory.CreateDirectListHolder(std::move(items));
  397. }
  398. case TType::EKind::Struct:
  399. {
  400. YQL_ENSURE(json.IsMap(), "Unexpected json type (expected map, but got " << jsonType << ")");
  401. auto structType = AS_TYPE(TStructType, type);
  402. NUdf::TUnboxedValue* items;
  403. NUdf::TUnboxedValue structValue = holderFactory.CreateDirectArrayHolder(structType->GetMembersCount(), items);
  404. auto jsonMap = json.GetMap();
  405. std::unordered_set<TString> unprocessed(jsonMap.size());
  406. for (auto const& map : jsonMap) {
  407. unprocessed.insert(map.first);
  408. }
  409. for (ui32 i = 0; i < structType->GetMembersCount(); ++i) {
  410. const auto keyName = TString(structType->GetMemberName(i));
  411. if (jsonMap.contains(keyName)) {
  412. items[i] = ReadJsonValue(jsonMap[keyName], structType->GetMemberType(i), holderFactory);
  413. } else {
  414. YQL_ENSURE(structType->GetMemberType(i)->IsOptional(), "Absent non optional field " << keyName << " at struct");
  415. items[i] = NKikimr::NUdf::TUnboxedValue();
  416. }
  417. unprocessed.erase(keyName);
  418. }
  419. YQL_ENSURE(unprocessed.empty(), "Extra fields into json map detected (" << JoinSeq(',', unprocessed) << ")");
  420. return structValue;
  421. }
  422. case TType::EKind::Optional:
  423. {
  424. YQL_ENSURE(json.IsArray()
  425. && json.GetArray().size() <= 1
  426. , "Unexpected json type (expected array no more than one element, but got " << jsonType << ")");
  427. auto array = json.GetArray();
  428. if (array.empty()) {
  429. return NUdf::TUnboxedValuePod().MakeOptional();
  430. }
  431. auto optionalType = AS_TYPE(TOptionalType, type);
  432. auto value = ReadJsonValue(array.front(), optionalType->GetItemType(), holderFactory);
  433. return value.Release().MakeOptional();
  434. }
  435. case TType::EKind::Data:
  436. {
  437. auto dataType = AS_TYPE(TDataType, type);
  438. switch (dataType->GetSchemeType()) {
  439. case NUdf::TDataType<bool>::Id:
  440. YQL_ENSURE(json.IsBoolean(), "Unexpected json type (expected bool, but got " << jsonType << ")");
  441. return NUdf::TUnboxedValuePod(json.GetBoolean());
  442. #define INTEGER_CONVERTOR(type, wideType) \
  443. case NUdf::TDataType<type>::Id: { \
  444. YQL_ENSURE(jsonType == EJsonValueType::JSON_INTEGER \
  445. || jsonType == EJsonValueType::JSON_UINTEGER, \
  446. "Unexpected json type (expected " << #type << ", but got " << jsonType << ")"); \
  447. wideType intValue = jsonType == EJsonValueType::JSON_INTEGER ? json.GetInteger() : json.GetUInteger(); \
  448. YQL_ENSURE(intValue >= std::numeric_limits<type>::min() \
  449. && intValue <= std::numeric_limits<type>::max(), \
  450. "Exceeded the range of acceptable values for " << #type); \
  451. return NUdf::TUnboxedValuePod(type(intValue)); \
  452. }
  453. INTEGER_CONVERTOR(ui8, ui64)
  454. INTEGER_CONVERTOR(ui16, ui64)
  455. INTEGER_CONVERTOR(ui32, ui64)
  456. INTEGER_CONVERTOR(ui64, ui64)
  457. INTEGER_CONVERTOR(i8, i64)
  458. INTEGER_CONVERTOR(i16, i64)
  459. INTEGER_CONVERTOR(i32, i64)
  460. INTEGER_CONVERTOR(i64, i64)
  461. #undef INTEGER_CONVERTOR
  462. case NUdf::TDataType<float>::Id: {
  463. YQL_ENSURE(json.IsDouble() || json.IsInteger() || json.IsUInteger(),
  464. "Unexpected json type (expected double or integer, but got " << jsonType << ")");
  465. double value = jsonType == EJsonValueType::JSON_DOUBLE
  466. ? json.GetDouble()
  467. : (jsonType == EJsonValueType::JSON_INTEGER ? double(json.GetInteger()) : double(json.GetUInteger()));
  468. YQL_ENSURE(value >= std::numeric_limits<float>::min() && value <= std::numeric_limits<float>::max(),
  469. "Exceeded the range of acceptable values for float");
  470. return NUdf::TUnboxedValuePod(float(value));
  471. }
  472. case NUdf::TDataType<double>::Id: {
  473. YQL_ENSURE(json.IsDouble() || json.IsInteger() || json.IsUInteger(),
  474. "Unexpected json type (expected double or integer, but got " << jsonType << ")");
  475. double value = jsonType == EJsonValueType::JSON_DOUBLE
  476. ? json.GetDouble()
  477. : (jsonType == EJsonValueType::JSON_INTEGER ? double(json.GetInteger()) : double(json.GetUInteger()));
  478. return NUdf::TUnboxedValuePod(value);
  479. }
  480. case NUdf::TDataType<NUdf::TUtf8>::Id:
  481. case NUdf::TDataType<char*>::Id: {
  482. YQL_ENSURE(json.IsString(), "Unexpected json type (expected string, but got " << jsonType << ")");
  483. auto value = json.GetString();
  484. return NUdf::TUnboxedValue(MakeString(NUdf::TStringRef(value)));
  485. }
  486. case NUdf::TDataType<NUdf::TDecimal>::Id: {
  487. YQL_ENSURE(json.IsString(), "Unexpected json type (expected string, but got " << jsonType << ")");
  488. const auto params = static_cast<TDataDecimalType*>(type)->GetParams();
  489. const auto value = NDecimal::FromString(json.GetString(), params.first, params.second);
  490. YQL_ENSURE(!NDecimal::IsError(value));
  491. return NUdf::TUnboxedValuePod(value);
  492. }
  493. case NUdf::TDataType<NUdf::TDate>::Id:
  494. case NUdf::TDataType<NUdf::TDatetime>::Id:
  495. case NUdf::TDataType<NUdf::TTimestamp>::Id:
  496. case NUdf::TDataType<NUdf::TInterval>::Id:
  497. case NUdf::TDataType<NUdf::TTzDate>::Id:
  498. case NUdf::TDataType<NUdf::TTzDatetime>::Id:
  499. case NUdf::TDataType<NUdf::TTzTimestamp>::Id:
  500. case NUdf::TDataType<NUdf::TDate32>::Id:
  501. case NUdf::TDataType<NUdf::TDatetime64>::Id:
  502. case NUdf::TDataType<NUdf::TTimestamp64>::Id:
  503. case NUdf::TDataType<NUdf::TInterval64>::Id: {
  504. YQL_ENSURE(json.IsString(), "Unexpected json type (expected string, but got " << jsonType << ")");
  505. YQL_ENSURE(IsValidStringValue(*dataType->GetDataSlot(), json.GetString()), "Invalid date format (expected ISO-8601)");
  506. return ValueFromString(*dataType->GetDataSlot(), json.GetString());
  507. }
  508. default:
  509. YQL_ENSURE(false, "Can't convert from JSON (unsupported YQL type " << dataType->GetSchemeType() << ")");
  510. }
  511. }
  512. break;
  513. default:
  514. YQL_ENSURE(false, "Can't convert from JSON (unsupported YQL type " << type->GetKindAsStr() << ")");
  515. }
  516. return NKikimr::NUdf::TUnboxedValuePod();
  517. }
  518. }
  519. }
  520. }