Hive使用json_tuple, posexplode 解析 json

直接上例子,下面是我要處理的 json 數據格式

{
    "IP": "192.168.1.1",
    "appName": "sichuan_yunyingyong",
    "customEvent": [
        {
            "eventName": "xx1",
            "du": "xx",
            "timestamp": "1480521763049",
            "eventParams": {
                "ContentID": "yixiuge",
                "account": "13856976635",
                "networkType": "WIFI",
                "result": "0",
                "type": "11"
            }
        },
        {
            "eventName": "xx2",
            "du": "xx",
            "timestamp": "1480521763049",
            "eventParams": {
                "ContentID": "yixiuge",
                "account": "13856976636",
                "networkType": "WIFI",
                "result": "0",
                "type": "11"
            }
        }
    ]
}


這裏面有json對象,還有json array,json對象好解析,json array不好解析,接下來兩者都講解下,需要使用 lateral view

select

j1.j1_ip,

j1.j1_appName,

j2.j2_customEvent_json

FROM tab_json s

lateral view json_tuple(s.json, 'IP', 'appName', 'customEvent') j1 as j1_ip, j1_appName, j1_customEvent

lateral view posexplode(split(regexp_replace(regexp_replace(j1.j1_customEvent,'\\}\\,\\{','\\}\\|\\|\\{'),'\\[|\\]',''), '\\|\\|')) j2 as j2_customEvents_pos, j2_customEvent_json

這個表 tab_json是包含json數據的表,json是json數據的字段,結果爲

192.168.1.1     sichuan_yunyingyong     {"eventName":"xx1","du":"xx","timestamp":"1480521763049","eventParams":{"ContentID":"yixiuge","account":"13856976635","networkType":"WIFI","result":"0","type":"11"}}

192.168.1.1     sichuan_yunyingyong     {"eventName":"xx2","du":"xx","timestamp":"1480521763049","eventParams":{"ContentID":"yixiuge","account":"13856976636","networkType":"WIFI","result":"0","type":"11"}}

json數據就是直接把key當成字段,直接把key作爲json_tuple方法的參數即可,這種解析json對象比較簡單,如json_tuple(s.json, 'IP') 就是取json中字段IP的值,

但是,爲什麼原來是一條記錄怎麼解析成2條記錄了呢,問題如下

posexplode(split(regexp_replace(regexp_replace(j1.j1_customEvent,'\\}\\,\\{','\\}\\|\\|\\{'),'\\[|\\]',''), '\\|\\|')) j2 as j2_customEvents_pos, j2_customEvent_json

我把json array的格式通過替換變成了 {json1} || {json2} , 這種格式再根據 || 來拆開,形成了一個有兩個元素的數組

注意:hive轉義符需要寫兩個 \

接着 posexplode 在把數組變成(pos, json) 的鍵值對,pos記錄了元素的位置,json就是實際的json數據,這樣一條數據就變成了兩條了,這點要注意,數據量因爲這種操作,成倍的增加


解釋了這點,那麼我想獲取IP , appName , account 字段怎麼辦呢,我直接給出sql語句了

select

j1.j1_ip,

j1.j1_appName,

j4.j4_account

FROM tab_json s

lateral view json_tuple(s.json, 'IP', 'appName', 'customEvent') j1 as j1_ip, j1_appName, j1_customEvent

lateral view posexplode(split(regexp_replace(regexp_replace(j1.j1_customEvent,'\\}\\,\\{','\\}\\|\\|\\{'),'\\[|\\]',''), '\\|\\|')) j2 as j2_customEvents_pos, j2_customEvent_json

lateral view json_tuple(j2.j2_customEvent_json, 'eventParams') j3 as j3_eventParams

lateral view json_tuple(j3.j3_eventParams, 'account') j4 as j4_account

結果如下:

192.168.1.1     sichuan_yunyingyong     13856976635

192.168.1.1     sichuan_yunyingyong     13856976636


上面的例子json array有兩個元素,如果你只關注其中一個元素,那麼可以如下操作

lateral view posexplode(array(split(regexp_replace(regexp_replace(j1.j1_customEvent,'\\}\\,\\{','\\}\\|\\|\\{'),'\\[|\\]',''), '\\|\\|')[1])) j2 as j2_customEvents_pos, j2_customEvent_json

split 跟上數組下標,就能取出某個元素,由於posexplode只接受 array類型的參數,可以使用array函數轉換成對應的數組,這樣就只有一條數據了,結果如下

192.168.1.1     sichuan_yunyingyong     13856976636



總結下:

在現在的hive版本中,hive 2還沒有試用,不知道是不是已經引入了json array的解析函數了,目前的版本是不能通過方法解析的,

思路是,通過給json array替換字符,由原來的 [ {} , {} ] 變成 {} || {} 這樣,在轉換成數組用 posexplode 函數,這樣就可以了

當然實際使用時數據放大也要注意,如果json array只有一個元素就不會放大

在只有一個元素的情況下,直接把 [ ] 去掉,用array 轉成數組即可

以後可以自己寫一個UDF來解析json array,欲知詳情,請聽下回分解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章