spark中类Json结构的解析

spark中类Json结构的解析,json,scala,apache-spark,apache-spark-sql,Json,Scala,Apache Spark,Apache Spark Sql,我有一个数据结构如下的文件 {'analytics_category_id': 'Default', 'item_sub_type': '', 'deleted_at': '', 'product_category_id': 'Default', 'unit_price': '0.000', 'id': 'myntramprdii201907174a72fb2475d84103844083d1348acb9e', 'is_valid': True, 'measurement_uom_id': '

我有一个数据结构如下的文件

{'analytics_category_id': 'Default', 'item_sub_type': '', 'deleted_at': '', 'product_category_id': 'Default', 'unit_price': '0.000', 'id': 'myntramprdii201907174a72fb2475d84103844083d1348acb9e', 'is_valid': True, 'measurement_uom_id': '', 'description': '', 'invoice_type': 'receivable_debit_note', 'linked_core_invoice_item_id': '', 'ref_3': '741423', 'ref_2': '6001220139357318', 'ref_1': '2022-07-04', 'tax_rate': '0.000', 'reference_id': '', 'ref_4': '', 'product_id': 'Default', 'total_amount': '0.000', 'tax_auth_party_id': '', 'item_type': 'Product', 'invoice_item_attributes': '', 'core_invoice_id': 'myntramprdi20190717a1e925911345463393bc4ac1b124dbe5', 'tax_auth_geo_id': '', 'quantity': 1}


{'analytics_category_id': 'Default', 'item_sub_type': '', 'deleted_at': '', 'product_category_id': 'Default', 'unit_price': '511.000', 'id': 'myntramprdii20190717c749a96d2e7144aea7fc5125287717f7', 'is_valid': True, 'measurement_uom_id': '', 'description': '', 'invoice_type': 'receivable_debit_note', 'linked_core_invoice_item_id': '', 'ref_3': '741424', 'ref_2': '6001220152640260', 'ref_1': '2022-07-07', 'tax_rate': '0.000', 'reference_id': '', 'ref_4': '', 'product_id': 'Default', 'total_amount': '511.000', 'tax_auth_party_id': '', 'item_type': 'Product', 'invoice_item_attributes': '', 'core_invoice_id': 'myntramprdi20190717a1e925911345463393bc4ac1b124dbe5', 'tax_auth_geo_id': '', 'quantity': 1}
我正试图用scala在Spark中解析这一点,并从中创建一个数据帧,但由于结构原因,无法这样做。我想用替换“但是我的文本也可以有相同的。我需要的是数据的键值对

到目前为止,我已经尝试:

read.option("multiline", "true").json("s3://******/*********/prod_flattener/y=2019/m=07/d=17/type=flattened_core_invoices_items/invoice_items_2019_07_17_23_53_19.txt") 
我确实成功地将此作为多行文本阅读:

read.option("multiline", "true").textFile("s3://********/*********/prod_flattener/y=2019/m=07/d=17/type=flattened_core_invoices_items/invoice_items_2019_07_17_23_53_19.txt")

现在如何将键读取为列?

您的问题链接到条目中用作布尔值的真值:这在JSON中无效,需要

如果您的数据集不是很大,最简单的方法是作为文本加载,修复此问题,写入固定数据,然后将其作为json重新打开

import spark.implicits._
import org.apache.spark.sql.types._

val initial = spark.read.text("s3://******/*********/prod_flattener/y=2019/m=07/d=17/type=flattened_core_invoices_items/invoice_items_2019_07_17_23_53_19.txt") 

val fixed = initial
    .select(regexp_replace('value,"\\bTrue\\b","true") as "value")
    .select(regexp_replace('value,"\\bFalse\\b","false") as "value")

fixed.write.mode("overwrite").text("/tmp/fixed_items")

val json_df = spark.read.json("/tmp/fixed_items")
json_df: org.apache.spark.sql.DataFrame = [analytics_category_id: string, core_invoice_id: string ... 23 more fields]
如果不想创建临时数据集,可以直接使用from_json解析固定文本值,但需要事先在spark中手动定义模式,并在解析后进行一些列重命名:

val jsonSchema = StructType.fromDDL("`analytics_category_id` STRING,`core_invoice_id` STRING,`deleted_at` STRING,`description` STRING,`id` STRING,`invoice_item_attributes` STRING,`invoice_type` STRING,`is_valid` BOOLEAN,`item_sub_type` STRING,`item_type` STRING,`linked_core_invoice_item_id` STRING,`measurement_uom_id` STRING,`product_category_id` STRING,`product_id` STRING,`quantity` BIGINT,`ref_1` STRING,`ref_2` STRING,`ref_3` STRING,`ref_4` STRING,`reference_id` STRING,`tax_auth_geo_id` STRING,`tax_auth_party_id` STRING,`tax_rate` STRING,`total_amount` STRING,`unit_price` STRING")

val jsonParsingOptions: Map[String,String] = Map()

val json_df = fixed
     .select(from_json('value, jsonSchema, jsonParsingOptions) as "j")
     .select(jsonSchema.map(f => 'j.getItem(f.name).as(f.name)):_*)
json_df: org.apache.spark.sql.DataFrame = [analytics_category_id: string, core_invoice_id: string ... 23 more fields]


另外,从您发布的代码片段来看,您似乎不需要多行选项,但如果确实需要,则需要将该选项添加到jsonParsingOptions映射中。

尝试了以下操作:val fixed=coreinvoiceData。选择regexp\u replacecoreinvoiceData.colvalue,\\b确实\\b,值为true。选择regexp\u replacecoreinvoiceData.colvalue,\\b false\\b,false as value1,但我在线程main org.apache.spark.sql.AnalysisException中遇到异常:已解析属性value0在运算符的value11中丢失。这是一个AnalysisException:这意味着,当spark试图找出coreinvoiceData的架构时,它会发现两个可能存在差异的值列,并且不知道您指的是哪一个。这是一个如何创建这个数据框架的问题。是的。。明白了,谢谢。尽管如此,这个解决方案并没有起到任何作用。我尝试了var json_df=coreinvoiceData.selectfrom_jsoncoreinvoiceData.colvalue、jsonSchema、jsonParsingOptions.aliasj json_df=json_df.selectjsonSchema.mapf=>json_df.colj.getItemf.name.aliasf.name:.*但我在DataFrame的所有列中都得到了null解决方案是有效的,因为您实际上得到了作为列的解析数据帧。所有空列都可能意味着强制jsonSchema中的列名与json文件中的列名不匹配。正如我所写的,保存一个临时数据集并重新读取它更容易使其正常工作。首先,至少要找出正确的模式。
val jsonSchema = StructType.fromDDL("`analytics_category_id` STRING,`core_invoice_id` STRING,`deleted_at` STRING,`description` STRING,`id` STRING,`invoice_item_attributes` STRING,`invoice_type` STRING,`is_valid` BOOLEAN,`item_sub_type` STRING,`item_type` STRING,`linked_core_invoice_item_id` STRING,`measurement_uom_id` STRING,`product_category_id` STRING,`product_id` STRING,`quantity` BIGINT,`ref_1` STRING,`ref_2` STRING,`ref_3` STRING,`ref_4` STRING,`reference_id` STRING,`tax_auth_geo_id` STRING,`tax_auth_party_id` STRING,`tax_rate` STRING,`total_amount` STRING,`unit_price` STRING")

val jsonParsingOptions: Map[String,String] = Map()

val json_df = fixed
     .select(from_json('value, jsonSchema, jsonParsingOptions) as "j")
     .select(jsonSchema.map(f => 'j.getItem(f.name).as(f.name)):_*)
json_df: org.apache.spark.sql.DataFrame = [analytics_category_id: string, core_invoice_id: string ... 23 more fields]