Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error <No method asJSON S3 class: difftime> in R plumber

Tags:

r

I faced some issues regarding difftime in R plumber API. Tried with R, it works normally. However, when turned to API, its returned "

with R plumber

#' @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
}

Result:

simpleError: No method asJSON S3 class: difftime

Anyone knows what is the issue and how to fix it? Thank you a lot!

like image 649
Katty Nguyen Avatar asked Oct 21 '25 20:10

Katty Nguyen


2 Answers

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)

like image 164
josep maria porrà Avatar answered Oct 24 '25 10:10

josep maria porrà


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

like image 45
Steve Avatar answered Oct 24 '25 10:10

Steve



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!