首先说下解析的数据如下:
{"username":"king","actionInfo":{"id":1,"age":"22","partList":[{"code":"123","uname":"king"},{"code":"0012","uname":"king"}]}}
刚开始看,这个就是一个Map结构嵌套了Map,再嵌套了一个数组结构。通常情况下的表结构定义如下:
create table dw_stg.test( username string, actionInfo_id string, actionInfo_age string, actionInfo_partlist array<Map<string,string>> ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' STORED AS TEXTFILE;
这样当数据来直接插入到hdfs中,然后利用explode就可以一行转多行扩展开了。
但是我的需求是这个actionInfo中的字段不固定的,可能是任意的结构,所以我定义的表结构中以string类型存放。如下:
create table dw_stg.test(
username string,
actionInfo string
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
STORED AS TEXTFILE;
这时候在做数据清洗时,需要通过json_tuple, get_json_object,explode等函数将string类型解析出来。
[{"code":"123","uname":"king"},{"code":"0012","uname":"king"}]
在字符串时针对上面中括号中等值解析时一直报错。
最后使用正则的方式,将中括号替换掉,然后在转化为数组,从而解析成功。参考以下代码:
select username,ai.id,ai.age,p.uname,p.code from test1 lateral view json_tuple(actioninfo,'id','age','partlist') ai as id,age,partlist lateral view explode(split(regexp_replace(regexp_extract(partlist,'^\[(.+)\]$',1),'\}\,\{', '\}\|\|\{'),'\|\|')) partlist as p lateral view json_tuple(p,'code','uname') p as code,uname
这里比较重要的一段是:
explode(split(regexp_replace(regexp_extract('包含中括号的字符串','^\[(.+)\]$',1),'\}\,\{', '\}\|\|\{'),'\|\|'))
解析过后的显示结果: