ODPS自定义UDF解析json字符串
吐槽阿里ODPS:
SLS收录日志功能只能收取客户端前五分钟的数据,如果出故障就再也折腾不进去了,我技术挫,重指时间列,改时间,改系统时间..... 问阿里技术曰:就是只能收前五钟的,原理不可说。
SLS数据归档问题,日志数据中,假如只有两列,一列时间,一列json,归档到ODPS中,你会发现数据归为了一列,并且json化,也就意味着原来的json又被json化了一遍,会变成json字符串,加斜线了,问曰:设计问题,会改正,可自己写udf解之。
仅仅这样开始了苦逼的udf解析json之路。其实后还有坑更大
2.神我拿什么写UDF:
翻文档,有两种方式:java和python,心想python吧,团队其他人也会折腾,省得以后麻烦,开始找文档,耕遍文档库都没有,心想用 “odps udf python”来google之,搜之无一字,无力问度娘。算了吧,拿java来折腾吧,想偷懒也不成了。然后下eclipse,写代码,打jar,代码 写了十来分钟,怕代码有问题,用正则试了一把没问题,大有搞头的udf开始了,代码如下:
package playcrab.com.aliyun.odps.udf;import java.util.Map;import com.aliyun.odps.udf.UDF;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONArray;public final class custom_get_json_object extends UDF { public static String json2object(String jsonStr, String key) { try { Map map1 = JSON.parseObject(jsonStr); return JSON.toJSONString(map1.get(key.toString())); } catch (Exception e) { JSONArray jarr = JSONArray.parseArray(jsonStr);// JSON.parseArray(jsonStr); return JSON.toJSONString(jarr.get(Integer.parseInt(key))); } } public static String json2array(String jsonStr, String index) { JSONArray jarr = JSONArray.parseArray(jsonStr);// JSON.parseArray(jsonStr); return JSON.toJSONString(jarr.get(Integer.parseInt(index))); } public String evaluate(String jsonStr, String index) { if (jsonStr == null) { return null; } jsonStr.replaceAll("\\\\\"", "\""); jsonStr.replace("\"{\"", "{\""); jsonStr.replace("}\"}", "}}"); try { String[] keys = index.split("\\."); for (int i = 1; i < keys.length; i++) { jsonStr = json2object(jsonStr, keys[i]); } return jsonStr; } catch (Exception e) { String[] keys = index.split("\\."); for (int i = 1; i < keys.length; i++) { jsonStr = json2array(jsonStr, keys[i]); } return jsonStr; } } public static void main(String[] args) { //String jsonStr = "{\"a\":{\"b\":{\"c\":[\"fff\",\"ddddd\"]}}}"; //System.out.println(evaluate(jsonStr, "$.a.b.c.1")); //String jsonStr ="[{‘age‘:22,‘sex‘:‘男‘,‘userName‘:‘xiaoliang‘},{‘age‘:23,‘sex‘:‘男‘,‘userName‘:‘xiaoliang‘}]"; //System.out.println(evaluate(jsonStr, "$.0.age")); // select // get_json_object(regexp_replace(regexp_replace(regexp_replace(sls_extract_others,‘\\\\\"‘,‘"‘),‘"{"‘,‘{"‘),‘}"}‘,‘}}‘),‘$.content.content.action‘) // from z limit 1; } }
经过如下几步满怀期望
drop resource customgetjson_object.jar;
create resource jar customgetjson_object.jar;
create function customgetjsonobject playcrab.com.aliyun.odps.udf.customgetjsonobject customgetjson_object.jar
执行后,select customgetjsonobject(slsextract_others,‘$.content.content.zhi‘) from z limit 1;
好吧报错,说是找不到第三方fastjson
问曰:不支持第三方包,必须用odps自己的包,好吧看了一眼果然有一json-1.0.jar,心想大爷的我怎么知道你有哪些方法,只能 把包全加到lib中,import试,真佩服自己,又过了一遍jar,看见有gson,终于有希望了,这个是常用的包哈,快速扫了一遍方法,改吧,改吧, 改的一点都不能依赖阿里之外的第三方包,爷!fastjson不是阿里的么........
package playcrab.com.aliyun.odps.udf; import java.util.Map; import com.aliyun.odps.udf.UDF; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.google.gson.internal.LinkedTreeMap; public class custom_get_json_object extends UDF { /** * * 函数名称: parseData 函数描述: 将json字符串转换为map * * @param data * @return */ private static Map<String, String> parseData(String data) { GsonBuilder gb = new GsonBuilder(); Gson g = gb.create(); Map<String, String> map = g.fromJson(data, new TypeToken<Map<String, String>>() { }.getType()); return map; } public static String json2object(String jsonStr, String key) { try { //JSON转map后get指定key return (String) parseData(jsonStr).get(key); } catch (Exception e) { //System.out.println(e.toString()); //本身就是json串,变为map 指定key Gson gson = new Gson(); Map depts = gson.fromJson(jsonStr, Map.class); return gson.toJson(depts.get(key)); } } // TODO define parameters and return type, e.g., public Long evaluate(Long // a, Long b) public String evaluate(String jsonStr, String index) { //String index; //index = "$.content.content.tag"; String[] keys = index.split("\\."); for (int i = 1; i < keys.length; i++) { jsonStr = json2object(jsonStr, keys[i]); } return jsonStr; } }
打包,上传,使用,没问题了,好吧,刚才漏了一点,上传使用过程中,因为刚才我上传过一个jar并且创建函数了,后面的就不能用相同的函数名了,不知道能不能删除原来的。好吧,终于能使用了,阿门!
www.djhull.com
本文出自 “djshell” 博客,请务必保留此出处http://djshell.blog.51cto.com/6932750/1647280
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。