Skip to content

Commit

Permalink
Fix json_structure
Browse files Browse the repository at this point in the history
  • Loading branch information
colearendt committed Jun 14, 2017
1 parent 43496cb commit 4ffec9d
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 31 deletions.
64 changes: 39 additions & 25 deletions R/json_structure.R
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ json_structure <- function(.x) {
this_level <- 0L
while(structure %>% should_json_structure_expand_more(this_level)) {

structure <- rbind_tbl_json(
structure <- bind_rows(
structure,
json_structure_level(structure %>% filter(level == this_level))
json_structure_level(structure %>% dplyr::filter(level == this_level))
)

this_level <- this_level + 1L
Expand All @@ -84,6 +84,11 @@ json_structure <- function(.x) {

json_structure_init <- function(x) {

if (!'document.id' %in% names(x)) {
x <- x %>% dplyr::mutate(
document.id=row_number()
)
}
x %>%
dplyr::mutate(
parent.id = NA_character_,
Expand Down Expand Up @@ -131,18 +136,19 @@ json_structure_empty <- function() {
json_structure_level <- function(s) {

new_s <- json_structure_empty()
new_s <- new_s %>% dplyr::select_(.dots=names(s)[names(s) %in% names(new_s)])

# Expand any objects
if (any(s$type == "object")) {
new_s <- rbind_tbl_json(
new_s <- bind_rows(
new_s,
s %>% json_structure_objects
)
}

# Expand any arrays
if (any(s$type == "array")) {
new_s <- rbind_tbl_json(
new_s <- bind_rows(
new_s,
s %>% json_structure_arrays
)
Expand All @@ -153,14 +159,14 @@ json_structure_level <- function(s) {
}

json_structure_objects <- function(s) {


v <- c('document.id',parent.id='child.id','seq',level ='level + 1L')
v <- v[v != 'document.id' | 'document.id' %in% names(s)]

expand_s <- s %>%
dplyr::filter(type == "object") %>%
dplyr::transmute(
document.id,
parent.id = child.id,
seq,
level = level + 1L
dplyr::transmute_(
.dots=v
) %>%
gather_object %>%
json_types %>%
Expand All @@ -173,10 +179,13 @@ json_structure_objects <- function(s) {
dplyr::ungroup() %>%
dplyr::mutate(
child.id = paste(parent.id, index, sep = "."),
seq = map2(seq, name, c)
) %>%
dplyr::select(
document.id, parent.id, level, index, child.id, seq, name, type, length
seq = purrr::map2(seq, name, c)
)

v <- c('document.id','parent.id','level','index','child.id','seq','name','type','length')
v <- v[v != 'document.id' | 'document.id' %in% names(df_s)]
df_s <- df_s %>% dplyr::select_(
.dots=v
)

# Reconstruct tbl_json object
Expand All @@ -185,25 +194,30 @@ json_structure_objects <- function(s) {
}

json_structure_arrays <- function(s) {

v <- c('document.id',parent.id='child.id','seq',level ='level + 1L')
v <- v[v != 'document.id' | 'document.id' %in% names(s)]

s %>%
s <- s %>%
dplyr::filter(type == "array") %>%
dplyr::transmute(
document.id,
parent.id = child.id,
seq,
level = level + 1L
dplyr::transmute_(
.dots=v
) %>%
gather_array("index") %>%
json_types %>%
json_lengths %>%
dplyr::mutate(
child.id = paste(parent.id, index, sep = "."),
seq = map2(seq, index, c)
) %>%
dplyr::transmute(
document.id, parent.id, level, index, child.id,
seq, name = NA_character_, type, length
seq = purrr::map2(seq, index, c)
)

v <- c('document.id', 'parent.id', 'level'
, 'index', 'child.id', 'seq'
, name='NA_character_', 'type', 'length')
v <- v[v != 'document.id' | 'document.id' %in% names(s)]

s %>% dplyr::transmute_(
.dots=v
)

}
38 changes: 32 additions & 6 deletions tests/testthat/test-json_structure.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ test_that("simple string works", {
expect_identical(
'"a"' %>% json_structure,
tbl_json(
data_frame(
dplyr::data_frame(
document.id = 1L,
parent.id = NA_character_,
level = 0L,
Expand All @@ -27,7 +27,7 @@ test_that("simple object works", {
expect_identical(
'{"name": "value"}' %>% json_structure,
tbl_json(
data_frame(
dplyr::data_frame(
document.id = c(1L, 1L),
parent.id = c(NA_character_, "1"),
level = c(0L, 1L),
Expand All @@ -49,7 +49,7 @@ test_that("simple array works", {
expect_identical(
'[1, 2]' %>% json_structure,
tbl_json(
data_frame(
dplyr::data_frame(
document.id = c(1L, 1L, 1L),
parent.id = c(NA_character_, "1", "1"),
level = c(0L, 1L, 1L),
Expand All @@ -71,7 +71,7 @@ test_that("nested object works", {
expect_identical(
'{"k1": {"k2": "value"}}' %>% json_structure,
tbl_json(
data_frame(
dplyr::data_frame(
document.id = c(1L, 1L, 1L),
parent.id = c(NA_character_, "1", "1.1"),
level = c(0L, 1L, 2L),
Expand All @@ -95,7 +95,7 @@ test_that("works with empty values appropriately", {
expect_identical(
'null' %>% json_structure,
tbl_json(
data_frame(
dplyr::data_frame(
document.id = 1L,
parent.id = NA_character_,
level = 0L,
Expand All @@ -117,7 +117,7 @@ test_that("works with tbl_json already", {
expect_identical(
c('"a"', '"b"') %>% as.tbl_json %>% json_structure,
tbl_json(
data_frame(
dplyr::data_frame(
document.id = c(1L, 2L),
parent.id = rep(NA_character_, 2),
level = rep(0L, 2),
Expand Down Expand Up @@ -154,3 +154,29 @@ test_that("works with empty JSON", {
expect_identical('null' %>% json_structure %>% nrow, 1L)

})


test_that("imputes document.id when not present", {
j1 <- dplyr::data_frame(id=1, json='"a"') %>%
as.tbl_json(json.column = 'json') %>% json_structure()
j2 <- dplyr::data_frame(id=1, json='["a"]') %>%
as.tbl_json(json.column = 'json') %>% json_structure()
j3 <- dplyr::data_frame(id=1, json='{"a":1}') %>%
as.tbl_json(json.column = 'json') %>% json_structure()

expect_identical(names(j1), names(j2))
expect_identical(names(j1), names(j3))
expect_identical(nrow(j2),nrow(j3))
expect_identical(as.character(j2$type), c('array','string'))
expect_identical(as.character(j3$type), c('object','number'))
})

test_that("imputed document.id works", {
j <- dplyr::data_frame(id=1, json='[{"a":1},{"a":2}]') %>%
as.tbl_json(json.column='json') %>% gather_array() %>%
json_structure()

expect_identical(j$document.id, c(1L,2L,1L,2L))
expect_identical(as.character(j$type),c('object','object','number','number'))
expect_identical(j$child.id,c('1','1','1.1','1.2'))
})

0 comments on commit 4ffec9d

Please sign in to comment.