Lee JSON multilínea en Apache Spark

Estaba tratando de usar un archivo JSON como una pequeña base de datos. Después de crear una tabla de plantillas en DataFrame, lo consulté con SQL y obtuve una excepción. Aquí está mi código:

val df = sqlCtx.read.json("/path/to/user.json") df.registerTempTable("user_tt") val info = sqlCtx.sql("SELECT name FROM user_tt") info.show() 

df.printSchema() resultado:

 root |-- _corrupt_record: string (nullable = true) 

Mi archivo JSON:

 { "id": 1, "name": "Morty", "age": 21 } 

Exeption:

 Exception in thread "main" org.apache.spark.sql.AnalysisException: cannot resolve 'name' given input columns: [_corrupt_record]; 

¿Cómo puedo arreglarlo?

UPD

_corrupt_record es

 +--------------------+ | _corrupt_record| +--------------------+ | {| | "id": 1,| | "name": "Morty",| | "age": 21| | }| +--------------------+ 

UPD2

Es extraño, pero cuando reescribo mi JSON para hacerlo oneliner, todo funciona bien.

 {"id": 1, "name": "Morty", "age": 21} 

Entonces el problema está en una newline .

UPD3

Encontré en los documentos la siguiente oración:

Tenga en cuenta que el archivo que se ofrece como un archivo json no es un archivo JSON típico. Cada línea debe contener un objeto JSON válido e independiente. Como consecuencia, un archivo JSON multilínea regular generalmente fallará.

No es conveniente mantener JSON en dicho formato. ¿Hay alguna solución para deshacerse de la estructura de líneas múltiples de JSON o para convertirla en un oneliner?

Spark> = 2.2

Spark 2.2 introdujo la opción multiLine wholeFile multiLine que se puede usar para cargar archivos JSON (no JSONL):

 spark.read .option("multiLine", true).option("mode", "PERMISSIVE") .json("/path/to/user.json") 

Ver:

  • SPARK-18352 : analiza archivos JSON multilínea normales (no solo líneas JSON) .
  • SPARK-20980 : Cambie el nombre de la opción wholeFile a multiLine para JSON y CSV.

Spark <2.2

Bueno, usar datos formateados JSONL puede ser un inconveniente, pero argumentaré que ese no es el problema con la API, sino el formato en sí. JSON simplemente no está diseñado para procesarse en paralelo en sistemas distribuidos.

No proporciona ningún esquema y sin hacer algunas suposiciones muy específicas sobre su formato y forma, es casi imposible identificar correctamente los documentos de nivel superior. Podría decirse que este es el peor formato posible de imaginar para usar en sistemas como Apache Spark. También es bastante complicado y poco práctico escribir JSON válidos en sistemas distribuidos.

Dicho esto, si los archivos individuales son documentos JSON válidos (ya sea un documento único o una matriz de documentos) siempre puedes probar wholeTextFiles :

 spark.read.json(sc.wholeTextFiles("/path/to/user.json").values()) 

Solo para agregar a la respuesta de zero323, la opción en Spark 2.2+ para leer JSON multilínea se renombró a multiLine (consulte la documentación de Spark aquí ).

Por lo tanto, la syntax correcta es ahora:

 spark.read .option("multiLine", true).option("mode", "PERMISSIVE") .json("/path/to/user.json") 

Esto sucedió en https://issues.apache.org/jira/browse/SPARK-20980 .