当你遇到大数据里含有json时候,离线数仓开发,hive有特别好用的get_json函数。
例如下面的:
SELECT get_json_object(xjson,"$.[0].age") FROM person
但遇到实时处理该咋办?
同学们会说,Flink SQL里不是有吗?好吧,你太想当然了。
在FlinkSQL,特别是最好用的FlinkSQL里,居然没有成型的JSON解析函数。
根据遇到的情形,有好几种方式。
如果遇到的是json有固定结构,那在定义flinkSQL的表结构里可以。比如:
像这样的json,
{
"funcName": "test",
"data": {
"snapshots": [{
"content_type": "application/x-gzip-compressed-jpeg",
"url": "https://blog.youkuaiyun.com/xianpanjia4616"
}],
"audio": [{
"content_type": "audio/wav",
"url": " https://bss.youkuaiyun.com/m/topic/blog_star2020/detail?username=xianpanjia4616"
}]
},
"resultMap": {
"result": {
"cover": "/data/test/log.txt"
},
"isSuccess": true
},
"meta": {
"video_type": "normal"
},
"type": 2,
"timestamp": 1610549997263,
"arr": [{
"address": "北京市海淀区",
"city": "beijing"
}, {
"address": "北京市海淀区",
"city": "beijing"
}, {
"address": "北京市海淀区",
"city": "beijing"
}],
"map": {
"flink": 456
},
"doublemap": {
"inner_map": {
"key": 123
}
}
}
可以使用这样的表结构定义:
CREATE TABLE kafka_source (
funcName STRING,
data ROW<snapshots ARRAY<ROW<content_type STRING,url STRING>>,audio ARRAY<ROW<content_type STRING,url STRING>>>,
resultMap ROW<`result` MAP<STRING,STRING>,isSuccess BOOLEAN>,
meta MAP<STRING,STRING>,
`type` INT,
`timestamp` BIGINT,
arr ARRAY<ROW<address STRING,city STRING>>,
map MAP<STRING,INT>,
doublemap MAP<STRING,MAP<STRING,INT>>,
proctime as PROCTIME()
) WITH (
'connector' = 'kafka', -- 使用 kafka connector
'topic' = 'test', -- kafka topic
'properties.bootstrap.servers' = 'master:9092,storm1:9092,storm2:9092', -- broker连接信息
'properties.group.id' = 'jason_flink_test', -- 消费kafka的group_id
'scan.startup.mode' = 'latest-offset', -- 读取数据的位置
'format' = 'json', -- 数据源格式为 json
'json.fail-on-missing-field' = 'true', -- 字段丢失任务不失败
'json.ignore-parse-errors' = 'false' -- 解析失败跳过
)
但是,如果json里是可变的结构,并且,json是嵌套的,如果需要像hive里一样用jsonpath来获取元素值,那该怎么办?
经过若干次失败,用python实现了这个方法。而且在flinkSQL里就可以直接使用,用过的同事都叫好。
UDF 函数代码如下:
from pyflink.table import DataTypes
from pyflink.table.udf import udf
import jsonpath
import json
@udf(input_types=[DataTypes.STRING(),DataTypes.STRING()], result_type=DataTypes.STRING()
)
def json_get(k,s):
try:
js=json.loads(s)
except json.decoder.JSONDecodeError:
return ""
ret= jsonpath.jsonpath(js,k)
if not ret:
return ""
return str(ret[0])
如何执行
flink-1.12.2/bin/sql-client.sh embedded -e ./env.yaml -pyexec /data3/soft/pyflink/bin/python -pyfs ./test.py

在大数据处理中,面对包含JSON的数据,Flink SQL相较于Hive缺少现成的JSON解析函数。本文介绍了一种应对策略,特别是在处理结构不固定且嵌套的JSON时,通过编写Python UDF并在Flink SQL中使用,实现了类似Hive的jsonpath功能,以解决实时处理需求。提供了UDF代码示例及执行方法。
3168

被折叠的 条评论
为什么被折叠?



