From 6945f68ec5a6c12b1d7d4ad79e283626767def37 Mon Sep 17 00:00:00 2001 From: Jeremy Stanley Date: Fri, 3 Apr 2015 06:59:19 -0400 Subject: [PATCH 1/2] #27 first draft tests for as.tbl_json.data.frame --- tests/testthat/test-tbl_json.r | 55 ++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/tests/testthat/test-tbl_json.r b/tests/testthat/test-tbl_json.r index 67911e0..5d2bb6e 100644 --- a/tests/testthat/test-tbl_json.r +++ b/tests/testthat/test-tbl_json.r @@ -68,6 +68,59 @@ test_that("throws error on invalid json", { } ) +context("tbl_json: as.tbl_json.data.frame") + +test_that("works for a data.frame and data_frame created objects", { + + df <- data.frame( + document.id = 1:2, + json = c('{"name": "bob"}', '{"name": "susan"}'), + stringsAsFactors = FALSE) + # data.frame + expect_identical( + as.tbl_json(df, json.column = "json"), + as.tbl_json(df$json) + ) + # data_frame + df <- data_frame( + document.id = 1:2, + json = c('{"name": "bob"}', '{"name": "susan"}')) + expect_identical( + as.tbl_json(df, json.column = "json"), + as.tbl_json(df$json) + ) + + } +) + +test_that("works in a pipeline", { + + df <- data_frame( + age = c(32, 45), + json = c('{"name": "bob"}', '{"name": "susan"}') + ) + + expect_identical( + df %>% as.tbl_json(json.column = "json") %>% + spread_values(name = jstring("name")) %>% + filter(age == 32) %>% + extract2("name"), + "bob" + ) + + } +) + +test_that("throws an error without json.column specified", { + expect_error(as.tbl_json(iris)) + } +) + +test_that("throws an error if json column doesn't exist", { + expect_error(as.tbl_json(iris, json.column = "json")) + } +) + context("tbl_json") test_that("tbl_json constructor works with no data", { @@ -164,7 +217,6 @@ test_that("dplyr::arrange works with a simple example", { } ) - test_that("dplyr::mutate works with a simple example", { x <- as.tbl_json(c('{"name": "bob"}', '{"name": "susan"}')) @@ -185,7 +237,6 @@ test_that("dplyr::mutate works with a simple example", { } ) - test_that("dplyr::mutate works in a more complex pipeline", { json <- c( From fd10eb640a21bf8606422dbc851f3a75aafc2c0a Mon Sep 17 00:00:00 2001 From: Jeremy Stanley Date: Fri, 3 Apr 2015 07:19:10 -0400 Subject: [PATCH 2/2] #27 implement as.tbl_json.data.frame, all tests passing --- NAMESPACE | 1 + R/tbl_json.r | 21 +++++++++++++++++++++ man/allowed_json_types.Rd | 1 - man/append_values.Rd | 1 - man/append_values_factory.Rd | 1 - man/append_values_type.Rd | 1 - man/commits.Rd | 1 - man/companies.Rd | 1 - man/determine_types.Rd | 1 - man/enter_object.Rd | 1 - man/gather_array.Rd | 1 - man/gather_keys.Rd | 1 - man/issues.Rd | 1 - man/jfactory.Rd | 1 - man/jfunctions.Rd | 1 - man/json_lengths.Rd | 1 - man/json_types.Rd | 1 - man/list_path.Rd | 1 - man/my_unlist.Rd | 1 - man/prep_path.Rd | 1 - man/replace_nulls.Rd | 1 - man/spread_values.Rd | 1 - man/sub-.tbl_json.Rd | 1 - man/tbl_json.Rd | 12 ++++++++++-- man/tidyjson.Rd | 1 - man/worldbank.Rd | 1 - man/wrap_dplyr_verb.Rd | 1 - tests/testthat/test-tbl_json.r | 2 +- 28 files changed, 33 insertions(+), 27 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index c6bcdd4..daaa9b1 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,6 +3,7 @@ S3method("[",tbl_json) S3method(arrange_,tbl_json) S3method(as.tbl_json,character) +S3method(as.tbl_json,data.frame) S3method(as.tbl_json,tbl_json) S3method(filter_,tbl_json) S3method(mutate_,tbl_json) diff --git a/R/tbl_json.r b/R/tbl_json.r index 2b83021..571eb10 100644 --- a/R/tbl_json.r +++ b/R/tbl_json.r @@ -60,6 +60,27 @@ as.tbl_json.character <- function(x, ...) { tbl_json(ids, json) } +#' Turns a data.frame into a tbl_json object +#' @param x data.frame that has a column of JSON data +#' @param json.column the name of the JSON column of data in x, if x is a data.frame +#' @rdname tbl_json +#' @export +as.tbl_json.data.frame <- function(x, json.column, ...) { + + assert_that(is.character(json.column)) + assert_that(json.column %in% names(x)) + + # Parse the json + json <- lapply(x[[json.column]], fromJSON, simplifyVector = FALSE) + + # Remove json column + x <- x[, setdiff(names(x), json.column), drop = FALSE] + + # Construct tbl_json + tbl_json(x, json) + +} + #' @rdname tbl_json #' @export is.tbl_json <- function(x) inherits(x, "tbl_json") diff --git a/man/allowed_json_types.Rd b/man/allowed_json_types.Rd index 6c07388..bc0c582 100644 --- a/man/allowed_json_types.Rd +++ b/man/allowed_json_types.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/json_types.r \docType{data} \name{allowed_json_types} \alias{allowed_json_types} diff --git a/man/append_values.Rd b/man/append_values.Rd index 28230e5..f2d686b 100644 --- a/man/append_values.Rd +++ b/man/append_values.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/append_values.r \name{append_values} \alias{append_values} \alias{append_values_logical} diff --git a/man/append_values_factory.Rd b/man/append_values_factory.Rd index 9eeb9f9..0601303 100644 --- a/man/append_values_factory.Rd +++ b/man/append_values_factory.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/append_values.r \name{append_values_factory} \alias{append_values_factory} \title{Creates the append_values_* functions} diff --git a/man/append_values_type.Rd b/man/append_values_type.Rd index ee488a4..b9594ca 100644 --- a/man/append_values_type.Rd +++ b/man/append_values_type.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/append_values.r \name{append_values_type} \alias{append_values_type} \title{get list of values from json} diff --git a/man/commits.Rd b/man/commits.Rd index 35bd6c7..e88fbc7 100644 --- a/man/commits.Rd +++ b/man/commits.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/data-commits.r \docType{data} \name{commits} \alias{commits} diff --git a/man/companies.Rd b/man/companies.Rd index 93f5354..849048b 100644 --- a/man/companies.Rd +++ b/man/companies.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/data-companies.r \docType{data} \name{companies} \alias{companies} diff --git a/man/determine_types.Rd b/man/determine_types.Rd index b154332..aeebd4a 100644 --- a/man/determine_types.Rd +++ b/man/determine_types.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/json_types.r \name{determine_types} \alias{determine_types} \title{Determines the types of a list of parsed JSON} diff --git a/man/enter_object.Rd b/man/enter_object.Rd index 42c44ae..48525d9 100644 --- a/man/enter_object.Rd +++ b/man/enter_object.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/enter_object.r \name{enter_object} \alias{enter_object} \title{Selects an object by key and filters rows to just those with matching keys} diff --git a/man/gather_array.Rd b/man/gather_array.Rd index 0f0cb3c..1112791 100644 --- a/man/gather_array.Rd +++ b/man/gather_array.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/gather_array.r \name{gather_array} \alias{gather_array} \title{Expands a tbl_json to span the indices of a JSON array} diff --git a/man/gather_keys.Rd b/man/gather_keys.Rd index a66fcf1..87cd158 100644 --- a/man/gather_keys.Rd +++ b/man/gather_keys.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/gather_keys.r \name{gather_keys} \alias{gather_keys} \title{Gathers every key from the top level of the json and stacks them} diff --git a/man/issues.Rd b/man/issues.Rd index 9cb9c00..9ba6cd5 100644 --- a/man/issues.Rd +++ b/man/issues.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/data-issues.r \docType{data} \name{issues} \alias{issues} diff --git a/man/jfactory.Rd b/man/jfactory.Rd index a5fac83..b44adb6 100644 --- a/man/jfactory.Rd +++ b/man/jfactory.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/spread_values.r \name{jfactory} \alias{jfactory} \title{Factory that creates the j* functions below} diff --git a/man/jfunctions.Rd b/man/jfunctions.Rd index e4adbe3..ecf5193 100644 --- a/man/jfunctions.Rd +++ b/man/jfunctions.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/spread_values.r \name{jfunctions} \alias{jfunctions} \alias{jlogical} diff --git a/man/json_lengths.Rd b/man/json_lengths.Rd index 31c53bc..af5ceb8 100644 --- a/man/json_lengths.Rd +++ b/man/json_lengths.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/json_lengths.r \name{json_lengths} \alias{json_lengths} \title{Add a column that tells the 'length' of the data in the root of the JSON} diff --git a/man/json_types.Rd b/man/json_types.Rd index 85d93be..972ffcb 100644 --- a/man/json_types.Rd +++ b/man/json_types.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/json_types.r \name{json_types} \alias{json_types} \title{Add a column that tells the 'type' of the data in the root of the JSON} diff --git a/man/list_path.Rd b/man/list_path.Rd index 7cc299c..2a0d184 100644 --- a/man/list_path.Rd +++ b/man/list_path.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/path.r \name{list_path} \alias{list_path} \title{Recursively access a path} diff --git a/man/my_unlist.Rd b/man/my_unlist.Rd index 29f1cc3..a58f255 100644 --- a/man/my_unlist.Rd +++ b/man/my_unlist.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/append_values.r \name{my_unlist} \alias{my_unlist} \title{Unlists while preserving NULLs and only unlisting lists with one value} diff --git a/man/prep_path.Rd b/man/prep_path.Rd index 0e6d703..0a53388 100644 --- a/man/prep_path.Rd +++ b/man/prep_path.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/path.r \name{prep_path} \alias{prep_path} \title{Prepare a path from ...} diff --git a/man/replace_nulls.Rd b/man/replace_nulls.Rd index f7a9448..664bf89 100644 --- a/man/replace_nulls.Rd +++ b/man/replace_nulls.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/path.r \name{replace_nulls} \alias{replace_nulls} \title{Replace nulls with something else} diff --git a/man/spread_values.Rd b/man/spread_values.Rd index 97f0d87..0951181 100644 --- a/man/spread_values.Rd +++ b/man/spread_values.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/spread_values.r \name{spread_values} \alias{spread_values} \title{Extracts values from JSON refereced by a sequence of keys} diff --git a/man/sub-.tbl_json.Rd b/man/sub-.tbl_json.Rd index 22c5bca..5383580 100644 --- a/man/sub-.tbl_json.Rd +++ b/man/sub-.tbl_json.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/tbl_json.r \name{[.tbl_json} \alias{[.tbl_json} \title{Extract subsets of a tbl_json object (not replace)} diff --git a/man/tbl_json.Rd b/man/tbl_json.Rd index bc65f00..62b9f03 100644 --- a/man/tbl_json.Rd +++ b/man/tbl_json.Rd @@ -1,8 +1,8 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/tbl_json.r \name{tbl_json} \alias{as.tbl_json} \alias{as.tbl_json.character} +\alias{as.tbl_json.data.frame} \alias{as.tbl_json.tbl_json} \alias{is.tbl_json} \alias{tbl_json} @@ -16,6 +16,8 @@ as.tbl_json(x, ...) \method{as.tbl_json}{character}(x, ...) +\method{as.tbl_json}{data.frame}(x, json.column, ...) + is.tbl_json(x) } \arguments{ @@ -25,9 +27,13 @@ is.tbl_json(x) \item{drop.null.json}{drop NULL json entries from data.frame and json} +\item{...}{other arguments} + \item{x}{character vector of json} -\item{...}{other arguments} +\item{x}{data.frame that has a column of JSON data} + +\item{json.column}{the name of the JSON column of data in x, if x is a data.frame} } \description{ Combines structured JSON (as a data.frame) with remaining JSON @@ -38,5 +44,7 @@ note that "..JSON" is a reserved column name used internally for filtering tbl_json objects, and so is not allowed in the data.frame names. Turns a character vector into a tbl_json object + +Turns a data.frame into a tbl_json object } diff --git a/man/tidyjson.Rd b/man/tidyjson.Rd index 70048cd..be5655d 100644 --- a/man/tidyjson.Rd +++ b/man/tidyjson.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/tidyjson-package.r \docType{package} \name{tidyjson} \alias{tidyjson} diff --git a/man/worldbank.Rd b/man/worldbank.Rd index e150969..8b2d21d 100644 --- a/man/worldbank.Rd +++ b/man/worldbank.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/data-worldbank.r \docType{data} \name{worldbank} \alias{worldbank} diff --git a/man/wrap_dplyr_verb.Rd b/man/wrap_dplyr_verb.Rd index da8aa70..64ff32f 100644 --- a/man/wrap_dplyr_verb.Rd +++ b/man/wrap_dplyr_verb.Rd @@ -1,5 +1,4 @@ % Generated by roxygen2 (4.1.0): do not edit by hand -% Please edit documentation in R/tbl_json.r \name{wrap_dplyr_verb} \alias{wrap_dplyr_verb} \title{Wrapper for extending dplyr verbs to tbl_json objects} diff --git a/tests/testthat/test-tbl_json.r b/tests/testthat/test-tbl_json.r index 5d2bb6e..3507bac 100644 --- a/tests/testthat/test-tbl_json.r +++ b/tests/testthat/test-tbl_json.r @@ -104,7 +104,7 @@ test_that("works in a pipeline", { df %>% as.tbl_json(json.column = "json") %>% spread_values(name = jstring("name")) %>% filter(age == 32) %>% - extract2("name"), + `[[`("name"), "bob" )