2016-01-14 1 views
2

API-интерфейс, я использую потребности, чтобы я послал ему сообщение JSON как в:кодирующая выражение JSON из R с jsonlite или что-то еще

y <- '[{"a":1, "b":"select", "c":["A", "B", "C"]}, 
     {"a":2, "b":"text"}, 
     {"a":3, "b":"select", "c":["D", "E", "F", "G"]}]' 

Обратите внимание, что в случае "b" : "select" есть еще одна переменная c с значение - массив.

При попытке запуска fromJSON(y)jsonlite пакете) я получаю data.frame, где третий столбец списка:

> z <- fromJSON(y) 
> class(z) 
[1] "data.frame" 
> z %>% glimpse() 
Observations: 3 
Variables: 3 
$ a (int) 1, 2, 3 
$ b (chr) "select", "text", "select" 
$ c (list) A, B, C, NULL, D, E, F, G 

Но когда я преобразовать его обратно в JSON(который является формат, я хочу для отправки в API), переменная c появляется там, где ее не должно быть.

[{"a":1,"b":"select","c":["A","B","C"]}, 
{"a":2,"b":"text","c":{}}, 
{"a":3,"b":"select","c":["D","E","F","G"]}] 

Есть еще одна структура данных R, которые могли бы надежно получить меня из кадра данных исходного JSON сообщения с помощью jsonlite (или что-то еще)? Как это сработает?

+0

Я думаю, что если вы используете 'RJSONIO: fromJSON', а затем' jsonlite :: toJSON' вы получите то, что вы хотите. –

ответ

5

с jsonlite, вы можете сделать следующее:

z <- fromJSON(y, simplifyDataFrame = F) 
toJSON(z, auto_unbox=T) 

Кроме того, рассмотрим следующий случай, когда последний c элемент ["D"]:

y2 <- '[{"a":1, "b":"select", "c":["A", "B", "C"]}, 
     {"a":2, "b":"text"}, 
     {"a":3, "b":"select", "c":["D"]}]' 

z2 <- fromJSON(y2, simplifyDataFrame = F) 
toJSON(z2, auto_unbox=T) 

Результат таков:

[{"a":1,"b":"select","c":["A","B","C"]}, 
{"a":2,"b":"text"}, 
{"a":3,"b":"select","c":"D"}] 

Это может быть проблема, потому что последние c элемент "D" не ["D"].

Чтобы предотвратить это, не используйте auto_unbox. Используйте unbox тщательно следующим образом:

z2 <- fromJSON(y2, simplifyDataFrame = F) 
for(i in 1:length(z2)){ 
    z2[[i]][[1]] <- unbox(z2[[i]][[1]]) 
    z2[[i]][[2]] <- unbox(z2[[i]][[2]]) 
} 
toJSON(z2) 
+0

О, это для меня тоже! Узнал что-то: D –

+0

Это отличная подсказка - я долго боролся с этой проблемой. – Iain

1

Если вам нужно иметь фрейм данных для вычисления вещи, вы могли бы сделать (функция rmNullObs от here):

z <- fromJSON(y) 

is.NullOb <- function(x) is.null(x) | all(sapply(x, is.null)) 

## Recursively step down into list, removing all such objects 
rmNullObs <- function(x) { 
    x <- Filter(Negate(is.NullOb), x) 
    lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x) 
}  

z_list <- rmNullObs(as.list(as.data.frame(t(z)))) 
toJSON(unname(z_list), auto_unbox=T) 

Это превращает dataframe к список, удаляет NULL и преобразует обратно в JSON.

Если вы не нуждаетесь в dataframe см @ ответ skwon в

+0

Это похоже на то, что я ищу, но я получаю: '{" 1 ": {" a ": 1," b ":" select "," c ": [" A "," B " , "С"]}, "2": { "а": 2, "б": "текст"}, "3": { "а": 3, "б": "выбрать", "C": ["D", "E", "F", "G"]}} 'из вашего кода. Мне нужна внешняя структура данных как массив. – wdkrnls

+1

забыли «игнорировать» список, исправили его. – NicE

Смежные вопросы