Leggi il JSON multilinea in Apache Spark

Stavo cercando di utilizzare un file JSON come un piccolo DB. Dopo aver creato una tabella di template su DataFrame, l’ho interrogato con SQL e ottenuto un’eccezione. Ecco il mio codice:

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() :

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

Il mio file 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]; 

Come posso ripararlo?

UPD

_corrupt_record is

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

UPD2

È strano, ma quando riscrivo il mio JSON per renderlo oneliner, tutto funziona perfettamente.

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

Quindi il problema è in una newline .

UPD3

Ho trovato in documenti la frase successiva:

Si noti che il file offerto come file JSON non è un tipico file JSON. Ogni riga deve contenere un object JSON valido, separato e autonomo. Di conseguenza, un normale file JSON multilinea spesso fallisce.

Non è conveniente mantenere JSON in tale formato. C’è qualche soluzione per sbarazzarsi della struttura multi-foderata di JSON o convertirla in oneliner?

Spark> = 2.2

Spark 2.2 ha introdotto l’opzione wholeFile multiLine che può essere utilizzata per caricare file JSON (non JSONL):

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

Vedere:

  • SPARK-18352 – Analizza file JSON normali, multilinea (non solo linee JSON) .
  • SPARK-20980 – Rinomina l’opzione wholeFile su multiLine per JSON e CSV.

Spark <2.2

Bene, l’uso di dati formulati da JSONL può essere sconveniente ma sosterrò che non è il problema con l’API ma il formato stesso. JSON semplicemente non è progettato per essere elaborato in parallelo in sistemi distribuiti.

Non fornisce schemi e senza fare alcune ipotesi molto specifiche sulla sua formattazione e forma è quasi imansible identificare correttamente i documenti di livello superiore. Probabilmente questo è il peggior formato ansible da immaginare per l’uso in sistemi come Apache Spark. È anche abbastanza complicato e in genere poco pratico scrivere un JSON valido nei sistemi distribuiti.

Detto questo, se i singoli file sono documenti JSON validi (singoli documenti o array di documenti), puoi sempre provare wholeTextFiles :

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

Solo per aggiungere alla risposta di zero323, l’opzione in Spark 2.2+ per leggere JSON multilinea è stata rinominata multiLine (vedere la documentazione Spark qui ).

Pertanto, la syntax corretta è ora:

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

Questo è successo in https://issues.apache.org/jira/browse/SPARK-20980 .