Hive自定义UDTF解析json不定长数组

我就是我 2023-01-03 04:46 268阅读 0赞

Hive自定义UDTF解析json不定长数组

一、UDTF函数概述

UDTF(User-Defined Table-Generating Functions) 用来解决 输入一行输出多行(On-to-many maping) 的需求。

二、添加pom.xml依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.apache.hive</groupId>
  4. <artifactId>hive-exec</artifactId>
  5. <version>3.1.2</version>
  6. </dependency>
  7. </dependencies>

三、继承GenericUDTF实现解析json不定长数组

  1. package com.hive;
  2. import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
  3. import org.apache.hadoop.hive.ql.metadata.HiveException;
  4. import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
  5. import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
  6. import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
  7. import org.apache.hadoop.hive.serde2.objectinspector.StructField;
  8. import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
  9. import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
  10. import org.json.JSONArray;
  11. import java.util.ArrayList;
  12. import java.util.List;
  13. public class myUDTF extends GenericUDTF {
  14. /** * 作用:1.检查入参是否符合要求,如果不符合,可以进行通知 * 2.返回ObjectInspector,代表每行中内容的类型 * * 要求传入的必须是一个String * * @param argOIs * @return * @throws UDFArgumentException */
  15. @Override
  16. public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
  17. //获取函数传入的所有字段
  18. List<? extends StructField> inputFields = argOIs.getAllStructFieldRefs();
  19. //判断函数传入的是否是一个字段
  20. if (inputFields.size() != 1){
  21. throw new UDFArgumentException("此函数只能传入一列!");
  22. }
  23. //判断传入的字段是否是字符串
  24. if (!"string".equals(inputFields.get(0).getFieldObjectInspector().getTypeName())){
  25. throw new UDFArgumentException("此函数只能传入一列字符串");
  26. }
  27. //返回的是N行1列,每行都是只有一列(string)
  28. //每行的每列的名称
  29. List<String> fieldNames = new ArrayList<>();
  30. fieldNames.add("jsonObjectStr");
  31. //每行的每列的类型
  32. List<ObjectInspector> fieldOIS = new ArrayList<>();
  33. fieldOIS.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
  34. return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,fieldOIS);
  35. }
  36. //构造一个容器,存放输出的每行内容
  37. private String [] result = new String[1];
  38. //process: 生成UDTF返回的每行内容,生成后,调用forward(),将结果传给其他的运算符运算!
  39. public void process(Object[] args) throws HiveException {
  40. //获取函数传入的JsonArrayStr
  41. String jsonArrayStr = args[0].toString();
  42. //将JsonArrayStr转换为JsonArray对象
  43. JSONArray jsonArray = new JSONArray(jsonArrayStr);
  44. //遍历jsonArray,取出每一个JsonObject代表的str
  45. for (int i=0;i<jsonArray.length();i++){
  46. String jsonObjectStr = jsonArray.getJSONObject(i).toString();
  47. result[0] = jsonObjectStr;
  48. forward(result);
  49. }
  50. }
  51. //关闭资源
  52. public void close() throws HiveException {
  53. }
  54. }

四、在Hive创建自定义函数

①将上述代码打包上传到hive家目录下的auxlib文件夹内($HIVE_HOME/auxlib)

如果不存在需要自己手动创建,重启hive的服务,hive会自动读取auxlib目录下的jar包

②创建永久函数

​ 注意: 函数是有库的范围,自定义的函数,在哪个库定义,只能在哪个库用! 或使用 库名.函数名

  1. create function 函数名 as '函数全类名';
  2. create function explode_array as 'com.hive.myUDTF';

五、函数使用

  1. SELECT
  2. GET_JSON_OBJECT(line,'$.common.ar'),
  3. GET_JSON_OBJECT(line,'$.common.ba'),
  4. GET_JSON_OBJECT(line,'$.common.ch') ,
  5. GET_JSON_OBJECT(line,'$.common.md') ,
  6. GET_JSON_OBJECT(line,'$.common.mid'),
  7. GET_JSON_OBJECT(line,'$.common.os') ,
  8. GET_JSON_OBJECT(line,'$.common.uid') ,
  9. GET_JSON_OBJECT(line,'$.common.vc') ,
  10. GET_JSON_OBJECT(line,'$.page.during_time') ,
  11. GET_JSON_OBJECT(line,'$.page.item') ,
  12. GET_JSON_OBJECT(line,'$.page.item_type') ,
  13. GET_JSON_OBJECT(line,'$.page.last_page_id') ,
  14. GET_JSON_OBJECT(line,'$.page.page_id') ,
  15. GET_JSON_OBJECT(line,'$.page.sourceType') ,
  16. GET_JSON_OBJECT(line,'$.ts') ,
  17. GET_JSON_OBJECT(jsonObjectStr,'$.displayType') ,
  18. GET_JSON_OBJECT(jsonObjectStr,'$.item') ,
  19. GET_JSON_OBJECT(jsonObjectStr,'$.item_type') ,
  20. GET_JSON_OBJECT(jsonObjectStr,'$.order')
  21. FROM ods_log
  22. lateral view explore_arr(GET_JSON_OBJECT(line,'$.displays')) tmp as jsonObjectStr
  23. WHERE GET_JSON_OBJECT(line ,'$.displays') is not null
  24. AND dt='2021-01-04';

-—————————————————————————————更新——————————————————————————————————————

对json数组字符串数组进行处理,拆分后使用explore函数处理(explore函数也是UDTF函数)

  1. SELECT
  2. GET_JSON_OBJECT(line,'$.common.ar'),
  3. GET_JSON_OBJECT(line,'$.common.ba'),
  4. GET_JSON_OBJECT(line,'$.common.ch') ,
  5. GET_JSON_OBJECT(line,'$.common.md') ,
  6. GET_JSON_OBJECT(line,'$.common.mid'),
  7. GET_JSON_OBJECT(line,'$.common.os') ,
  8. GET_JSON_OBJECT(line,'$.common.uid') ,
  9. GET_JSON_OBJECT(line,'$.common.vc') ,
  10. GET_JSON_OBJECT(line,'$.page.during_time') ,
  11. GET_JSON_OBJECT(line,'$.page.item') ,
  12. GET_JSON_OBJECT(line,'$.page.item_type') ,
  13. GET_JSON_OBJECT(line,'$.page.last_page_id') ,
  14. GET_JSON_OBJECT(line,'$.page.page_id') ,
  15. GET_JSON_OBJECT(line,'$.page.sourceType') ,
  16. GET_JSON_OBJECT(line,'$.ts') ,
  17. GET_JSON_OBJECT(jsonObjectStr,'$.displayType') ,
  18. GET_JSON_OBJECT(jsonObjectStr,'$.item') ,
  19. GET_JSON_OBJECT(jsonObjectStr,'$.item_type') ,
  20. GET_JSON_OBJECT(jsonObjectStr,'$.order')
  21. --REGEXP_REPLACE( GET_JSON_OBJECT(line,'$.displays') ,'\\[|\\]' ,'' )
  22. --REGEXP_REPLACE( REGEXP_REPLACE( GET_JSON_OBJECT(line,'$.displays') ,'\\[|\\]' ,'' ),'\\}\\,\\{' ,'\\}\\!\\{')
  23. --split( REGEXP_REPLACE( REGEXP_REPLACE( GET_JSON_OBJECT(line,'$.displays') ,'\\[|\\]' ,'' ),'\\}\\,\\{' ,'\\}\\!\\{'),'\\!' )
  24. from ods_log
  25. lateral view explode( split( REGEXP_REPLACE( REGEXP_REPLACE( GET_JSON_OBJECT(line,'$.displays') ,'\\[|\\]' ,'' ),'\\}\\,\\{' ,'\\}\\!\\{'),'\\!' ) ) tmp as jsonObjectStr
  26. where GET_JSON_OBJECT(line ,'$.displays') is not null
  27. and dt='2021-01-04'
  28. ;

发表评论

表情:
评论列表 (有 0 条评论,268人围观)

还没有评论,来说两句吧...

相关阅读

    相关 hive: 定义UDTF

    在hive项目中, 有client和server通信的log日志体系如下,中间的网络传输使用的json格式,所以在server端接收时需要使用阿里的fastJSON来解析为日志

    相关 Hive UDTF

    UDTF:用户自定义表生成函数,表生成函数接受0个或多个输入然后产生多列或多行输出。 例如: select array(1,2,3); 结果为: ![在这里

    相关 vector不定数组

      看书的时候第n次见到vector了,一时兴起:既然这么好用就掌握它吧。 看书看别人的博客发现原理并不复杂。并且!居然支持任意位置插入!!一直以来无限头疼的问题,唯有二叉