使用嵌套数组raw spark sql分解数组

z0qdvdin  于 2021-06-24  发布在  Hive
关注(0)|答案(1)|浏览(418)

我有以下json结构,它作为字符串存储在我的配置单元表列中

[  
{"outer_id": 123000, "outer_field_1": blah, "inner_list": [{"inner_id": 456}, {"inner_id": 789}]},  
{"outer_id": 123001, "outer_field_1": blahblah, "inner_list": [{"inner_id": 456}, {"inner_id": 789}]},  
{"outer_id": 123002, "outer_field_1": blahblahblah,  "inner_list": [{"inner_id": 456}, {"inner_id": 789}]},  
]

现在我想把它解析成一个表,表中的元素以每行的形式表示。每个json对象的字段被解析为每一列,同时仍将内部列表保留为字符串:

| outer_id | outer_field_1 | inner_list  |   |   |   
|----------|---------------|-------------|---|---|  
| 123000   |  blah         |  struct     |   |   |  
| 123001   |  blahblah     |  struct     |   |   |  
| 123002   |  blahblahblah |  struct     |   |   |

现在我知道了使用regex创建自定义分隔符的诀窍,在其上拆分,然后使用横向视图分解,但是在本例中,还有嵌套数组将与regex匹配:使用hive解析json数组
有什么办法吗?如果可能的话,我想用原始的sparksql来做这个。没有自定义项或农奴。
我尝试过: select explode(get_json_object(outer_list, "$[*]")) from wt_test; 不起作用,它说函数explode的输入应该是数组或Map类型,而不是字符串 select explode(split(substr(outer_list, 2, length(strategies)-2),",")) from wt_test; 这会将每个逗号拆分为一行,这不是我们想要的:

{"outer_id": 123000
"outer_field_1": blah
"inner_list": [{"inner_id": 456}
{"inner_id": 789}]}
... more rows ...
2admgd59

2admgd591#

假设我理解正确,你有以下几点:

输入

{
   "some_id":1,
   "outer_list":'[{"outer_id": 123000, "outer_field_1": "blah", "inner_list": [{"inner_id": 456}, {"inner_id": 789}]}, {"outer_id": 123001, "outer_field_1": "blahblah", "inner_list": [{"inner_id": 456}, {"inner_id": 789}]}, {"outer_id": 123002, "outer_field_1": "blahblahblah", "inner_list": [{"inner_id": 456}, {"inner_id": 789}]}]'
}

期望输出:

| outer_id | outer_field_1 | inner_list  |   |   |   
|----------|---------------|-------------|---|---|  
| 123000   |  blah         |  struct     |   |   |  
| 123001   |  blahblah     |  struct     |   |   |  
| 123002   |  blahblahblah |  struct     |   |   |

首先,您需要将字符串解析为一个模式,以便定义一个模式:

schema = ArrayType(
   StructType([StructField('outer_id', IntegerType()), 
               StructField('outer_field_1', StringType()), 
               StructField('inner_list', StringType())])
)

请注意,这是一个简单的版本,其中内部的\u列表只是作为字符串。
在Dataframe上应用该架构:

df = df.select(from_json('outer_list', schema).alias('test'))

现在您有了一个带有数组的列:

+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|test                                                                                                                                                                       |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|[[123000, blah, [{"inner_id":456},{"inner_id":789}]], [123001, blahblah, [{"inner_id":456},{"inner_id":789}]], [123002, blahblahblah, [{"inner_id":456},{"inner_id":789}]]]|
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

你现在可以爆炸了:

df.select(explode('test').alias('exploded')).select('exploded.*')

因此:

+--------+-------------+-----------------------------------+
|outer_id|outer_field_1|inner_list                         |
+--------+-------------+-----------------------------------+
|123000  |blah         |[{"inner_id":456},{"inner_id":789}]|
|123001  |blahblah     |[{"inner_id":456},{"inner_id":789}]|
|123002  |blahblahblah |[{"inner_id":456},{"inner_id":789}]|
+--------+-------------+-----------------------------------+

现在,当您仍然在解析外部的\u列表时,您可以从一开始就对内部的\u列表执行相同的操作。但你应该先自己试试,这里有你需要的一切。
别忘了导入:

from pyspark.sql.functions import *
from pyspark.sql.types import *

sql版本如果输入以表json\U test的形式给出:

select exploded.* from 
   (select explode(
             from_json(
               outer_list, 
    "array<struct<outer_id:int,outer_field_1:string,inner_list:string>>"
       )
    ) as exploded from json_test
)

相关问题