[GIS] “Invalid JSON primitive: geometry” when adding features

arcgis-rest-apijsonpython

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."
    ]
  }
}

Best Answer

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
}
Related Question