yql_json_codec.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  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::TTzDate32>::Id:
  205. case NUdf::TDataType<NUdf::TTzDatetime64>::Id:
  206. case NUdf::TDataType<NUdf::TTzTimestamp64>::Id:
  207. case NUdf::TDataType<NUdf::TJsonDocument>::Id: {
  208. const NUdf::TUnboxedValue out(ValueToString(*dataType->GetDataSlot(), value));
  209. writer.Write(out.AsStringRef());
  210. break;
  211. }
  212. default:
  213. throw yexception() << "Unknown data type: " << dataType->GetSchemeType();
  214. }
  215. }
  216. break;
  217. case TType::EKind::Struct:
  218. {
  219. writer.OpenMap();
  220. auto structType = AS_TYPE(TStructType, type);
  221. for (ui32 i = 0, e = structType->GetMembersCount(); i < e; ++i) {
  222. writer.WriteKey(structType->GetMemberName(i));
  223. WriteValueToJson(writer, value.GetElement(i), structType->GetMemberType(i), convertPolicy);
  224. }
  225. writer.CloseMap();
  226. break;
  227. }
  228. case TType::EKind::List:
  229. {
  230. writer.OpenArray();
  231. auto listType = AS_TYPE(TListType, type);
  232. const auto it = value.GetListIterator();
  233. for (NUdf::TUnboxedValue item; it.Next(item);) {
  234. WriteValueToJson(writer, item, listType->GetItemType(), convertPolicy);
  235. }
  236. writer.CloseArray();
  237. break;
  238. }
  239. case TType::EKind::Optional:
  240. {
  241. writer.OpenArray();
  242. if (value) {
  243. auto optionalType = AS_TYPE(TOptionalType, type);
  244. WriteValueToJson(writer, value.GetOptionalValue(), optionalType->GetItemType(), convertPolicy);
  245. }
  246. writer.CloseArray();
  247. break;
  248. }
  249. case TType::EKind::Dict:
  250. {
  251. writer.OpenArray();
  252. auto dictType = AS_TYPE(TDictType, type);
  253. const auto it = value.GetDictIterator();
  254. // is Set<>
  255. if (dictType->GetPayloadType()->GetKind() == TType::EKind::Void) {
  256. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  257. WriteValueToJson(writer, key, dictType->GetKeyType(), convertPolicy);
  258. }
  259. } else {
  260. for (NUdf::TUnboxedValue key, payload; it.NextPair(key, payload);) {
  261. writer.OpenArray();
  262. WriteValueToJson(writer, key, dictType->GetKeyType(), convertPolicy);
  263. WriteValueToJson(writer, payload, dictType->GetPayloadType(), convertPolicy);
  264. writer.CloseArray();
  265. }
  266. }
  267. writer.CloseArray();
  268. break;
  269. }
  270. case TType::EKind::Tuple:
  271. {
  272. writer.OpenArray();
  273. auto tupleType = AS_TYPE(TTupleType, type);
  274. for (ui32 i = 0, e = tupleType->GetElementsCount(); i < e; ++i) {
  275. WriteValueToJson(writer, value.GetElement(i), tupleType->GetElementType(i), convertPolicy);
  276. }
  277. writer.CloseArray();
  278. break;
  279. }
  280. case TType::EKind::Variant:
  281. {
  282. writer.OpenArray();
  283. auto index = value.GetVariantIndex();
  284. auto underlyingType = AS_TYPE(TVariantType, type)->GetUnderlyingType();
  285. if (underlyingType->IsTuple()) {
  286. writer.Write(index);
  287. WriteValueToJson(writer, value.GetVariantItem(),
  288. AS_TYPE(TTupleType, underlyingType)->GetElementType(index), convertPolicy);
  289. } else {
  290. auto structType = AS_TYPE(TStructType, underlyingType);
  291. writer.Write(structType->GetMemberName(index));
  292. WriteValueToJson(writer, value.GetVariantItem(), structType->GetMemberType(index), convertPolicy);
  293. }
  294. writer.CloseArray();
  295. break;
  296. }
  297. case TType::EKind::Tagged:
  298. {
  299. auto underlyingType = AS_TYPE(TTaggedType, type)->GetBaseType();
  300. WriteValueToJson(writer, value, underlyingType, convertPolicy);
  301. break;
  302. }
  303. default:
  304. YQL_ENSURE(false, "doesn't known how to convert type " << type->GetKindAsStr() << " to JSON");
  305. }
  306. }
  307. NKikimr::NUdf::TUnboxedValue ReadJsonValue(TJsonValue& json, NKikimr::NMiniKQL::TType* type,
  308. const NMiniKQL::THolderFactory& holderFactory)
  309. {
  310. auto jsonType = json.GetType();
  311. switch (type->GetKind()) {
  312. case TType::EKind::Void:
  313. case TType::EKind::Null:
  314. YQL_ENSURE(json.IsNull(), "Unexpected json type (expected null value, but got type " << jsonType << ")");
  315. return NKikimr::NUdf::TUnboxedValuePod();
  316. case TType::EKind::EmptyList:
  317. case TType::EKind::EmptyDict:
  318. YQL_ENSURE(json.IsArray(), "Unexpected json type (expected array, but got " << jsonType << ")");
  319. YQL_ENSURE(json.GetArray().size() == 0, "Expected empty array, but got array with " << json.GetArray().size() << " elements");
  320. return holderFactory.GetEmptyContainerLazy();
  321. case TType::EKind::Tuple:
  322. {
  323. YQL_ENSURE(json.IsArray(), "Unexpected json type (expected array, but got " << jsonType << ")");
  324. auto tupleType = AS_TYPE(TTupleType, type);
  325. auto array = json.GetArray();
  326. YQL_ENSURE(array.size() == tupleType->GetElementsCount(),
  327. "Expected " << tupleType->GetElementsCount() << " elements in tuple, but got " << array.size());
  328. NUdf::TUnboxedValue* items;
  329. NUdf::TUnboxedValue tuple = holderFactory.CreateDirectArrayHolder(tupleType->GetElementsCount(), items);
  330. for (ui32 i = 0, e = array.size(); i < e; i++) {
  331. items[i] = ReadJsonValue(array[i], tupleType->GetElementType(i), holderFactory);
  332. }
  333. return tuple;
  334. }
  335. case TType::EKind::Dict:
  336. {
  337. YQL_ENSURE(json.IsArray(), "Unexpected json type (expected array, but got " << jsonType << ")");
  338. auto dictType = AS_TYPE(TDictType, type);
  339. auto array = json.GetArray();
  340. auto builder = holderFactory.NewDict(dictType, NUdf::TDictFlags::EDictKind::Hashed);
  341. // is Set<>
  342. if (dictType->GetPayloadType()->GetKind() == TType::EKind::Void) {
  343. for (ui32 i = 0, e = array.size(); i < e; i++) {
  344. auto value = ReadJsonValue(array[i], dictType->GetKeyType(), holderFactory);
  345. builder->Add(std::move(value), NKikimr::NUdf::TUnboxedValuePod());
  346. }
  347. } else {
  348. for (ui32 i = 0, e = array.size(); i < e; i++) {
  349. auto tuple = array[i];
  350. YQL_ENSURE(tuple.IsArray() && tuple.GetArray().size() == 2,
  351. "Unexpected json type (expected array with 2 elements, but got " << tuple.GetType() << ")");
  352. auto key = ReadJsonValue(tuple[0], dictType->GetKeyType(), holderFactory);
  353. auto value = ReadJsonValue(tuple[1], dictType->GetPayloadType(), holderFactory);
  354. builder->Add(std::move(key), std::move(value));
  355. }
  356. }
  357. return builder->Build();
  358. }
  359. case TType::EKind::Variant:
  360. {
  361. YQL_ENSURE(json.IsArray(), "Unexpected json type (expected array, but got " << jsonType << ")");
  362. auto array = json.GetArray();
  363. YQL_ENSURE(array.size() == 2, "Expected array with 2 elements, but got array with " << array.size() << " elements");
  364. auto underlyingType = AS_TYPE(TVariantType, type)->GetUnderlyingType();
  365. NUdf::TUnboxedValuePod variant;
  366. if (underlyingType->IsTuple()) {
  367. auto indexType = json[0].GetType();
  368. YQL_ENSURE(indexType == EJsonValueType::JSON_INTEGER || indexType == EJsonValueType::JSON_UINTEGER,
  369. "First element of variant has unexpected type(expected integer, but got " << indexType << ")");
  370. ui64 index = indexType == EJsonValueType::JSON_INTEGER ? json[0].GetInteger() : json[0].GetUInteger();
  371. auto tupleType = AS_TYPE(TTupleType, underlyingType);
  372. YQL_ENSURE(index < tupleType->GetElementsCount(), "Member with index " << index << " didn't find in Variant by tuple");
  373. auto value = ReadJsonValue(array[1], tupleType->GetElementType(index), holderFactory);
  374. variant = holderFactory.CreateVariantHolder(value.Release(), index);
  375. } else {
  376. auto structType = AS_TYPE(TStructType, underlyingType);
  377. YQL_ENSURE(json[0].IsString(), "First element of variant has unexpected type(expected string, but got " << json[0].GetType() << ")");
  378. auto index = structType->FindMemberIndex(json[0].GetString());
  379. YQL_ENSURE(index, "Member with name `" << json[0].GetString() << "` didn't find in Variant by struct");
  380. auto value = ReadJsonValue(array[1], structType->GetMemberType(*index), holderFactory);
  381. variant = holderFactory.CreateVariantHolder(value.Release(), *index);
  382. }
  383. return variant;
  384. }
  385. case TType::EKind::Tagged:
  386. {
  387. auto underlyingType = AS_TYPE(TTaggedType, type)->GetBaseType();
  388. return ReadJsonValue(json, underlyingType, holderFactory);
  389. }
  390. case TType::EKind::List:
  391. {
  392. YQL_ENSURE(json.IsArray(), "Unexpected json type (expected array, but got " << jsonType << ")");
  393. auto listType = AS_TYPE(TListType, type);
  394. TDefaultListRepresentation items;
  395. auto array = json.GetArray();
  396. for (ui32 i = 0, e = array.size(); i < e; i++) {
  397. items = items.Append(ReadJsonValue(array[i], listType->GetItemType(), holderFactory));
  398. }
  399. return holderFactory.CreateDirectListHolder(std::move(items));
  400. }
  401. case TType::EKind::Struct:
  402. {
  403. YQL_ENSURE(json.IsMap(), "Unexpected json type (expected map, but got " << jsonType << ")");
  404. auto structType = AS_TYPE(TStructType, type);
  405. NUdf::TUnboxedValue* items;
  406. NUdf::TUnboxedValue structValue = holderFactory.CreateDirectArrayHolder(structType->GetMembersCount(), items);
  407. auto jsonMap = json.GetMap();
  408. std::unordered_set<TString> unprocessed(jsonMap.size());
  409. for (auto const& map : jsonMap) {
  410. unprocessed.insert(map.first);
  411. }
  412. for (ui32 i = 0; i < structType->GetMembersCount(); ++i) {
  413. const auto keyName = TString(structType->GetMemberName(i));
  414. if (jsonMap.contains(keyName)) {
  415. items[i] = ReadJsonValue(jsonMap[keyName], structType->GetMemberType(i), holderFactory);
  416. } else {
  417. YQL_ENSURE(structType->GetMemberType(i)->IsOptional(), "Absent non optional field " << keyName << " at struct");
  418. items[i] = NKikimr::NUdf::TUnboxedValue();
  419. }
  420. unprocessed.erase(keyName);
  421. }
  422. YQL_ENSURE(unprocessed.empty(), "Extra fields into json map detected (" << JoinSeq(',', unprocessed) << ")");
  423. return structValue;
  424. }
  425. case TType::EKind::Optional:
  426. {
  427. YQL_ENSURE(json.IsArray()
  428. && json.GetArray().size() <= 1
  429. , "Unexpected json type (expected array no more than one element, but got " << jsonType << ")");
  430. auto array = json.GetArray();
  431. if (array.empty()) {
  432. return NUdf::TUnboxedValuePod().MakeOptional();
  433. }
  434. auto optionalType = AS_TYPE(TOptionalType, type);
  435. auto value = ReadJsonValue(array.front(), optionalType->GetItemType(), holderFactory);
  436. return value.Release().MakeOptional();
  437. }
  438. case TType::EKind::Data:
  439. {
  440. auto dataType = AS_TYPE(TDataType, type);
  441. switch (dataType->GetSchemeType()) {
  442. case NUdf::TDataType<bool>::Id:
  443. YQL_ENSURE(json.IsBoolean(), "Unexpected json type (expected bool, but got " << jsonType << ")");
  444. return NUdf::TUnboxedValuePod(json.GetBoolean());
  445. #define INTEGER_CONVERTOR(type, wideType) \
  446. case NUdf::TDataType<type>::Id: { \
  447. YQL_ENSURE(jsonType == EJsonValueType::JSON_INTEGER \
  448. || jsonType == EJsonValueType::JSON_UINTEGER, \
  449. "Unexpected json type (expected " << #type << ", but got " << jsonType << ")"); \
  450. wideType intValue = jsonType == EJsonValueType::JSON_INTEGER ? json.GetInteger() : json.GetUInteger(); \
  451. YQL_ENSURE(intValue >= std::numeric_limits<type>::min() \
  452. && intValue <= std::numeric_limits<type>::max(), \
  453. "Exceeded the range of acceptable values for " << #type); \
  454. return NUdf::TUnboxedValuePod(type(intValue)); \
  455. }
  456. INTEGER_CONVERTOR(ui8, ui64)
  457. INTEGER_CONVERTOR(ui16, ui64)
  458. INTEGER_CONVERTOR(ui32, ui64)
  459. INTEGER_CONVERTOR(ui64, ui64)
  460. INTEGER_CONVERTOR(i8, i64)
  461. INTEGER_CONVERTOR(i16, i64)
  462. INTEGER_CONVERTOR(i32, i64)
  463. INTEGER_CONVERTOR(i64, i64)
  464. #undef INTEGER_CONVERTOR
  465. case NUdf::TDataType<float>::Id: {
  466. YQL_ENSURE(json.IsDouble() || json.IsInteger() || json.IsUInteger(),
  467. "Unexpected json type (expected double or integer, but got " << jsonType << ")");
  468. double value = jsonType == EJsonValueType::JSON_DOUBLE
  469. ? json.GetDouble()
  470. : (jsonType == EJsonValueType::JSON_INTEGER ? double(json.GetInteger()) : double(json.GetUInteger()));
  471. YQL_ENSURE(value >= std::numeric_limits<float>::min() && value <= std::numeric_limits<float>::max(),
  472. "Exceeded the range of acceptable values for float");
  473. return NUdf::TUnboxedValuePod(float(value));
  474. }
  475. case NUdf::TDataType<double>::Id: {
  476. YQL_ENSURE(json.IsDouble() || json.IsInteger() || json.IsUInteger(),
  477. "Unexpected json type (expected double or integer, but got " << jsonType << ")");
  478. double value = jsonType == EJsonValueType::JSON_DOUBLE
  479. ? json.GetDouble()
  480. : (jsonType == EJsonValueType::JSON_INTEGER ? double(json.GetInteger()) : double(json.GetUInteger()));
  481. return NUdf::TUnboxedValuePod(value);
  482. }
  483. case NUdf::TDataType<NUdf::TUtf8>::Id:
  484. case NUdf::TDataType<char*>::Id: {
  485. YQL_ENSURE(json.IsString(), "Unexpected json type (expected string, but got " << jsonType << ")");
  486. auto value = json.GetString();
  487. return NUdf::TUnboxedValue(MakeString(NUdf::TStringRef(value)));
  488. }
  489. case NUdf::TDataType<NUdf::TDecimal>::Id: {
  490. YQL_ENSURE(json.IsString(), "Unexpected json type (expected string, but got " << jsonType << ")");
  491. const auto params = static_cast<TDataDecimalType*>(type)->GetParams();
  492. const auto value = NDecimal::FromString(json.GetString(), params.first, params.second);
  493. YQL_ENSURE(!NDecimal::IsError(value));
  494. return NUdf::TUnboxedValuePod(value);
  495. }
  496. case NUdf::TDataType<NUdf::TDate>::Id:
  497. case NUdf::TDataType<NUdf::TDatetime>::Id:
  498. case NUdf::TDataType<NUdf::TTimestamp>::Id:
  499. case NUdf::TDataType<NUdf::TInterval>::Id:
  500. case NUdf::TDataType<NUdf::TTzDate>::Id:
  501. case NUdf::TDataType<NUdf::TTzDatetime>::Id:
  502. case NUdf::TDataType<NUdf::TTzTimestamp>::Id:
  503. case NUdf::TDataType<NUdf::TDate32>::Id:
  504. case NUdf::TDataType<NUdf::TDatetime64>::Id:
  505. case NUdf::TDataType<NUdf::TTimestamp64>::Id:
  506. case NUdf::TDataType<NUdf::TInterval64>::Id:
  507. case NUdf::TDataType<NUdf::TTzDate32>::Id:
  508. case NUdf::TDataType<NUdf::TTzDatetime64>::Id:
  509. case NUdf::TDataType<NUdf::TTzTimestamp64>::Id: {
  510. YQL_ENSURE(json.IsString(), "Unexpected json type (expected string, but got " << jsonType << ")");
  511. YQL_ENSURE(IsValidStringValue(*dataType->GetDataSlot(), json.GetString()), "Invalid date format (expected ISO-8601)");
  512. return ValueFromString(*dataType->GetDataSlot(), json.GetString());
  513. }
  514. default:
  515. YQL_ENSURE(false, "Can't convert from JSON (unsupported YQL type " << dataType->GetSchemeType() << ")");
  516. }
  517. }
  518. break;
  519. default:
  520. YQL_ENSURE(false, "Can't convert from JSON (unsupported YQL type " << type->GetKindAsStr() << ")");
  521. }
  522. return NKikimr::NUdf::TUnboxedValuePod();
  523. }
  524. }
  525. }
  526. }