Skip to content

Add na="null_specials" to differentiate Inf/NaN from NA#462

Open
r2evans wants to merge 1 commit intojeroen:masterfrom
r2evans:fix/461-null-specials
Open

Add na="null_specials" to differentiate Inf/NaN from NA#462
r2evans wants to merge 1 commit intojeroen:masterfrom
r2evans:fix/461-null-specials

Conversation

@r2evans
Copy link
Copy Markdown

@r2evans r2evans commented Jan 13, 2026

I'm being optimistic that you'll be amenable to addressing #461. It's an opt-in addition to na= that defaults to unchanged legacy behavior.

Previous behavior:

toJSON(c(3.14, NA, NaN, 21, Inf, -Inf))
# [3.14,"NA","NaN",21,"Inf","-Inf"] 
toJSON(c(3.14, NA, NaN, 21, Inf, -Inf), na = "null")
# [3.14,null,null,21,null,null] 
toJSON(c(3.14, NA, NaN, 21, Inf, -Inf), na = "string")
# [3.14,"NA","NaN",21,"Inf","-Inf"] 

With this patch:

toJSON(c(3.14, NA, NaN, 21, Inf, -Inf))
# [3.14,"NA","NaN",21,"Inf","-Inf"] 
toJSON(c(3.14, NA, NaN, 21, Inf, -Inf), na = "null")
# [3.14,null,null,21,null,null] 
toJSON(c(3.14, NA, NaN, 21, Inf, -Inf), na = "string")
# [3.14,"NA","NaN",21,"Inf","-Inf"] 
toJSON(c(3.14, NA, NaN, 21, Inf, -Inf), na = "null_specials")
# [3.14,null,"NaN",21,"Inf","-Inf"] 

I added unit-tests to confirm this behavior. All other tests pass.

In full disclosure, there is a slight performance dip. In the C code I tried to be a bit more "unrolled" to mitigate this, but it's non-zero.

set.seed(42)
n <- 10000
dat <- data.frame(lgl=sample(c(F,T,NA), size=n, replace=TRUE), int=sample(100L, size=n, replace=TRUE), num=runif(n=n), dat=sample(c(Sys.Date(), NA), size=n, replace=TRUE), psx=sample(c(Sys.time(), NA), size=n, replace=TRUE))
microbenchmark::microbenchmark(toJSON(dat), times=1000) # before this PR, after, and with "null_specials"
# Unit: milliseconds
#                             expr      min       lq     mean   median       uq      max neval
#               toJSON(dat) before 10.01105 10.26181 10.80194 10.32343 10.39608 78.23144  1000
#                toJSON(dat) after 11.40054 12.04596 12.74151 12.18012 12.41033 37.34489  1000
#  toJSON(dat, na="null_specials") 11.85302 12.49873 13.24990 12.62183 12.91810 39.65528  1000

The same method using n <- 10, a more modest comparison, not demonstrating a significant change.

n <- 10
### ...
# Unit: microseconds
#                             expr     min       lq     mean   median      uq       max neval
#               toJSON(dat) before 183.762 197.8250 215.3376 206.3735 220.539  2900.955  1000
#                toJSON(dat) after 182.819 189.4815 213.9801 193.9505 215.209  9884.157  1000
#  toJSON(dat, na="null_specials") 176.710 194.6475 217.5185 198.7885 216.521 10203.055  1000

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant