Skip to content

Commit

Permalink
Re-introduce NDJSON support
Browse files Browse the repository at this point in the history
  • Loading branch information
coolbutuseless committed Mar 15, 2024
1 parent 298d9f1 commit a23d34b
Show file tree
Hide file tree
Showing 29 changed files with 3,260 additions and 22 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: yyjsonr
Type: Package
Title: Fast JSON Parser and Generator
Version: 0.1.18.9002
Version: 0.1.18.9004
Authors@R: c(
person("Mike", "Cheng", role = c("aut", "cre", 'cph'),
email = "[email protected]"),
Expand Down
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ export(read_json_conn)
export(read_json_file)
export(read_json_raw)
export(read_json_str)
export(read_ndjson_file)
export(validate_json_file)
export(validate_json_str)
export(write_json_file)
export(write_json_str)
export(write_ndjson_file)
export(write_ndjson_str)
export(yyjson_read_flag)
export(yyjson_version)
export(yyjson_write_flag)
useDynLib(yyjsonr, .registration=TRUE)
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@


# yyjsonr 0.1.18.9004 2024-03-15

* Re-introduce NDJSON support

# yyjsonr 0.1.18.9003 2024-03-13

* call `normalizePath()` on all file paths
Expand Down
143 changes: 143 additions & 0 deletions R/ndjson.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#' Parse an NDJSON file to a data.frame or list
#'
#' If reading as data.frame, each row of NDJSON becomes a row in the data.frame.
#' If reading as a list, then each row becomes an element in the list.
#'
#' If parsing NDJSON to a data.frame it is usually better if the json objects
#' are consistent from line-to-line. Type inference for the data.frame is done
#' during initialisation by reading through \code{nprobe} lines. Warning: if
#' there is a type-mismatch further into the file than it is probed, then you
#' will get missing values in the data.frame, or JSON values not captured in
#' the R data.
#'
#' No flattening of the namespace is done i.e. nested object remain nested.
#'
#' @inheritParams read_json_str
#' @param filename Path to file containing NDJSON data. May e a vanilla text
#' file or a gzipped file
#' @param type The type of R object the JSON should be parsed into. Valid
#' values are 'df' or 'list'. Default: 'df' (data.frame)
#' @param nread Number of records to read. Default: -1 (reads all JSON strings)
#' @param nskip Number of records to skip before starting to read. Default: 0
#' (skip no data)
#' @param nprobe Number of lines to read to determine types for data.frame
#' columns. Default: 100. Use \code{-1} to probe entire file.
#'
#'
#' @examples
#' tmp <- tempfile()
#' write_ndjson_file(head(mtcars), tmp)
#' read_ndjson_file(tmp)
#'
#' @family JSON Parsers
#' @return NDJSON data read into R as list or data.frame depending
#' on \code{'type'} argument
#' @export
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
read_ndjson_file <- function(filename, type = c('df', 'list'), nread = -1, nskip = 0, nprobe = 100, opts = list(), ...) {

type <- match.arg(type)
filename <- normalizePath(filename, mustWork = TRUE)

if (type == 'list') {
.Call(
parse_ndjson_file_as_list_,
filename,
nread,
nskip,
modify_list(opts, list(...))
)
} else {
.Call(
parse_ndjson_file_as_df_,
filename,
nread,
nskip,
nprobe,
modify_list(opts, list(...))
)
}
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#' Write list or data.frame object to NDJSON in a file
#'
#' For \code{list} input, each element of the list is written as a single JSON string.
#' For \code{data.frame} input, each row of the \code{data.frame} is written
#' as aJSON string.
#'
#' @inherit write_json_file
#' @param x \code{data.frame} or \code{list} to be written as multiple JSON strings
#' @param filename JSON strings will be written to this file one-line-per-JSON string.
#'
#' @return None
#' @family JSON Serializer
#' @export
#'
#' @examples
#' tmp <- tempfile()
#' write_ndjson_file(head(mtcars), tmp)
#' read_ndjson_file(tmp)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
write_ndjson_file <- function(x, filename, opts = list(), ...) {
opts <- modify_list(opts, list(...))
filename <- normalizePath(filename, mustWork = FALSE)

if (is.data.frame(x)) {
.Call(
serialize_df_to_ndjson_file_,
x,
filename,
opts
)
} else {
.Call(
serialize_list_to_ndjson_file_,
x,
filename,
opts
)
}
invisible()
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#' Write list or data.frame object to NDJSON in a string
#'
#' For \code{list} input, each element of the list is written as a single JSON string.
#' For \code{data.frame} input, each row of the \code{data.frame} is written
#' as aJSON string.
#'
#' @inherit write_ndjson_file
#'
#' @return String containing multiple JSON strings separated by newlines.
#' @family JSON Serializer
#' @export
#'
#' @examples
#' write_ndjson_str(head(mtcars))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
write_ndjson_str <- function(x, opts = list(), ...) {
opts <- modify_list(opts, list(...))

if (is.data.frame(x)) {
.Call(
serialize_df_to_ndjson_str_,
x,
opts
)
} else {
.Call(
serialize_list_to_ndjson_str_,
x,
opts
)
}
}


14 changes: 13 additions & 1 deletion R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,16 @@
modify_list <- function(old, new) {
for (nm in names(new)) old[[nm]] <- new[[nm]]
old
}
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#' Version number of 'yyjson' C library
#'
#' @export
#' @examples
#' yyjson_version()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
yyjson_version <- function() {
.Call(yyjson_version_)
}
3 changes: 2 additions & 1 deletion man/read_json_conn.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/read_json_file.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/read_json_raw.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/read_json_str.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 68 additions & 0 deletions man/read_ndjson_file.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion man/write_json_file.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion man/write_json_str.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions man/write_ndjson_file.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions man/write_ndjson_str.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a23d34b

Please sign in to comment.