Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Switch between R Plumber Serializers

#* @get /json
#* @serializer unboxedJSON
function() {
  return(iris)
}

#* @get /csv
#* @serializer csv list(type="text/plain; charset=UTF-8")
function() {
  return(iris)
}

#* @param type csv or json
#* @get /data
function(type = 'csv') {
  if (type == 'cvs') {
    #* @serializer csv list(type="text/plain; charset=UTF-8")
    return(iris)
  } else {
    #* @serializer unboxedJSON
    return(iris)
  }
}

The first 2 endpoints above each work fine, but the 3rd endpoint does not work as the #* @serializer unboxedJSON cannot be inside the function it seems. However, it would be great if I could somehow have a single endpoint which handles serializing before returning. plumber has plumber::serializer_csv and plumber::serializer_unboxed_json() and all of their serializers as functions, however I'm not sure how to use them inside the endpoint functions (or if this is even possible)

Thanks!

like image 570
Canovice Avatar asked Aug 29 '26 19:08

Canovice


1 Answers

You can create a custom serializer that changes the serialization format depending on the the response object. Here is an example. In this case, I attach an attribute to my response that provides the format that I want:

library(plumber)

#* @apiTitle Example Plumber API with Serializer to switch formats using object
#* attributes

serializer_switch <- function() {
  function(val, req, res, errorHandler) {
    tryCatch({
      format <- attr(val, "serialize_format")
      if (is.null(format) || format  == "json") {
        type <- "application/json"
        sfn <- jsonlite::toJSON
      } else if (format == "csv") {
        type <- "text/csv; charset=UTF-8"
        sfn <- readr::format_csv
      } else if (format == "rds") {
        type <- "application/rds"
        sfn <- function(x) base::serialize(x, NULL)
      }
      val <- sfn(val)
      res$setHeader("Content-Type", type)
      res$body <- val
      res$toResponse()
    }, error = function(err) {
      errorHandler(req, res, err)
    })
  }
}

register_serializer("switch", serializer_switch)

#* Return a data frame of random values
#* @param n size of data frame
#* @param format one of "json", "csv", or "rds"
#* @serializer switch
#* @get /random_df
function(n = 10, format = "json") {
  out <- data.frame(value = rnorm(n))
  attr(out, "serialize_format") <- format
  out
}
like image 162
Noam Ross Avatar answered Sep 01 '26 09:09

Noam Ross



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!