Skip to content

Commit cc4e710

Browse files
authored
fix parsing for integration tests (#503)
1 parent 9bb2a88 commit cc4e710

File tree

2 files changed

+59
-25
lines changed

2 files changed

+59
-25
lines changed

R/parse.R

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -81,32 +81,27 @@ parse_connectapi_typed <- function(data, ptype, strict = FALSE) {
8181
ensure_columns(parse_connectapi(data), ptype, strict)
8282
}
8383

84+
# Build a tibble column-by-column instead of row-by-row (via list_rbind).
85+
# This avoids type conflicts when the same field is NULL in some rows and
86+
# non-NULL in others: NULL -> NA, and unlist() coerces that NA to match the
87+
# type of the non-null values in the same column. ensure_columns() handles
88+
# any further type coercion (e.g. character -> POSIXct) after this step.
8489
parse_connectapi <- function(data) {
85-
tibble::as_tibble(
86-
purrr::list_rbind(
87-
purrr::map(
88-
data,
89-
function(x) {
90-
tibble::as_tibble(purrr::map(
91-
.x = x,
92-
.f = function(y) {
93-
if (is.list(y)) {
94-
# empty list object gets null
95-
prep <- purrr::pluck(y, .default = NULL)
96-
} else {
97-
# otherwise NA
98-
prep <- purrr::pluck(y, .default = NA)
99-
}
100-
if (length(prep) > 1) {
101-
prep <- list(prep)
102-
}
103-
return(prep)
104-
}
105-
))
106-
}
107-
)
108-
)
109-
)
90+
if (length(data) == 0) return(tibble::tibble())
91+
92+
all_names <- unique(unlist(lapply(data, names)))
93+
cols <- stats::setNames(lapply(all_names, function(nm) {
94+
# NULL / missing fields become NA; unlist() will coerce to the right type
95+
values <- lapply(data, function(row) row[[nm]] %||% NA)
96+
if (any(vapply(values, function(v) is.list(v) || length(v) > 1, logical(1)))) {
97+
# List column: wrap scalars so every element is a list
98+
lapply(values, function(v) if (is.list(v)) v else list(v))
99+
} else {
100+
# Scalar column: simplify to a vector
101+
unlist(values)
102+
}
103+
}), all_names)
104+
tibble::as_tibble(cols)
110105
}
111106

112107
coerce_fsbytes <- function(x, to, ...) {

tests/testthat/test-parse.R

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,42 @@ test_that("converts length one list", {
305305
hm <- ensure_column(tibble::tibble(one = "hi"), NA_list_, "one")
306306
expect_type(hm$one, "list")
307307
})
308+
309+
test_that("parse_connectapi handles mixed null/non-null character values", {
310+
data <- list(
311+
list(guid = "aaa", bundle_id = NULL, name = "first"),
312+
list(guid = "bbb", bundle_id = "123", name = "second")
313+
)
314+
315+
result <- parse_connectapi(data)
316+
expect_s3_class(result, "tbl_df")
317+
expect_equal(nrow(result), 2)
318+
expect_type(result$bundle_id, "character")
319+
expect_identical(result$bundle_id, c(NA_character_, "123"))
320+
})
321+
322+
test_that("parse_connectapi handles mixed null/non-null datetime strings", {
323+
data <- list(
324+
list(guid = "aaa", active_time = NULL),
325+
list(guid = "bbb", active_time = "2023-08-22T14:13:14Z")
326+
)
327+
328+
result <- parse_connectapi(data)
329+
expect_s3_class(result, "tbl_df")
330+
expect_equal(nrow(result), 2)
331+
expect_type(result$active_time, "character")
332+
expect_identical(result$active_time, c(NA_character_, "2023-08-22T14:13:14Z"))
333+
})
334+
335+
test_that("parse_connectapi handles mixed null/non-null integer timestamps", {
336+
data <- list(
337+
list(key = "abc", start_time = 1732573574, end_time = NULL),
338+
list(key = "def", start_time = 1732553145, end_time = 1732556770)
339+
)
340+
341+
result <- parse_connectapi(data)
342+
expect_s3_class(result, "tbl_df")
343+
expect_equal(nrow(result), 2)
344+
expect_type(result$end_time, "double")
345+
expect_identical(result$end_time, c(NA_real_, 1732556770))
346+
})

0 commit comments

Comments
 (0)