--- title: "Converting between GeoJSON and sf" author: "D Cooley" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: fig_caption: yes toc: true vignette: > %\VignetteIndexEntry{Converting between GeoJSON and sf} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ## What it does Quickly converts between GeoJSON and `sf` objects ## What it doesn't do As per GeoJSON ([RFC 7946 specification)](https://tools.ietf.org/html/rfc7946#page-11), foreign members are ignored, and nested objects and arrays inside the `properties` object are converted to string/characters. ```{r} library(geojsonsf) # library(sf) ``` You would also typically load `library(sf)` to take advantange of its `plot` methods. ## GeoJSON ### Geometry ```{r} p <- '{"type":"Point","coordinates":[0,0]}' sf <- geojson_sf(p) head(sf) ``` ### Geometry Collection ```{r} gc <- '{ "type": "GeometryCollection", "geometries": [ {"type": "Point", "coordinates": [100.0, 0.0]}, {"type": "LineString", "coordinates": [[101.0, 0.0], [102.0, 1.0]]}, {"type" : "MultiPoint", "coordinates" : [[0,0], [1,1], [2,2]]} ] }' sf <- geojson_sf(gc) head(sf) ``` Some web-plotting libraries (such as `googleway`) can't plot GeometryCollections directly. Therefore, you can set `expand_geometries` to `TRUE` and it will extract each geometry from a GeometryCollection and create a row for each one ```{r} gc <- '{ "type": "GeometryCollection", "geometries": [ {"type": "Point", "coordinates": [100.0, 0.0]}, {"type": "LineString", "coordinates": [[101.0, 0.0], [102.0, 1.0]]}, {"type" : "MultiPoint", "coordinates" : [[0,0], [1,1], [2,2]]} ] }' sf <- geojson_sf(gc, expand_geometries = T) head(sf) ``` ### Feature ```{r} f <- '{ "type": "Feature", "properties": {"id":1,"value":100,"text":"the quick brown fox"}, "geometry": { "type": "LineString", "coordinates": [[101.0, 0.0], [102.0, 1.0]] } }' sf <- geojson_sf(f) head(sf) ``` ### Feature Collection ```{r} fc <- '{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": {"foo" : "feature 1.1", "bar" : "feature 1.2"}, "geometry": {"type": "Point", "coordinates": [100.0, 0.0]} }, { "type": "Feature", "properties": null, "geometry": {"type": "LineString", "coordinates": [[101.0, 0.0], [102.0, 1.0]]} }, { "type": "Feature", "properties": {"foo" : "feature 3.1", "bar" : "feature 3.2"}, "geometry": {"type": "LineString", "coordinates": [[101.0, 0.0], [102.0, 1.0]]} } ] }' sf <- geojson_sf(fc) head(sf) ``` ## Vectors of GeoJSON ```{r} geo <- c(p, gc, f, fc) sf <- geojson_sf(geo) head(sf) ``` ## JSON Arrays of GeoJSON ```{r} js <- '[ { "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": null, "geometry": {"type": "Point", "coordinates": [100.0, 0.0]} }, { "type": "Feature", "properties": null, "geometry": {"type": "LineString", "coordinates": [[201.0, 0.0], [102.0, 1.0]]} }, { "type": "Feature", "properties": null, "geometry": {"type": "LineString", "coordinates": [[301.0, 0.0], [102.0, 1.0]]} } ] }, { "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": null, "geometry": {"type": "Point", "coordinates": [100.0, 0.0]} }, { "type": "Feature", "properties": null, "geometry": {"type": "LineString", "coordinates": [[501.0, 0.0], [102.0, 1.0]]} }, { "type": "Feature", "properties": null, "geometry": {"type": "LineString", "coordinates": [[601.0, 0.0], [102.0, 1.0]]} } ] } ]' sf <- geojson_sf(js) head(sf) ``` ## Reading from URL ```r url <- "http://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_050_00_500k.json" sf <- geojson_sf(url) #head(sf) ``` ## Reading from file ```{r} sf <- geojson_sf(system.file("examples", "geo_melbourne.geojson", package = "geojsonsf")) head(sf) ``` ## sf to GeoJSON ```{r} geo <- sf_geojson(sf) substr(geo, 1, 80) ``` ### Atomising Sometimes it's useful to convert each row of an `sf` object into it's own GeoJSON object, for example when you want to keep each geometry separate in a database. Set `atomise = TRUE` to return a vector of GeoJSON ```{r} geo <- sf_geojson(sf, atomise = T) ``` now `geo` is a vector of GeoJSON ```{r} substr(geo[1], 1, 80) substr(geo[2], 1, 80) ``` ## Well-known Text It also converts GeoJSON to Well-Known Text and returns a `data.frame` ```{r} fc <- '{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": {"foo" : "feature 1.1", "bar" : "feature 1.2"}, "geometry": {"type": "Point", "coordinates": [100.0, 0.0]} }, { "type": "Feature", "properties": null, "geometry": {"type": "LineString", "coordinates": [[101.0, 0.0], [102.0, 1.0]]} }, { "type": "Feature", "properties": {"foo" : "feature 3.1", "bar" : "feature 3.2"}, "geometry": {"type": "LineString", "coordinates": [[101.0, 0.0], [102.0, 1.0]]} } ] }' df <- geojson_wkt(fc) head(df) ```