udtf函数 解析jason 数组

package com.royal.hive.udtf;

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.json.JSONArray;

import java.util.ArrayList;
import java.util.List;

/**
 * @author csw
 * @time 2022/4/21 19:48
 */
public class ExplodeJSONArray extends GenericUDTF {


    @Override
    public StructObjectInspector initialize(ObjectInspector[] argOIs) throws UDFArgumentException {
        // 进行判断传参是否合法
        if (argOIs.length != 1) {
            throw new UDFArgumentException("传参不合法,只需要一个参数");
        }
        // 判断传参的类型
        // 由于前面控制了传参个数,所以此时是可以确信的直接取第一个参数判断类型,getCategory返回数据类型检查器
        // ObjectInspector.Category.PRIMITIVE基本数据类型
        if (argOIs[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {
            throw new RuntimeException("参数类型必须为基本数据类型");
        }
        // 将参数对象检查器强转为基本类型对象检查器
        PrimitiveObjectInspector argumentOI = (PrimitiveObjectInspector) argOIs[0];
        // 再去判断是否为String类型
        if (argumentOI.getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.STRING) {
            throw new RuntimeException("参数必须为String类型数据");
        }

        // 以上均是对使用该函数时的参数和条件判断

        // 定义返回值名称和类型
        List<String> fieldNames = new ArrayList<>();
        List<ObjectInspector> filedOIs = new ArrayList<>();

        fieldNames.add("items");
        filedOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);

        // 通过对象工厂进行创建一个Struct对象
        return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, filedOIs);
    }

    @Override
    public void process(Object[] objects) throws HiveException {

        // 获取值,为什么这里使用数值第一个,因为在初始化时传参就已经限制了条件,这里必只有一个值
        String jsonArray = objects[0].toString();

        // 解析为JSONArray数组
        JSONArray actions = new JSONArray(jsonArray);

        // 如何处理?遍历JSONArray数组,来获取每一个JSON对象
        for (int i = 0; i < actions.length(); i++) {

            // 这里由于我们hive自身有解析JSON的函数,(udtf是炸裂开的,因为这里时循环,所以实际最终输出的是一个数组)
            String[] result = new String[1];
            result[0] = actions.getString(i);
            forward(result);
        }
    }

    @Override
    public void close() throws HiveException {

    }
}
posted @ 2022-09-21 18:36  付十一。  阅读(104)  评论(0)    收藏  举报