Ошибка синтаксического анализа: завершающий мусор при попытке проанализировать столбец JSON во фрейме данных

У меня есть файл журнала, который выглядит как этот. Это текстовый документ, который выглядит так:

Id,Date,Level,Message
35054,2016-06-17 19:29:43 +0000,INFO,"{
  ""id"": -2,
  ""ipAddress"": ""100.100.100.100"",
  ""howYouHearAboutUs"": null,
  ""isInterestedInOffer"": true,
  ""incomeRange"": 60000,
  ""isEmailConfirmed"": false
}"
35055,2016-06-17 19:36:38 +0000,INFO,"{
  ""id"": -1,
  ""firstName"": ""John"",
  ""lastName"": ""Smith"",
  ""email"": ""[email protected]"",
  ""city"": ""Smalltown"",
  ""incomeRange"": 1,
  ""birthDate"": ""1999-12-10T05:00:00Z"",
  ""password"": ""*********"",
  ""agreeToTermsOfUse"": true,
  ""howYouHearAboutUs"": ""Radio"",
  ""isInterestedInOffer"": false
}"
35059,2016-07-19 19:52:08 +0000,INFO,"{
  ""id"": -3,
  ""visitUrl"": ""https://www.website.com/?purpose=X"",
  ""ipAddress"": ""100.200.300.400"",
  ""howYouHearAboutUs"": null,
  ""isInterestedInOffer"": true,
  ""incomeRange"": 100000,
  ""isEmailConfirmed"": true,
  ""isIdentityConfirmed"": false,
  ""agreeToTermsOfUse"": true,
  ""validationResults"": null
}"

Я пытаюсь разобрать JSON в столбце Message следующим образом:

library(readr)
library(jsonlite)

df <- read_csv("log_file_from_above.csv")
fromJSON(as.character(df$Message))

Но я получаю следующую ошибку:

Error: parse error: trailing garbage
          "isEmailConfirmed": false  } {    "id": -1,    "firstName": 
                     (right here) ------^

Как я могу избавиться от хвостового мусора?


person emehex    schedule 09.08.2016    source источник
comment
lapply(paste0("[",df$Message,"]"), function(x) jsonlite::fromJSON(x)) что-то дает?   -  person Abdou    schedule 09.08.2016
comment
Я скопировал блок данных json из html-документа в новый текстовый файл и также получил эту ошибку. Вторя приведенному выше комментарию, что решило эту проблему для меня, вручную добавив одну открытую скобку ( [ ) вверху моего текстового файла данных json и одну закрывающую скобку ( ] ) в конце.   -  person Omar Wasow    schedule 09.05.2018


Ответы (1)


fromJSON() не «применяется» к вектору символов, он пытается преобразовать все это во фрейм данных. Можешь попробовать

purrr::map(df$Message, jsonlite::fromJSON)

что предоставил @Abdou или

jsonlite::stream_in(textConnection(gsub("\\n", "", df$Message)))

Последние два будут создавать фреймы данных. Первый создаст список, который вы можете добавить в виде столбца.

Вы можете использовать последний метод с dplyr::bind_cols, чтобы создать новый фрейм данных со всеми данными:

dplyr::bind_cols(df[,1:3],
                 jsonlite::stream_in(textConnection(gsub("\\n", "", df$Message))))

@Abdou также предлагает почти чистое базовое решение R:

cbind(df, do.call(plyr::rbind.fill, lapply(paste0("[",df$Message,"]"), function(x) jsonlite::fromJSON(x))))

Полный, рабочий, рабочий процесс:

library(dplyr)
library(jsonlite)

df <- read.table("http://pastebin.com/raw/MMPMwNZv",
                 quote='"', sep=",", stringsAsFactors=FALSE, header=TRUE)

bind_cols(df[,1:3], stream_in(textConnection(gsub("\\n", "", df$Message)))) %>%
  glimpse()
## 
 Found 3 records...
 Imported 3 records. Simplifying into dataframe...
## Observations: 3
## Variables: 19
## $ Id                  <int> 35054, 35055, 35059
## $ Date                <chr> "2016-06-17 19:29:43 +0000", "2016-06-17 1...
## $ Level               <chr> "INFO", "INFO", "INFO"
## $ id                  <int> -2, -1, -3
## $ ipAddress           <chr> "100.100.100.100", NA, "100.200.300.400"
## $ howYouHearAboutUs   <chr> NA, "Radio", NA
## $ isInterestedInOffer <lgl> TRUE, FALSE, TRUE
## $ incomeRange         <int> 60000, 1, 100000
## $ isEmailConfirmed    <lgl> FALSE, NA, TRUE
## $ firstName           <chr> NA, "John", NA
## $ lastName            <chr> NA, "Smith", NA
## $ email               <chr> NA, "[email protected]", NA
## $ city                <chr> NA, "Smalltown", NA
## $ birthDate           <chr> NA, "1999-12-10T05:00:00Z", NA
## $ password            <chr> NA, "*********", NA
## $ agreeToTermsOfUse   <lgl> NA, TRUE, TRUE
## $ visitUrl            <chr> NA, NA, "https://www.website.com/?purpose=X"
## $ isIdentityConfirmed <lgl> NA, NA, FALSE
## $ validationResults   <lgl> NA, NA, NA
person hrbrmstr    schedule 09.08.2016
comment
Как я могу использовать purrr::map(df$Message, jsonlite::fromJSON) в кадре данных? Чтобы я не потерял временные метки? - person emehex; 09.08.2016
comment
@hrbrmstr, можешь добавить cbind(df[,1:3], do.call(plyr::rbind.fill, lapply(paste0("[",df$Message,"]"), function(x) jsonlite::fromJSON(x))))? Он использует пакет plyr. - person Abdou; 09.08.2016
comment
Все еще получаете ошибку синтаксического анализа с dplyr::bind_cols(df[,1:3], jsonlite::stream_in(textConnection(gsub("\\n", "", df$Message)))) ? Вы используете файл pastebin с сохраненным странным отступом? - person emehex; 09.08.2016