2016-07-23 16 views
5

Próbowałem użyć pliku JSON jako małej bazy danych. Po utworzeniu tabeli szablonów w DataFrame odpytałem ją za pomocą SQL i otrzymałem wyjątek. Tu jest mój kodu:Czytaj wielowierszowy JSON w Apache Spark

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

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

Mój plik 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]; 

Jak mogę to naprawić?

UPD

_corrupt_record jest

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

UPD2

To dziwne, ale kiedy przepisać moje JSON, aby go oneliner, wszystko działa bez zarzutu.

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

Problem dotyczy numeru newline.

UPD3

znalazłem w docs następne zdanie:

Zauważ, że plik, który oferowany jest w postaci pliku json nie jest to typowy plik JSON. Każda linia musi zawierać oddzielny, samodzielny poprawny obiekt JSON. W związku z tym zwykły wieloliniowy plik JSON najczęściej kończy się niepowodzeniem.

Nie jest wygodne utrzymywanie JSON w takim formacie. Czy istnieje obejście pozwalające pozbyć się wielowątkowej struktury JSON lub przekonwertować ją w onelinera?

Odpowiedz

14

Spark> = 2,2

Spark 2.2 wprowadzono wholeFilemultiline opcji, która może być używana do ładowania JSON (nie JSONL) pliki:

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

Patrz:

  • SPARK-18352 - Parsuj normalny, wielowierszowy JSON fi les (nie tylko JSON Lines).
  • SPARK-20980 - Zmień nazwę opcji wholeFile na multiLine dla JSON i CSV.

Spark < 2.2

Cóż, używanie sformatowanych danych JSONL może być niewygodne, ale będę twierdził, że to nie problem z API, ale sam format. JSON nie jest po prostu zaprojektowany do równoległego przetwarzania w systemach rozproszonych.

Nie zawiera schematu i bez pewnych bardzo konkretnych założeń dotyczących jego formatowania i kształtu jest prawie niemożliwe, aby poprawnie zidentyfikować dokumenty najwyższego poziomu. Prawdopodobnie jest to najgorszy z możliwych format do wykorzystania w systemach takich jak Apache Spark. Jest również dość trudne i zazwyczaj niepraktyczne pisanie poprawnego JSON w systemach rozproszonych.

W takiej sytuacji, jeśli poszczególne pliki są ważne dokumenty JSON (albo pojedynczy dokument lub tablicą dokumentów) zawsze można spróbować wholeTextFiles:

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

Wystarczy dodać do zero323 za odpowiedź, opcję w Spark 2.2+ do odczytu wieloliniowego JSON został przemianowany na multiLine (patrz dokumentacja Spark here).

Dlatego poprawna składnia jest teraz:

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

To zdarzyło się w https://issues.apache.org/jira/browse/SPARK-20980.

+0

Opcja "wielowierszowa" sprawdziła się u mnie. Dzięki Dan! – Omkar