I'm creating a web map using Leaflet, and I want to be able to grab feature layers from our ArcServer. I have successfully been able to retrieve a feature class as JSON, but Esri's JSON objects don't follow the GeoJSON standards so they cannot be displayed.
Does anyone know of a conversion script or tool that handles this?
If not, I plan on creating a script to convert ArcServer JSON objects to GeoJSON.
-
I was having trouble getting ogr2ogr to eat ESRI json coming from a MapServer feature query. (@SasaIvetic's example uses a FeatureServer request, and the MapServer result I need to consume must not have been interchangeable.) Anyway, this site totally did the trick: http://ogre.adc4gis.com/elrobis– elrobis2015年10月12日 16:08:47 +00:00Commented Oct 12, 2015 at 16:08
14 Answers 14
OGR:
ogr2ogr -f GeoJSON test.json "http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydrography/Watershed173811/FeatureServer/0/query?where=objectid+%3D+objectid&outfields=*&f=json" OGRGeoJSON
That command will read the query result directly from the URL. You can also supply it with a text file containing your JSON or you can directly supply encoded JSON on the command line. You can of course use ORG Python bindings to automate it within a script if necessary, or the library to do it in code.
For those that like web services, see Ogre an ogr2ogr web client which can convert json to geojson to and back, as well as geojson to shapefile.
Reference: http://www.gdal.org/drv_geojson.html
-
I downloaded FWTools. When I run that command, I get the error 'Unable to open datasource 'My URL here' with the following drivers. -> ESRI Shapefile -> MapInfo File -> UK .NTF -> SDTS -> TIGER -> S57 -> DGN -> VRT -> REC -> Memory -> BNA -> CSV -> NAS -> GML -> GPX -> KML -> GeoJSON -> Interlis 1 -> Interlis 2 -> GMT -> SQLite -> ODBC -> PGeo -> OGDI -> PostgreSQL -> MySQL -> XPlane -> AVCBin -> AVCE00 -> DXF -> Geoconcept -> GeoRSS -> GPSTrackMaker -> VFK I don't see something like 'ESRI JSON' in the list of drivers.Tanner– Tanner2011年08月03日 20:15:10 +00:00Commented Aug 3, 2011 at 20:15
-
1@Tanner: FWTools comes with OGR v1.7 where GeoJSON support was added with v1.8.0. I'm running GDAL/OGR 1.9dev here, though not through FWTools. I think I got them from gisinternals.com/sdkSasa Ivetic– Sasa Ivetic2011年08月03日 20:33:25 +00:00Commented Aug 3, 2011 at 20:33
-
Thanks. I got this to work on the command line. I'm still working on getting it to work in my Javascript - any tips would be appreciated.Tanner– Tanner2011年08月04日 18:03:31 +00:00Commented Aug 4, 2011 at 18:03
-
@Tanner how did you get past that error? It's not a version issue for me but I'm getting the same error on my windows machinekflaw– kflaw2016年06月22日 19:45:31 +00:00Commented Jun 22, 2016 at 19:45
-
@kflaw Sorry, but I don't recall exactly. I think I just used ogr2ogr on the command line, and didn't need or use FWTools.Tanner– Tanner2016年06月23日 17:19:36 +00:00Commented Jun 23, 2016 at 17:19
You can also see Esri's geojson-utils on Github that "contains [javascript] utilities for converting GeoJSON to other geographic json formats and vice versa. Currently only GeoJSON to Esri JSON has been developed. Also, note that only geometries in the WGS84 coordinate system are supported."
-
2Update 12/2017:
geojson-utils
is deprecated. See arcgis-to-geojson-utils or terraformerGavinR– GavinR2017年12月11日 14:44:17 +00:00Commented Dec 11, 2017 at 14:44
ArcGIS now supports GeoJSON
Now ArcGIS Server (since 10.4) and ArcGIS Online has GeoJSON through ArcGIS Rest API URL. All you need to do is set f=geojson
in the URL and configure the service. Be aware, by default, ArcGIS Online will not allow GeoJSON export until you explicit permit other output formats.
Here is how to enable the export:
- Log into ArcGIS Online
- Click the feature layers,
- Click the setting tab
- Check this box that says
Export Data
Allow others to export to different formats. 5. Save and wait a few minutes.
In the query page, you should see the output format dropdown list with the GeoJSON option. The old was called json
.
- Here is news release announcing the feature from Dec 2014
- You can see a sample of their GeoJSON out here
- Here is an HTML forum with customizable options showing you what the ArcGIS API is capable of
-
1Is a agol rest service different from an ArcGIS server rest service? Can only agol provide geoJSON as a rest service and not server?jotamon– jotamon2018年03月29日 23:57:01 +00:00Commented Mar 29, 2018 at 23:57
-
I just edited the asnwer, hopefully will be shown soon, this is also supported in ArcGIS Server as of 10.4najel– najel2020年07月09日 01:36:24 +00:00Commented Jul 9, 2020 at 1:36
-
While AGOL/ArcGIS Server do "support" GeoJSON, attempting to export data using this format can lead to timeouts. Try downloading data from the USGS "National Map" endpoints. The JSON endpoints do not appear to suffer from this timeout issue.Malcolm– Malcolm2021年12月18日 11:42:59 +00:00Commented Dec 18, 2021 at 11:42
ESRI JSON to GeoJSON (for OpenLayers) *Likely to be modified for Leaflet javascript
//create esri JSON object
var myReturn = "esriObj = "+xmlHttpGet(restCall, false);
eval(myReturn);
I can now work with esriObj as a JSON object i.e. esriObj.geometryType. What happens in the xmlHttpGet method? Basically I create a XMLHttpRequest and pass in my REST URL – your can see this code here
3. OK i have my ‘ESRI query’ JSON object now I need to parse the features in this object and essentially create GeoJSON strings which the OpenLayers sample will be happy with – cue the code butchery...
function esriDeserialize(geojson)
{
var element = document.getElementById('text');
var type = document.getElementById("formatType").value;
var features = formats['in'][type].read(geojson);
var bounds;
if(features)
{
if(features.constructor != Array) {
features = [features];
}
for(var i=0; i<features.length;>
if (!bounds) {
bounds = features[i].geometry.getBounds();
} else {
bounds.extend(features[i].geometry.getBounds());
}
}
vectors.addFeatures(features);
//map.zoomToExtent(bounds);
var plural = (features.length > 1) ? 's' : '';
//element.value = features.length + ' feature' + plural + ' added'
} else {
element.value = 'Bad input ' + type;
}
}
function getEsriGeom(restCall){
//call ESRI Rest API
//"http://pc302926/ArcGIS/rest/services/worldadmin/MapServer/0/query?text=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&where=%22FIPS_CNTRY%22+%3D+%27AS%27&returnGeometry=true&outSR=4326&outFields=&f=json"
var element = document.getElementById('text');
//create esri JSON object
var myReturn = "esriObj = "+xmlHttpGet(restCall, false);
eval(myReturn);
element.value = "";
var coordPairsPerFeature = 0;
//for each feature
for (var i=0; i < esriObj.features.length; i++)
{
//get the geometry
var o = esriObj.features[i].geometry;
element.value = element.value + esriObj.features[i].attributes.ADMIN_NAME;
//loop through all the rings
for (var s=0; s < o.rings.length; s++)
{
//create geojson start & end - i know i'm getting polygons
var geojsonstart = '{"type":"Feature", "id":"OpenLayers.Feature.Vector_124", "properties":{}, "geometry":{"type":"Polygon", "coordinates":[['
var geojsonend = ']]}, "crs":{"type":"OGC", "properties":{"urn":"urn:ogc:def:crs:OGC:1.3:CRS84"}}}';
//the coordinates for this ring
var coords = o.rings[s];
//loop through each coordinate
var coordPair="";
for (var g=0; g < coords.length; g++)
{
coordPairsPerFeature = coordPairsPerFeature+1;
//alert(coords[g]);
if(g==coords.length-1){
coordPair = coordPair+"["+coords[g]+"]";
}else{
coordPair=coordPair+"["+coords[g]+"],";
}
}
//combine to create geojson string
esriDeserialize(geojsonstart+coordPair+geojsonend);
}
element.value = element.value + "," + coordPairsPerFeature +"n";
}
}
</features.length;>
source: http://mapbutcher.com/blog/?p=62
-
If you're going to convert you should use ogr2ogrEvan Carroll– Evan Carroll2017年01月12日 07:36:54 +00:00Commented Jan 12, 2017 at 7:36
-
"*Likely to be modified for Leaflet javascript" - is there an update? (also, the Map Butcher URL is 404 :-(Mawg– Mawg2020年11月10日 21:09:13 +00:00Commented Nov 10, 2020 at 21:09
Converting ArcGIS JSON to GeoJSONThere in pure Browser
there are 2 ways you can do
Note: use in node.js and use in browser are different, details see link
2) Esri/arcgis-to-geojson-utils
use in browser, ArcgisToGeojsonUtils is global var reference the entry point of this module
<script src="https://unpkg.com/@esri/[email protected]/dist/arcgis-to-geojson.js"></script>
// parse ArcGIS JSON, convert it to GeoJSON
const geojson = ArcgisToGeojsonUtils.arcgisToGeoJSON({
"x":-122.6764,
"y":45.5165,
"spatialReference": {
"wkid": 4326
}
});
However, if you want to bundle by yourself, just for learning, follow steps
a) You need to compile all the module source file into a single bundle.js
rollup.js install by
npm install --global rollup
then go to your js lib root folder, find the entry point js file, in this case it is index.js
$ rollup index.js --format umd --name "esri_arcgis_to_geojson" --file bundle.js
You should find a new file bundle.js in your root directory.
Now in your browser html file, include this bundle.js file
<script src='.../.../.../bundle.js'>
You can use it now by
// parse ArcGIS JSON, convert it to GeoJSON
var geojson = esri_arcgis_to_geojson.arcgisToGeoJSON({
"x":-122.6764,
"y":45.5165,
"spatialReference": {
"wkid": 4326
}
});
// take GeoJSON and convert it to ArcGIS JSON
var arcgis = esri_arcgis_to_geojson.geojsonToArcGIS({
"type": "Point",
"coordinates": [45.5165, -122.6764]
});enter code here
Remember esri_arcgis_to_geojson is the name you named the lib
This becomes the global variable name, available in browser.
The trick is, bundle process add instant implement function like (function xx {}) here is the top part from bundle.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ?
factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'],
factory) :
(factory((global.arcgis_to_geojson = {})));
}(this, (function (exports) { 'use strict';
***ORIGINAL SOURCE CODE OF JS MODULE***
})));
-
This webpage: ArcGIS JSON to GeoJSON uses Terraformer and you can see an example of how it's used hereJohn– John2024年07月24日 14:13:18 +00:00Commented Jul 24, 2024 at 14:13
Leaflet and ArGIS vector layer.
https://github.com/JasonSanford/leaflet-vector-layers
Working demo. http://geojason.info/leaflet-vector-layers/demos/arcgis-server/
More on Leaflet and ArcGIS.
- Leaflet and ArcGIS Server layers i.e. AgsDynamicLayer and AgsFeatureLayer.
You can get this fork which has support for ArcGIS server.
https://github.com/dtsagile/Leaflet/
var sitesLayer = new L.AgsDynamicLayer(
'http://ags2.dtsagile.com/ArcGIS/rest/services/LiveFeeds/WxMappr/MapServer',
{ maxZoom: 19,
attribution: "NOAA",
opacity: 1,
layers: 'show:2' });
_map.addLayer(sitesLayer);
http://blog.davebouwman.com/2011/08/04/leaflet-lean-mean-javascript-maps/
ArcGIS Image Services and Leaflet http://blog.geomusings.com/2012/04/17/arcgis-image-services-and-leaflet/
Its usually* pretty easy converting.
I made a script https://github.com/calvinmetcalf/esri2geo and there are others that work well too.
*The exception is multi-part polygons with holes which don't convert 1-to-1 without some geoprocessing.
I've built a server object extension to generate GeoJSON from ArcGIS Server map services. It's been tested with 10.1 and 10.2 but not earlier. https://github.com/geobabbler/AGSOpenFormats
For a one-time conversion I would have used the accepted answer from @Sasa Ivetic but needed something real-time, and Terraformer worked decently for that. Unfortunately it's only for single features by default, so for multiple features you need to loop through the array and add an ID to each feature:
var FeatureCollection = {
type: "FeatureCollection",
features: []
}
for (var i = 0; i < arcgis.features.length; i++) {
var feature = Terraformer.ArcGIS.parse(arcgis.features[i]);
feature.id = i;
FeatureCollection.features.push(feature)
};
This worked fine for me except on multi-part polygons (i.e. Alaska and its islands), but I'm new to this so it's possible I coded something incorrectly!
If its a one time query and you don't have more than 1000 features try pasting this into qgis by using the add vector layer - choose protocol and replace this arcgis rest URL with yours: http://geodata.epa.gov/arcgis/rest/services/OAR/USEPA_NEI_2005/MapServer/1/query?where=objectid+%3D+objectid&outfields=*&f=json ... This assumes you have gdal 1.10 installed
I made a web version of ESRI's Terraformer tool for ESRI JSON -> GeoJSON conversion in the browser at https://observablehq.com/@thadk/arcgis-json-parser-to-geojson which can be customized as needed when the ArcGIS server does not allow you to export it as GeoJSON directly.
Perhaps even easier you can use the Esri-leaflet library to add it natively as a layer in Leaflet.
-
3Could you incorporate an example in your post outlining how this answer's the OP's question?Paul– Paul2013年09月26日 18:00:33 +00:00Commented Sep 26, 2013 at 18:00
If all you need is to return the ArcServer Service as a GeoJSON to use in whichever mapping tech you want, I highly recommend you look at this GitHub issue dialogue.
I am not going to replicate the dialogue here because that would waste time. Your options are clearly laid out there directly from Esri.
arcgis server rest api, feature service,
if you query the layer, with URL like this, .../FeatureServer/query?layerDefs=...
http://services3.arcgis.com/your_token/arcgis/rest/services/Parcels/FeatureServer/query?layerDefs={"0":""}&returnGeometry=true&f=pgeojson&geometryType=esriGeometryEnvelope&geometry={"xmin" : -117.923158, "ymin" : 33.644081, "xmax" : -117.921436, "ymax" : 33.645157,"spatialReference" : {"wkid" : 4326}}
You can not set geojson format, f=pgeojson will be bad request, f=json, because the return stuff is not feature, the layers json was return.
Try this html query page, you can see, no geojson option,
http://services3.arcgis.com/you_token/arcgis/rest/services/Parcels/FeatureServer/query
If you want to return geojson (feature), you must use this URL .../FeatureServer/0/query...
/0/ means layerID, if on has only 1 layer, then layerID = 0.....
Try this html query page, you can see, geojson is option, because you are query specific layer with layerID = 0
http://services3.arcgis.com/your_token/arcgis/rest/services/Parcels/FeatureServer/0/query
Note: remember to set those 2 parameters: outSR=4326&f=geojson in the URL spatial reference ID, srid = 4326, because web map all use this, f means format, both f=pgeojson and f=geojson works. If you don't set outSR=4326, arcgis server rest api by default will NOT use 4326, instead use something else, only 4326 has unit degree, which is used in most web map. Other format would not work with web maps.
By the way, for those want to use arcgis server rest api with tile service,
tilestream and others
/zoom(z)/x/y.png
http://localhost/v2/city_parcels/12/706/1641.png
arcgis server tile service: no png, x and y in different order
/zoom(z)/y/x
http://services3.arcgis.com/your_token/ArcGIS/rest/services/Parcels/MapServer/tile/12/1641/706