#r #json #dataframe
Вопрос:
Я работаю с API Orbitly, и их API требует строки JSON в этом конкретном формате:
{
"requests": [
{
"params": {
"email": ["steve@woz.org"]
}
},
{
"params": {
"profile": ["https://www.linkedin.com/in/brianchesky/"]
}
},
{
"params": {
"phone": ["17186893174"]
}
},
{
"params": {
"name": ["marc benioff"],
"company": ["salesforce"]
}
}
],
"required": "profiles.network:linkedin AND (phone_numbers OR emails)"
}
Мои данные в настоящее время находятся в этом формате (импортированы из электронной таблицы).:
> df
# A tibble: 4 x 5
email profile phone name company
<chr> <chr> <chr> <chr> <chr>
1 steve@woz.org NA NA NA NA
2 NA https://www.linkedin.com/in/brianchesky/ NA NA NA
3 NA NA 17186893174 NA NA
4 NA NA NA marc benioff salesforce
Если я вызову jsonlite::toJSON
метод, я смогу преобразовать фрейм данных/tibble в формат, который в некотором роде близок, но, по понятным причинам, он ничего не объединяет в списки, и, насколько я могу судить, нет никакого способа заставить toJSON
использовать несколько неестественное объединение params
перед всем:
> print(toJSON(df, simplifyVector=FALSE, pretty=TRUE))
[
{
"email": "steve@woz.org"
},
{
"profile": "https://www.linkedin.com/in/brianchesky/"
},
{
"phone": "17186893174"
},
{
"name": "marc benioff",
"company": "salesforce"
}
]
Является ли моя единственная надежда на то, что этот фрейм данных будет сохранен в правильном формате, каким-то добавлением строки вручную? Или есть более умный способ применить этот toJSON
метод?
Ответ №1:
jsonlite::toJSON(list(
requests=unname(do.call(Map, c(list(f=function(...) list(params = Filter(Negate(is.na), list(...)))), df))),
required="profiles.network:linkedin AND (phone_numbers OR emails)"),
pretty = TRUE)
# {
# "requests": [
# {
# "params": {
# "email": ["steve@woz.org"]
# }
# },
# {
# "params": {
# "profile": ["https://www.linkedin.com/in/brianchesky/"]
# }
# },
# {
# "params": {
# "phone": ["17186893174"]
# }
# },
# {
# "params": {
# "name": ["marc benioff"],
# "company": ["salesforce"]
# }
# }
# ],
# "required": ["profiles.network:linkedin AND (phone_numbers OR emails)"]
# }
Данные
df <- structure(list(email = c("steve@woz.org", NA, NA, NA), profile = c(NA, "https://www.linkedin.com/in/brianchesky/", NA, NA), phone = c(NA, NA, "17186893174", NA), name = c(NA, NA, NA, "marc benioff"), company = c(NA, NA, NA, "salesforce")), class = "data.frame", row.names = c(NA, 4L))
Комментарии:
1. Разве это не разбивает строки, если в них есть данные нескольких переменных? В требуемом формате API
marc benioff
иsalesforce
находятся вместе в JSON.2. Я понял после того, как мой пример был сломан, и не показал этого. Мои извинения за это. Я думаю, что ваш ответ все еще очень близок к тому, что я ищу. Извините, я должен был убедиться, что вопрос был точным, так что извините, что отредактировал его постфактум.
3. Ваше последнее редактирование ничего не сделало, чтобы продемонстрировать этот эффект или то, что вы ожидаете от него. Я не использовал
df
в вашем вопросе, поэтому изменение этого не изменило того, как это работает.4.Я не знаю, смогу ли я вместить здесь всю строку, но использование вашего
df
кода и вашего кода создает строку, включающую следующее:{"params": {"name": ["marc benioff"]}},{"params": {"company": ["salesforce"]}}
в то время как это должно привести к чему-то подобному в моем вопросе, с этим:{"params": {"name": ["marc benioff"],"company": ["salesforce"]}}
. Точки данных, которые находятся в той же строке в данных (как и в вашихdf
тоже), должны быть в конечном результате такими жеparams
, как в документации API.5. Спасибо. Я сохранил результат как
df_as_json
, а затем вызвалdf_as_json$required <- unbox(df_as_json$required)
, потому что этот API требует, чтобы все было в списке, кромеrequired
параметра. Однако ваш код был именно тем, что мне было нужно! Спасибо!