2

I'm trying to use the arcGIS Rest API to add features to a feature layer, but I get an "Invalid JSON primitive: geometry" error. I get the same results if I leave out the spatialReference.

The feature layer was created on the arcGIS Developer Site, setting the geometry type to "Points". The fields are store_id (integer), address (string), items (string), and item_desc (string).

What am I doing wrong?

Python 2.7 code

import requests

def test_upload(token):
    test_locations = [
        {
            'store_id': 79,
            'address': 'address1',
            'latitude': 48.4680466419,
            'longitude': -94.4650303558,
            'item_id': '2 3 1',
            'desc': 'bar, baz, foo'
        },
        {
            'store_id': 89,
            'address': 'address2',
            'latitude': 48.7006190216,
            'longitude': -115.9411092720,
            'item_id': '2',
            'desc': 'bar'
        },
        {
            'store_id': 161,
            'address': 'address3',
            'latitude': 48.7425504958,
            'longitude': -111.5460764360,
            'item_id': '3 1',
            'desc': 'baz, foo'
        }
    ]

    features = []
    for location in test_locations:
        feature = {
            'attributes': {
                'store_id': location['store_id'],
                'address': location['address'],
                'items': location['item_id'],
                'item_desc': location['desc']
            },
            'geometry': {
                'x': location['longitude'],
                'y': location['latitude'],
                'spatialReference': {'wkid': 4326}
            }
        }
        features.append(feature)
    data = {
        'f': 'json',
        'features': features,
        'rollbackOnFailure': False,
        'token': token
    }

    print '############'
    print 'The JSON request looks like:'
    printable_data = data.copy()
    printable_data['token'] = '<withheld>'
    print json.dumps(printable_data, indent=2, separators=(',', ': '))
    print
    print '############'

    resp = requests.post(FEATURE_URL + '/addFeatures', data=data)
    print 'The response from the server is:'
    print 'HTTP Status Code:', resp.status_code
    print json.dumps(resp.json(), indent=2, separators=(',', ': '))


Output
When FEATURE_URL is defined and test_upload is passed a valid token, this gives the following output:

############
The JSON request looks like:
{
  "rollbackOnFailure": false,
  "features": [
    {
      "geometry": {
        "y": 48.4680466419,
        "x": -94.4650303558,
        "spatialReference": {
          "wkid": 4326
        }
      },
      "attributes": {
        "items": "2 3 1",
        "item_desc": "bar, baz, foo",
        "store_id": 79,
        "address": "address1"
      }
    },
    {
      "geometry": {
        "y": 48.7006190216,
        "x": -115.941109272,
        "spatialReference": {
          "wkid": 4326
        }
      },
      "attributes": {
        "items": "2",
        "item_desc": "bar",
        "store_id": 89,
        "address": "address2"
      }
    },
    {
      "geometry": {
        "y": 48.7425504958,
        "x": -111.546076436,
        "spatialReference": {
          "wkid": 4326
        }
      },
      "attributes": {
        "items": "3 1",
        "item_desc": "baz, foo",
        "store_id": 161,
        "address": "address3"
      }
    }
  ],
  "token": "<withheld>",
  "f": "json"
}

############
The response from the server is:
HTTP Status Code: 200
{
  "error": {
    "message": "Cannot perform operation. Invalid operation parameters.",
    "code": 400,
    "details": [
      "'features' parameter is invalid",
      "Invalid JSON primitive: geometry."
    ]
  }
}
  • Are you using an HTTP monitoring tool such as Fiddler to verify the requests are being passed correctly? What happens when you do a json.dumps on your data when you pass it into the post request? resp = requests.post(FEATURE_URL + '/addFeatures', json.dumps(data)) – crmackey Nov 2 '15 at 16:40
  • Changing data=data to json.dumps(data) doesn't seem to pass the request correctly. I get back an HTML (not JSON) response that includes <div class="restErrors">Token Required<br/></div>. I'll look into Fiddler. – erichamion Nov 3 '15 at 2:10
  • That's interesting as you are clearly passing in a token. Maybe try it on this line: 'features': json.dumps(features). Other than that, your code looks like it should be working to me. But yes, definitely download Fiddler and open it while you run this code. Inside the Inspectors tab, when you click on the WebForms tab it will show all the parameters you passed in your query. This is by far the best tool I have found for debugging python requests against REST Endpoints. – crmackey Nov 3 '15 at 13:53
  • 1
    I figured out a workable solution for updating features where I was getting the same error. Let me know if you'd like me to post. – traggatmot Dec 13 '16 at 23:46
  • 1
    Great news! I don't need it anymore, but it might help somebody in the future if you feel like posting an answer. – erichamion Dec 15 '16 at 0:32
1

The problem is due to the list getting lost using resp.url would probably come back with something like ...&updates=geometry&updates=attributes&f=json....

Therefore json.dumps is the answer but you want to do it to the features list not to the data.

data = {
    'f': 'json',
    'features': json.dumps(features),
    'rollbackOnFailure': False,
    'token': token
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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