I faced some issues regarding difftime in R plumber API. Tried with R, it works normally. However, when turned to API, its returned "
#' @param lease_start date
#' @param lease_end date
#' @post /difference
function(lease_start, lease_end){
lease_start <- as.Date("01/01/2018", format = "%d/%m/%Y")
lease_end <- as.Date("01/01/2019", format = "%d/%m/%Y")
lease_end <- as.Date(lease_end, ", "%d/%m/%Y")
difference <- lease_end - lease_start
difference
}
simpleError: No method asJSON S3 class: difftime
Anyone knows what is the issue and how to fix it? Thank you a lot!
To return an R object to an API client, {plumber} translates the object into a format that can be understood by the API client. This process is called “serialization” Rendering output with Plumber. By default, {plumber} uses JSON serialization and {jsonlite} R package to turn R objects into JSON.
As explained by @Steve, in R, difference of two dates returns a difftime object that cannot be processed into JSON. {jsonlite} raises, then, the error mentioned in the question as shown with the following code
library(plumber)
library(jsonlite)
lease_start <- as.Date("01/01/2018", format = "%d/%m/%Y")
lease_end <- as.Date("01/01/2019", format = "%d/%m/%Y")
difference <- lease_end - lease_start
class(difference)
#> [1] "difftime"
jsonlite::toJSON(difference)
#> Error: No method asJSON S3 class: difftime
One solution is to convert difftime object into a number or character. In this way, the object can be converted to JSON:
jsonlite::toJSON(as.numeric(difference))
#> [365]
jsonlite::toJSON(as.character(difference))
#> ["365"]
An alternative solution consists in controlling the serialization to return
a text object via print(), format() or cat(). This can be done adding
alternative serializers provided by {plumber}
#* @param lease_start date
#* @param lease_end date
#* @serializer format
#* @post /difference_format
function(lease_start = "01/01/2018", lease_end="01/01/2019"){
lease_start <- as.Date(lease_start, format = "%d/%m/%Y")
lease_end <- as.Date(lease_end, format = "%d/%m/%Y")
difference <- lease_end - lease_start
difference
}
In a similar way, you can use @serializer cat or @serializer print
Nevertheless, the solution I prefer is to return difftime object two parts (units and actual difference value) in a list.
list(units = units(difference), value = as.numeric(difference))
#> $units
#> [1] "days"
#>
#> $value
#> [1] 365
The advantage is that lists can be processed by {plumber} default serializer and no error will be raised
jsonlite::toJSON(list(units = units(difference), value = as.numeric(difference)))
#> {"units":["days"],"value":[365]}
#* @param lease_start date
#* @param lease_end date
#* @post /difference
function(lease_start = "01/01/2018", lease_end="01/01/2019"){
lease_start <- as.Date(lease_start, format = "%d/%m/%Y")
lease_end <- as.Date(lease_end, format = "%d/%m/%Y")
difference <- lease_end - lease_start
list(units = units(difference), value = as.numeric(difference))
}
Created on 2022-02-26 by the reprex package (v2.0.1)
this line -- difference <- lease_end - lease_start will create a R specific object called difftime which cannot be properly parsed by Plumber.
you can try at the end convert difference to character or integer by as.character(difference) or as.integer(difference) and it will work
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With