繁体   English   中英

在 Spark 中将数据帧转换为 json 时如何打印空值

[英]How can I print nulls when converting a dataframe to json in Spark

我有一个从 csv 读取的数据框。

CSV:
name,age,pets
Alice,23,dog
Bob,30,dog
Charlie,35,

Reading this into a DataFrame called myData:
+-------+---+----+
|   name|age|pets|
+-------+---+----+
|  Alice| 23| dog|
|    Bob| 30| dog|
|Charlie| 35|null|
+-------+---+----+

现在,我想使用myData.toJSON将此数据帧的每一行转换为 json。 我得到的是以下jsons。

{"name":"Alice","age":"23","pets":"dog"}
{"name":"Bob","age":"30","pets":"dog"}
{"name":"Charlie","age":"35"}

我希望第三行的 json 包含空值。 例如。

{"name":"Charlie","age":"35", "pets":null}

然而,这似乎是不可能的。 我通过代码调试,看到Spark的org.apache.spark.sql.catalyst.json.JacksonGenerator类有如下实现

  private def writeFields(
    row: InternalRow, schema: StructType, fieldWriters: 
    Seq[ValueWriter]): Unit = {
    var i = 0
    while (i < row.numFields) {
      val field = schema(i)
      if (!row.isNullAt(i)) {
        gen.writeFieldName(field.name)
        fieldWriters(i).apply(row, i)
      }
      i += 1
    }
  }

如果它为空,这似乎是跳过一列。 我不太确定为什么这是默认行为,但是有没有办法使用 Spark 的toJSON在 json 中打印空值?

我正在使用Spark 2.1.0

要使用 Spark 的toJSON方法打印 JSON 中的空值,您可以使用以下代码:

myData.na.fill("null").toJSON

它会给你预期的结果:

+-------------------------------------------+
|value                                      |
+-------------------------------------------+
|{"name":"Alice","age":"23","pets":"dog"}   |
|{"name":"Bob","age":"30","pets":"dog"}     |
|{"name":"Charlie","age":"35","pets":"null"}|
+-------------------------------------------+

我希望它有帮助!

我修改了 JacksonGenerator.writeFields 函数并包含在我的项目中。 下面是步骤——

1)在“src/main/scala/”中创建包“org.apache.spark.sql.catalyst.json”

2) 复制 JacksonGenerator 类

3) 在 '' 包中创建 JacksonGenerator.scala 类并粘贴复制的代码

4)修改writeFields函数

private def writeFields(row: InternalRow, schema: StructType, fieldWriters:Seq[ValueWriter]): Unit = {
var i = 0
while (i < row.numFields) {
  val field = schema(i)
  if (!row.isNullAt(i)) {
    gen.writeFieldName(field.name)
    fieldWriters(i).apply(row, i)
  }
  else{
    gen.writeNullField(field.name)
  }
  i += 1
}}
import org.apache.spark.sql.types._
import scala.util.parsing.json.JSONObject

def convertRowToJSON(row: Row): String = {
    val m = row.getValuesMap(row.schema.fieldNames).filter(_._2 != null)
    JSONObject(m).toString()
  }

用 Spark 3.0.0 测试:

创建spark.sql.jsonGenerator.ignoreNullFields会话时,将spark.sql.jsonGenerator.ignoreNullFields设置为 false。

toJSON函数在内部使用org.apache.spark.sql.catalyst.json.JacksonGenerator ,后者又使用org.apache.spark.sql.catalyst.json.JSONOptions进行配置。 后者包括一个选项ignoreNullFields 但是, toJSON使用默认值,在此特定选项的情况下,默认值取自上面给出的 sql 配置。

配置设置为 false 的示例:

val schema = StructType(Seq(StructField("a", StringType), StructField("b", StringType)))
val rows = Seq(Row("a", null), Row(null, "b"))
val frame = spark.createDataFrame(spark.sparkContext.parallelize(rows), schema)
println(frame.toJSON.collect().mkString("\n"))

产生

{"a":"a","b":null}
{"a":null,"b":"b"}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM