Skip to content

For working with GeoJSON/TopoJSON data you have two options: either read it into sp objects; or use the addGeoJSON() and addTopoJSON() functions.

Reading as sp

The first approach is to use either sf or geojsonio (packages) to read GeoJSON/TopoJSON as sp objects. Then, you can use the full functionality of polygons, markers, colors, legends, etc.

# From and
nycounties <- sf::read_sf("") 
# Or use the geojsonio equivalent:
# nycounties <- geojsonio::geojson_read("", what = "sp") 

pal <- colorNumeric("viridis", NULL)

leaflet(nycounties) %>%
  addTiles() %>%
  addPolygons(stroke = FALSE, smoothFactor = 0.3, fillOpacity = 1,
    fillColor = ~pal(log10(pop)),
    label = ~paste0(county, ": ", formatC(pop, big.mark = ","))) %>%
  addLegend(pal = pal, values = ~log10(pop), opacity = 1.0,
    labFormat = labelFormat(transform = function(x) round(10^x)))

This approach is preferred over using addGeoJSON()/addTopoJSON(), as it makes it easy to use feature properties in determining map colors, labels, etc., or to modify or add new properties.

The main downside to this approach is that it only supports feature collections where all features are of the same type, whereas in GeoJSON/TopoJSON it’s possible—though uncommon—to have a single feature collection that contains, say, both markers and polygons.

Working with raw GeoJSON/TopoJSON

addGeoJSON() and addTopoJSON() accept GeoJSON data in either parsed (nested lists) or stringified (single-element character vector) format.

Note that for larger JSON data, using parsed is significantly slower than using stringified, because parsed data must go through a JSON encoding step.

A simple example using stringified data:

topoData <- readLines("") %>% paste(collapse = "\n") 

leaflet() %>% setView(lng = -98.583, lat = 39.833, zoom = 3) %>%
  addTiles() %>%
  addTopoJSON(topoData, weight = 1, color = "#444444", fill = FALSE)

Styling raw GeoJSON/TopoJSON

You can modify the style of GeoJSON/TopoJSON features in a few ways. (Currently only paths and shapes can be styled; marker styling is not supported.)

One way to apply styles to all of the features is to use the arguments directly with addGeoJSON()/addTopoJSON(). Another way is to encode styling information directly in the JSON object/string by putting a style object directly underneath the top level JSON object.

You can provide feature-specific styles by annotating each feature’s property object with a style: {...} object. The feature-specific styles have the highest precedence, then the top-level style object, and finally the style-related arguments passed to the function.

See Leaflet’s path options for available style properties.

The previous example demonstrated the style arguments. Below is a more involved example that sets both global styles and per-feature styles directly into the JSON object.

(This approach is not recommended for applying styling in R; instead, use the approach described above where we convert to sp first. However, if you have control over the process that generates the GeoJSON in the first place, you might use these techniques to put the styling information directly in the JSON.)


# From
geojson <- readLines("", warn = FALSE) %>%
  paste(collapse = "\n") %>%
  fromJSON(simplifyVector = FALSE)

# Default styles for all features
geojson$style = list(
  weight = 1,
  color = "#555555",
  opacity = 1,
  fillOpacity = 0.8

# Gather GDP estimate from all countries
gdp_md_est <- sapply(geojson$features, function(feat) {
# Gather population estimate from all countries
pop_est <- sapply(geojson$features, function(feat) {
  max(1, feat$properties$pop_est)

# Color by per-capita GDP using quantiles
pal <- colorQuantile("Greens", gdp_md_est / pop_est)
# Add a properties$style list to each feature
geojson$features <- lapply(geojson$features, function(feat) {
  feat$properties$style <- list(
    fillColor = pal(
      feat$properties$gdp_md_est / max(1, feat$properties$pop_est)

# Add the now-styled GeoJSON object to the map
leaflet() %>% addGeoJSON(geojson)