带有R Plumber的REST API-GeoJSON作为输入

问题描述

我正在尝试使用plumber R Package将函数包装到REST API中。作为Input,函数获取一个形状文件,并在转换后返回 GeoJSON作为输出

#* Return Spatial polygon Object in form of GeoJSON
#* @param dsn:character Path to Shapefile with Name
#* @param design:character one or two
#* @post /sprayermap

sprayer_map <-
  function(dsn,design = c("one","two")) {
# library
require(rgeos)
require(rgdal)
require(sp)
require(raster)
require(cleangeo)

#Import Shapefile
a_shape <- raster::shapefile(dsn)

result <-
  list("success" = F,additional_info = NULL,GeoJSON = NULL)

if (class(a_shape) == "SpatialpolygonsDataFrame") {
  a_shape <- tryCatch (
    rgeos::gBuffer(a_shape,byid = TRUE,width = 0),error = function(err) {
      return(paste("sprayer map : ",err))

    }
  )

  if (design == "one") {
    sprayer_map <- tryCatch (
      aggregate(a_shape,"Rx"),error = function(err) {
        return(paste("sprayer map : ",err))

      }
    )

    sprayer_map@data$Rx <- as.integer(sprayer_map@data$Rx)

  } else if (design == "two") {
    return(paste0("Design Two !"))

  }

  temppath <- file.path(tempdir(),"sprayermap.GeoJSON")
  rgdal::writeOGR(
    sprayer_map,dsn = temppath,layer = "geojson",driver = "GeoJSON",overwrite_layer = TRUE
  )

  if (file.exists(temppath)) {
    GeoJSON <- readLines(temppath)
    result$success <- T
    result$GeoJSON = GeoJSON
    return(result)
  } else {
    return(paste0("GeoJSON Creation Failed!"))
  }

} else {
  return(paste0("Please provide spatial polygon object !"))

}
  }

现在要使REST API在实现和使用方面更加通用,REST API的 Input 需要更改为 GeoJSON 作为请求正文(req $ postBody)代替形状文件路径导入方法。 寻找指导在这种情况下如何实现相同的目标。 Test Input Shape file as well as GeoJSON

解决方法

使用水管工1.0

只需加载一次库。将它们带出端点。

首先创建一个解析器和一个序列化器来解析geojson内容并返回geojson响应。这也可以在端点内部完成。它只是使其更具可重用性。

解析器负责处理请求正文内容。 序列化器对API响应进行编码。

我重新分配了parser_rds和serializer_rds的用途,只是替换为GeoJSON函数。

然后,您使用刚刚创建的解析器和序列化器完成端点。

如有任何疑问,请不要犹豫。

编辑:添加了一个压缩文件夹序列化器。

library(rgeos)
library(rgdal)
library(sp)
library(raster)
library(cleangeo)
library(plumber)

parser_geojson <- function(...) {
  parser_read_file(function(tmpfile) {
    rgdal::readOGR(tmpfile,...)
  })
}
register_parser("geojson",parser_geojson,fixed = c("application/geo+json","application/vnd.geo+json","application/octet-stream"))

serializer_geojson <- function(type = "application/geo+json") {
  serializer_write_file(
    fileext = ".GeoJSON",type = type,write_fn = function(val,tmpfile) {
      rgdal::writeOGR(val,dsn = tmpfile,layer = "geojson",driver = "GeoJSON",overwrite_layer = TRUE)
    }
  )
}
register_serializer("geojson",serializer_geojson)

serializer_shapezip <- function(type = "application/zip") {
  serializer_content_type(type,function(val) {
    tmpdir <- file.path(tempdir(),"output")
    dir.create(tmpdir)
    on.exit({
      if (dir.exists(tmpdir)) {
        unlink(tmpdir,recursive = TRUE)
      }
    },add = TRUE)
    raster::shapefile(val,file.path(tmpdir,"shapefile"))
    tmpfile <- file.path(tmpdir,"shapefile.zip")
    zip(tmpfile,dir(tmpdir)),extras = "-j")
    readBin(tmpfile,what = "raw",n = file.info(tmpfile)$size)
  })
}
register_serializer("shapezip",serializer_shapezip)

dothething <- function(a_shape,design) {
  if (!class(a_shape) == "SpatialPolygonsDataFrame") stop("Please provide spatial polygon object !")
  a_shape <- rgeos::gBuffer(a_shape,byid = TRUE,width = 0)

  if (design == "one") {
    sprayer_map <- aggregate(a_shape,"Rx")
    sprayer_map@data$Rx <- as.integer(sprayer_map@data$Rx)
  } else if (design == "two") {
    # This should return a geojson too since endpoint should have predictable outputs
    stop(paste0("Design Two !"))
  }

  sprayer_map
}

#* Return Spatial Polygon Object in form of GeoJSON
#* @param dsn:file A GeoJSON file
#* @param design:character one or two
#* @parser multi
#* @parser geojson
#* @serializer geojson
#* @post /sprayermap_geojson
function(dsn,design = c("one","two")) {
  a_shape <- dsn[[1]]
  as_attachment(dothething(a_shape,design),"response.GeoJSON")
}

#* Return Spatial Polygon Object in form of GeoJSON
#* @param dsn:character Path to Shapefile with Name
#* @param design:character one or two
#* @serializer shapezip
#* @post /sprayermap_shapefile
function(dsn,"two")) {
  # Import Shapefile
  a_shape <- raster::shapefile(dsn)
  as_attachment(dothething(a_shape,"response.zip")
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...