python script - select by json

4332
3
Jump to solution
09-11-2014 08:51 AM
J_B__K_
New Contributor III

HI!

I´m a bit stuck with this easy trouble... I need to make a geoprocessing service, it will take JSON geometry, select features in database and answer questions like "are there any features/how many features/witch features are in that JSON polygon. Im not able to find out how to write python script to select features by JSON... Any advise? Thank you!

0 Kudos
1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

To send a geometry, the geometry has to be specified in JSON format.

  • As from ArcGIS 10.1 SP1 you can use the json token SHAPE@JSON on a feature during a search cursor.
  • In ArcGIS 10.1 the arcpy.Polygon object has a property called "JSON" (arcpy.Polygon.JSON) which will do this for you.
  • In ArcGIS 10.0 you have to go a little deeper and use the private property arcpy.Polygon.__geo_interface__

Now, what might be a challenge, is (or was) the fact that the Python JSON flavor is not the same flavor ArcGIS Server consumes. This means that you will have to do some manual conversion to obtain the correct format.

# let's say you have an arcpy.Polygon object. No get the JSON:

polygonJSON = polygon.__geo_interface__ # 10.0 syntax

# convert this to the correct JSON format for ArcGIS Server

data_string = str(polygonJSON)

data_string = data_string.replace("'type': 'Polygon', 'coordinates':","'rings':")

data_string = data_string.replace("(", "[")

data_string = data_string.replace(")", "]")

You can use the urllib library to encode all your parameters like this:

params = urllib.urlencode({'f': 'json', 'geometryType': 'esriGeometryPolygon',

           'geometry': data_string, 'spatialRel': 'esriSpatialRelIntersects',

           'where': '1=1', 'outFields': '', 'returnGeometry': 'true'})

If you know the service URL to query:

http://someserver/ArcGIS/rest/services/aFolder/sService/MapServer/0

This actual url to connect to will be

http://someserver/ArcGIS/rest/services/aFolder/sService/MapServer/0/query

To force the POST request you will have to do the following:

# assuming this query URL

queryURL = "http://someserver/ArcGIS/rest/services/aFolder/sService/MapServer/0/query"

# use the request method on the urllib2 library

req = urllib2.Request(queryURL, params) # forces POST request

# get the response

response = urllib2.urlopen(req)

The response will be file based GeoJSON. To create a JSON object you will need to do the following:

# assuming this query URL

jsonResult = json.load(response)

Next, process the JSON with the results...

Kind regards, Xander

View solution in original post

0 Kudos
3 Replies
BruceHarold
Esri Regular Contributor

You'll want to make the input JSON a string parameter as use it as an argument to arcpy.AsShape().

The JSON will need to be well formed GeoJSON or EsriJSON, and if the former don;t forget to set a spatial reference to the result.  Also don't forget the boolean second argument to AsShape.

Regards

0 Kudos
J_B__K_
New Contributor III

Thank you. I´ve tested arcpy.AsShape(), but I don´t know how to select features with that polygon... ??? I know it must be something easy, but I can´t solve it...

0 Kudos
XanderBakker
Esri Esteemed Contributor

To send a geometry, the geometry has to be specified in JSON format.

  • As from ArcGIS 10.1 SP1 you can use the json token SHAPE@JSON on a feature during a search cursor.
  • In ArcGIS 10.1 the arcpy.Polygon object has a property called "JSON" (arcpy.Polygon.JSON) which will do this for you.
  • In ArcGIS 10.0 you have to go a little deeper and use the private property arcpy.Polygon.__geo_interface__

Now, what might be a challenge, is (or was) the fact that the Python JSON flavor is not the same flavor ArcGIS Server consumes. This means that you will have to do some manual conversion to obtain the correct format.

# let's say you have an arcpy.Polygon object. No get the JSON:

polygonJSON = polygon.__geo_interface__ # 10.0 syntax

# convert this to the correct JSON format for ArcGIS Server

data_string = str(polygonJSON)

data_string = data_string.replace("'type': 'Polygon', 'coordinates':","'rings':")

data_string = data_string.replace("(", "[")

data_string = data_string.replace(")", "]")

You can use the urllib library to encode all your parameters like this:

params = urllib.urlencode({'f': 'json', 'geometryType': 'esriGeometryPolygon',

           'geometry': data_string, 'spatialRel': 'esriSpatialRelIntersects',

           'where': '1=1', 'outFields': '', 'returnGeometry': 'true'})

If you know the service URL to query:

http://someserver/ArcGIS/rest/services/aFolder/sService/MapServer/0

This actual url to connect to will be

http://someserver/ArcGIS/rest/services/aFolder/sService/MapServer/0/query

To force the POST request you will have to do the following:

# assuming this query URL

queryURL = "http://someserver/ArcGIS/rest/services/aFolder/sService/MapServer/0/query"

# use the request method on the urllib2 library

req = urllib2.Request(queryURL, params) # forces POST request

# get the response

response = urllib2.urlopen(req)

The response will be file based GeoJSON. To create a JSON object you will need to do the following:

# assuming this query URL

jsonResult = json.load(response)

Next, process the JSON with the results...

Kind regards, Xander

0 Kudos