as_json_node.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #pragma once
  2. #include "resource.h"
  3. #include <yql/essentials/public/udf/udf_value.h>
  4. #include <yql/essentials/public/udf/udf_helpers.h>
  5. #include <yql/essentials/minikql/dom/node.h>
  6. #include <yql/essentials/minikql/dom/json.h>
  7. namespace NJson2Udf {
  8. using namespace NKikimr;
  9. using namespace NUdf;
  10. using namespace NYql;
  11. using namespace NDom;
  12. template <typename TSource>
  13. class TAsJsonNode: public TBoxedValue {
  14. public:
  15. TAsJsonNode(TSourcePosition pos)
  16. : Pos_(pos)
  17. {
  18. }
  19. static TStringRef Name();
  20. static bool DeclareSignature(
  21. const TStringRef& name,
  22. TType* userType,
  23. IFunctionTypeInfoBuilder& builder,
  24. bool typesOnly) {
  25. Y_UNUSED(userType);
  26. if (name != Name()) {
  27. return false;
  28. }
  29. auto optionalSourceType = builder.Optional()->Item<TSource>().Build();
  30. auto resourceType = builder.Resource(JSON_NODE_RESOURCE_NAME);
  31. builder.Args()
  32. ->Add(optionalSourceType)
  33. .Done()
  34. .Returns(resourceType);
  35. if (!typesOnly) {
  36. builder.Implementation(new TAsJsonNode<TSource>(builder.GetSourcePosition()));
  37. }
  38. builder.IsStrict();
  39. return true;
  40. }
  41. private:
  42. const size_t MaxParseErrors = 10;
  43. static TUnboxedValue Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder);
  44. TUnboxedValue Run(
  45. const IValueBuilder* valueBuilder,
  46. const TUnboxedValuePod* args) const final {
  47. Y_UNUSED(valueBuilder);
  48. try {
  49. if (!args[0].HasValue()) {
  50. return MakeEntity();
  51. }
  52. return Interpret(args[0], valueBuilder);
  53. } catch (const std::exception& e) {
  54. UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
  55. }
  56. }
  57. TSourcePosition Pos_;
  58. };
  59. template <>
  60. TStringRef TAsJsonNode<TUtf8>::Name() {
  61. return TStringRef::Of("Utf8AsJsonNode");
  62. }
  63. template <>
  64. TUnboxedValue TAsJsonNode<TUtf8>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
  65. return MakeString(sourceValue.AsStringRef(), valueBuilder);
  66. }
  67. template <>
  68. TStringRef TAsJsonNode<double>::Name() {
  69. return TStringRef::Of("DoubleAsJsonNode");
  70. }
  71. template <>
  72. TUnboxedValue TAsJsonNode<double>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
  73. Y_UNUSED(valueBuilder);
  74. return MakeDouble(sourceValue.Get<double>());
  75. }
  76. template <>
  77. TStringRef TAsJsonNode<bool>::Name() {
  78. return TStringRef::Of("BoolAsJsonNode");
  79. }
  80. template <>
  81. TUnboxedValue TAsJsonNode<bool>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
  82. Y_UNUSED(valueBuilder);
  83. return MakeBool(sourceValue.Get<bool>());
  84. }
  85. template <>
  86. TStringRef TAsJsonNode<TJson>::Name() {
  87. return TStringRef::Of("JsonAsJsonNode");
  88. }
  89. template <>
  90. TUnboxedValue TAsJsonNode<TJson>::Interpret(const TUnboxedValue& sourceValue, const IValueBuilder* valueBuilder) {
  91. return TryParseJsonDom(sourceValue.AsStringRef(), valueBuilder);
  92. }
  93. }