Опитвах се да използвам JSON файл като малка БД. След като създадох таблица с шаблони в DataFrame, го попитах с SQL и получих изключение. Ето моят код:
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)
Моят JSON файл:
{
"id": 1,
"name": "Morty",
"age": 21
}
освен в случаите:
Exception in thread "main" org.apache.spark.sql.AnalysisException: cannot resolve "name" given input columns: [_corrupt_record];
Как мога да го поправя?
UPD
_corrupt_record
е
+--------------------+
| _corrupt_record|
+--------------------+
| {|
| "id": 1,|
| "name": "Morty",|
| "age": 21|
| }|
+--------------------+
UPD2
Странно е, но когато пренапиша JSON, за да го направя еднолинейно, всичко работи добре.
{"id": 1, "name": "Morty", "age": 21}
Така че проблемът е в a newline
.
UPD3
Намерих в документи следващото изречение:
Обърнете внимание, че файлът, който се предлага като json файлне е типичен JSON файл. Всеки ред трябва да съдържа отделен, самостоятелен валиден JSON обект. В резултат на това редовен многоредов JSON файл най-често ще се провали.
Не е удобно да поддържате JSON в такъв формат. Има ли някакво решение, за да се отървете от многопластовата структура на JSON или да го преобразувате в oneliner?
Отговори:
21 за отговор № 1Искри> = 2.2
Въведена искра 2.2 wholeFile
multiLine
опция, която може да се използва за зареждане на файлове JSON (не JSONL):
spark.read
.option("multiLine", true).option("mode", "PERMISSIVE")
.json("/path/to/user.json")
Виж:
- SPARK-18352 - Разбор на нормални многоредови JSON файлове (не само JSON линии).
- SPARK-20980 - Преименувайте опцията
wholeFile
да сеmultiLine
за JSON и CSV.
Искрица <2.2
Е, използването на форматирани данни от JSONL може да бъденеудобно, но ще твърдя, че не е проблемът с API, а самият формат. JSON просто не е проектиран да се обработва паралелно в разпределени системи.
Той не предоставя схема и без да прави някоимного специфични предположения за неговото форматиране и форма е почти невъзможно правилно да се идентифицират документи от най-високо ниво. Може би това е най-лошият възможен формат за използване в системи като Apache Spark. Също така е доста сложно и обикновено непрактично да се пише валиден JSON в разпределени системи.
Като се има предвид, ако отделните файлове са валидни документи JSON (или единичен документ, или масив от документи), винаги можете да опитате wholeTextFiles
:
spark.read.json(sc.wholeTextFiles("/path/to/user.json").values())
3 за отговор № 2
Само за да добавите отговора на zero323, опцията в Spark 2.2+ за четене на многоредов JSON беше преименувана на multiLine
(вижте документацията за Spark тук).
Ето защо сега правилният синтаксис е:
spark.read
.option("multiLine", true).option("mode", "PERMISSIVE")
.json("/path/to/user.json")
Това се случи в https://issues.apache.org/jira/browse/SPARK-20980.