1

I'm new to working with GeoJSON and have been reviewing the ArcGIS page for AsShape, but the examples seem a little thin.

I'm currently pulling a WFS from a GeoServer instance in GeoJSON format. I am using pycurl to do this as the service is https and it's easier to do authentication with pycurl. I basically issue my url query and build a file (results.json).

I know how to easily build point feature classes from any text (including json) and build attributes using cursors, but the data I'm working with now has lines and polygons as well.

Could anyone give me some guidance, share a snippet, or something that basically shows me how to get into the .json file with AsShape, or uses AsShape successfully with the json.load command?

1 Answer 1

6

It is pretty simple actually, you just need to iterate through the features of the geojson structure once you have got it in a dictionary format (like from the json.load() function). I don't work with GeoServer WFS services, but I did find a json example online. The first shows just how to iterate through the json and get an arcpy.Geometry object back.

import arcpy
import os
arcpy.env.overwriteOutput = True

geojson = {
    "type": "FeatureCollection",
    "features": [{
        "type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": [102.0, 0.5]
        },
        "properties": {
            "Name": "aoi",
            "Source": "google"
        }
    }, {
        "type": "Feature",
        "geometry": {
            "type": "LineString",
            "coordinates": [
                [102.0, 0.0],
                [103.0, 1.0],
                [104.0, 0.0],
                [105.0, 1.0]
            ]
        },
        "properties": {
            "Name": "centerline",
            "Source": "bing"

        }
    }, {
        "type": "Feature",
        "geometry": {
            "type": "Polygon",
            "coordinates": [
                [
                    [100.0, 0.0],
                    [101.0, 0.0],
                    [101.0, 1.0],
                    [100.0, 1.0],
                    [100.0, 0.0]
                ]
            ]
        },
        "properties": {
            "Name": "parking lot",
            "Source": "esri"
        }
    }]
}

# print type from arcpy.Geometry objects
for ft in geojson['features']:
    geom = arcpy.AsShape(ft['geometry'], False)
    print geom.type

This example should print the following:

point
line
polygon

Taking a similar json structure for polygon features, you can easily convert it to a feature class by first creating a feature class, adding the necessary fields, then using an Insert Cursor to feed in the values.

import arcpy
import os
arcpy.env.overwriteOutput = True

geojson2 = {
    "type": "FeatureCollection",
    "features": [{
        "type": "Feature",
       "geometry": {
            "type": "Polygon",
            "coordinates": [
                [
                    [300.0, 200.0],
                    [301.0, 200.0],
                    [301.0, 201.0],
                    [300.0, 201.0],
                    [300.0, 200.0]
                ]
            ]
        },
        "properties": {
            "Name": "aoi",
            "Source": "google"
        }
    }, {
        "type": "Feature",
       "geometry": {
            "type": "Polygon",
            "coordinates": [
                [
                    [100.0, 0.0],
                    [101.0, 0.0],
                    [101.0, 1.0],
                    [100.0, 1.0],
                    [100.0, 0.0]
                ]
            ]
        },
        "properties": {
            "Name": "centerline",
            "Source": "bing"

        }
    }, {
        "type": "Feature",
        "geometry": {
            "type": "Polygon",
            "coordinates": [
                [
                    [400.0, 300.0],
                    [401.0, 300.0],
                    [401.0, 301.0],
                    [400.0, 301.0],
                    [400.0, 300.0]
                ]
            ]
        },
        "properties": {
            "Name": "parking lot",
            "Source": "esri"
        }
    }]
}

# we are working with polygons, so make new polygon fc
fc = r'C:\TEMP\testing.gdb\geojson_test'
sr = arcpy.SpatialReference(26915)  # utm 15N

path, name = os.path.split(fc)
arcpy.management.CreateFeatureclass(path, name, 'POLYGON', spatial_reference=sr)

# add fields as listed from the properties of each feature
fields = ['Name', 'Source']
for field in fields:
    arcpy.management.AddField(fc, field, 'TEXT')

# insert rows
with arcpy.da.InsertCursor(fc, ['SHAPE@'] + fields) as irows:
    for feature in geojson2['features']:
        geom = arcpy.AsShape(feature['geometry'], False)
        irows.insertRow([geom] + [feature['properties'][f] for f in fields])
print 'done'

I would also recommend having a look at the requests module instead of pycurl, you can get format back as raw json and do not have to worry about working with intermediate .json files. It also supports all kinds of authorization types and passing in arguments is very elegant.

4
  • Thanks crmackey, this isn't the first time you've helped me out! I appreciate it. Yeah, I use pycurl because I have to authenticate using a client certificate, which I send as a .pem. It's very simple and straightforward, but it sounds like I'll gain something by swapping it out for requests.
    – auslander
    Commented Jul 13, 2016 at 13:27
  • No problem. And, yes with the requests module I do believe you are able to send the .pem files with your requests. Alternatively, you can set the verify=False parameter to not validate SSL certificates. It is definitely worth checking out though!
    – crmackey
    Commented Jul 13, 2016 at 13:40
  • Actually, one question on general approach for json content that contains multiple geometries - how would you suss those out? the geometry tokens are different between point/line/polygon, which i guess would require 3 separate InsertCursor functions. Would you use if statements to check the geometry first and then include the InsertCursor within the loop, or is there a more elegant way to do that?
    – auslander
    Commented Jul 13, 2016 at 18:23
  • Right, you are exactly correct. In my first example there are 3 different geometry types in the geojson. So what I would do is create a feature class for each geomerty type. Then you could do the same process of creating fields based on the properties of each feature.
    – crmackey
    Commented Jul 13, 2016 at 20:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.