当包含在DataRicks Spark dataframe select中时,结构的JSON数组会生成一行空值

2024-04-24 11:44:15 发布

您现在位置:Python中文网/ 问答频道 /正文

在使用Azure DataRicks将JSON文件处理为Spark数据帧时,我遇到了一个奇怪的问题。JSON文件本身由一组结构(对象)组成,对象很复杂,包括嵌套的数组/结构

将JSON加载到数据帧后,我想分解“key_list”,其值是一个结构数组。当我只包含“id”值时,我的DataFrame select返回了100行,但一旦我将“key_list”添加到select中,结果就是一行空值。尽管DataFrame似乎已经正确地推断出了模式,但仍然存在这种情况

下面是一些重新创建问题的代码(简化为在数组中只包含两个顶级对象),我附上了一个在Azure Databricks中运行时看到的结果的屏幕截图。任何人都可以识别导致数据丢失的原因,而不是在第二列中返回两行的两个id值和表示为数组的key_列表吗

source_json = """
[
    {
        "id": 1,
        "key_list": [
            {
                "obj_key_id": "bp_nr",
                "val": "90000804",
                "prio": "",
                "ref_obj_id": "",
                "rule_id": "",
                "rule_templ_id": "",
                "seq_nr": 1,
                "trig_meta_typ_id": "",
                "trig_order_type_id": ""
            },
            {
                "obj_key_id": "bp_sym",
                "val": "CCC.CRST.BDJ02",
                "prio": "",
                "ref_obj_id": "",
                "rule_id": "",
                "rule_templ_id": "",
                "seq_nr": 1,
                "trig_meta_typ_id": "",
                "trig_order_type_id": ""
            },
            {
                "obj_key_id": "bp_swift",
                "val": "CRSTGB22XXX",
                "prio": "",
                "ref_obj_id": "",
                "rule_id": 1,
                "rule_templ_id": "",
                "seq_nr": 1,
                "trig_meta_typ_id": "",
                "trig_order_type_id": ""
            },
            {
                "obj_key_id": "bp_swift",
                "val": "CRSTGB20XXX",
                "prio": "0100",
                "ref_obj_id": "",
                "rule_id": 2,
                "rule_templ_id": "",
                "seq_nr": 2,
                "trig_meta_typ_id": "",
                "trig_order_type_id": ""
            },
            {
                "obj_key_id": "bp_clr",
                "val": "BDJ02",
                "prio": "1000",
                "ref_obj_id": 45046,
                "rule_id": 1,
                "rule_templ_id": "",
                "seq_nr": 1,
                "trig_meta_typ_id": "",
                "trig_order_type_id": ""
            }
        ]
    },
    {
        "id": 2,
        "key_list": [
            {
                "obj_key_id": "bp_nr",
                "val": "90000804",
                "prio": "",
                "ref_obj_id": "",
                "rule_id": "",
                "rule_templ_id": "",
                "seq_nr": 1,
                "trig_meta_typ_id": "",
                "trig_order_type_id": ""
            },
            {
                "obj_key_id": "bp_sym",
                "val": "CCC.CRST.BDJ02",
                "prio": "",
                "ref_obj_id": "",
                "rule_id": "",
                "rule_templ_id": "",
                "seq_nr": 1,
                "trig_meta_typ_id": "",
                "trig_order_type_id": ""
            },
            {
                "obj_key_id": "bp_swift",
                "val": "CRSTGB22XXX",
                "prio": "",
                "ref_obj_id": "",
                "rule_id": 1,
                "rule_templ_id": "",
                "seq_nr": 1,
                "trig_meta_typ_id": "",
                "trig_order_type_id": ""
            },
            {
                "obj_key_id": "bp_swift",
                "val": "CRSTGB20XXX",
                "prio": "0100",
                "ref_obj_id": "",
                "rule_id": 2,
                "rule_templ_id": "",
                "seq_nr": 2,
                "trig_meta_typ_id": "",
                "trig_order_type_id": ""
            },
            {
                "obj_key_id": "bp_clr",
                "val": "BDJ02",
                "prio": "1000",
                "ref_obj_id": 45046,
                "rule_id": 1,
                "rule_templ_id": "",
                "seq_nr": 1,
                "trig_meta_typ_id": "",
                "trig_order_type_id": ""
            }
        ]
    }
]
"""

dbutils.fs.put(file="/tmp/source.json", contents=source_json)

source_df = spark.read.option("multiline", "true").json(path="/tmp/source.json")
display(source_df)

result screenshot

更新: 我已经确定根本原因是key_list属性ref_obj_id和rule_id的推断模式,这两个属性都被推断为Long类型。如果我手动双引号引用通过的整数值,推断出的模式会将这些值键入字符串,然后一切正常。我还可以通过手动构建模式并在spark.read中应用该模式来实现相同的结果

但是,编辑源文件或手动构建模式并不理想,特别是因为此特定示例中的模式表示一种简化,而真正的模式比此要大得多、复杂得多。我想使用spark.read推断一个模式,然后在一个字符串变量中捕获该模式,在模式定义中将每个非字符串简单类型强制更改为字符串,然后使用这个动态生成的模式字符串变量创建一个实际的模式,然后通过第二个spark.read调用使用该模式。这是可能的(基本上是利用来自某个源文件的自动模式推断,但强制该模式的每个简单类型都是字符串类型),如果是,如何实现