REST API 以 R Plumber - GeoJSON 作为输入
REST API with R Plumber - GeoJSON as Input
我正在尝试使用管道工 R 包将函数包装到 REST API 中。作为输入,函数采用形状文件和 returns 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
使用 plumber 1.0
只需要加载一次库。将它们从您的端点中取出。
首先创建一个解析器和一个序列化器来解析 geojson 内容和 return 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, file.path(tmpdir, 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, design = c("one", "two")) {
# Import Shapefile
a_shape <- raster::shapefile(dsn)
as_attachment(dothething(a_shape, design), "response.zip")
}
我正在尝试使用管道工 R 包将函数包装到 REST API 中。作为输入,函数采用形状文件和 returns 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
使用 plumber 1.0
只需要加载一次库。将它们从您的端点中取出。
首先创建一个解析器和一个序列化器来解析 geojson 内容和 return 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, file.path(tmpdir, 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, design = c("one", "two")) {
# Import Shapefile
a_shape <- raster::shapefile(dsn)
as_attachment(dothething(a_shape, design), "response.zip")
}