json_udf.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #include <yql/essentials/public/udf/udf_helpers.h>
  2. #include <library/cpp/json/easy_parse/json_easy_parser.h>
  3. using namespace NKikimr;
  4. using namespace NUdf;
  5. namespace {
  6. class TGetField: public TBoxedValue {
  7. public:
  8. typedef bool TTypeAwareMarker;
  9. public:
  10. static TStringRef Name() {
  11. return TStringRef::Of("GetField");
  12. }
  13. TUnboxedValue Run(
  14. const IValueBuilder* valueBuilder,
  15. const TUnboxedValuePod* args) const override {
  16. if (!args[0]) {
  17. return valueBuilder->NewEmptyList();
  18. }
  19. const TString json(args[0].AsStringRef());
  20. const TString field(args[1].AsStringRef());
  21. if (field.empty()) {
  22. return valueBuilder->NewEmptyList();
  23. }
  24. NJson::TJsonParser parser;
  25. parser.AddField(field, false);
  26. TVector<TString> result;
  27. parser.Parse(json, &result);
  28. TUnboxedValue* items = nullptr;
  29. const auto list = valueBuilder->NewArray(result.size(), items);
  30. for (const TString& item : result) {
  31. *items++ = valueBuilder->NewString(item);
  32. }
  33. return list;
  34. }
  35. static bool DeclareSignature(
  36. const TStringRef& name,
  37. TType* userType,
  38. IFunctionTypeInfoBuilder& builder,
  39. bool typesOnly) {
  40. if (Name() == name) {
  41. bool useString = true;
  42. bool isOptional = true;
  43. if (userType) {
  44. // support of an overload with Json/Json? input type
  45. auto typeHelper = builder.TypeInfoHelper();
  46. auto userTypeInspector = TTupleTypeInspector(*typeHelper, userType);
  47. if (!userTypeInspector || userTypeInspector.GetElementsCount() < 1) {
  48. builder.SetError("Missing or invalid user type.");
  49. return true;
  50. }
  51. auto argsTypeTuple = userTypeInspector.GetElementType(0);
  52. auto argsTypeInspector = TTupleTypeInspector(*typeHelper, argsTypeTuple);
  53. if (!argsTypeInspector) {
  54. builder.SetError("Invalid user type - expected tuple.");
  55. return true;
  56. }
  57. if (argsTypeInspector.GetElementsCount() != 2) {
  58. builder.SetError("Invalid user type - expected two arguments.");
  59. return true;
  60. }
  61. auto inputType = argsTypeInspector.GetElementType(0);
  62. auto optInspector = TOptionalTypeInspector(*typeHelper, inputType);
  63. auto dataType = inputType;
  64. if (optInspector) {
  65. dataType = optInspector.GetItemType();
  66. } else {
  67. isOptional = false;
  68. }
  69. auto dataInspector = TDataTypeInspector(*typeHelper, dataType);
  70. if (dataInspector && dataInspector.GetTypeId() == TDataType<TJson>::Id) {
  71. useString = false;
  72. builder.UserType(userType);
  73. }
  74. }
  75. auto retType = builder.List()->Item<char*>().Build();
  76. if (useString) {
  77. builder.Args()->Add(builder.Optional()->Item<char*>().Build()).Add<char*>().Done().Returns(retType);
  78. } else {
  79. auto type = builder.SimpleType<TJson>();
  80. if (isOptional) {
  81. builder.Args()->Add(builder.Optional()->Item(type).Build()).Add<char*>().Done().Returns(retType);
  82. } else {
  83. builder.Args()->Add(type).Add<char*>().Done().Returns(retType);
  84. }
  85. }
  86. if (!typesOnly) {
  87. builder.Implementation(new TGetField);
  88. }
  89. builder.IsStrict();
  90. return true;
  91. } else {
  92. return false;
  93. }
  94. }
  95. };
  96. }
  97. SIMPLE_MODULE(TJsonModule,
  98. TGetField)
  99. REGISTER_MODULES(TJsonModule)