0

Using Python, I have an api with security incidents that I want to populate into a feature service layer. I've achieved this successfully using Add Features via the ArcGIS REST API endpoint (described here). However the original point feature class is stored in SDE, which has a defined coordinate system - WGS 1984 Web Mercator (Auxiliary Sphere)

Therefore my points are being added with the wrong projection (because I'm adding using the just geographic coordinates).

Are there any programmatic solutions to change the geometry to a matching projection before adding the features? Or some other work around to match the projection?

My (slightly modified) working code is included. Basically I have two functions - the first one grabs the API data and then returns a list of reformatted features. Then, the next function takes that list as input and adds each feature to the feature service layer.

import urllib
import requests
import json, time
from datetime import datetime
import unicodedata
    
def getFeaturesReformatPayload(api_url):
    ''' Requests API, returns list with reformatted payload for adding features.
    '''
    # get planet risk data
    print('Getting Planet Risk data...')
    response = requests.get(api_url)
    if response.status_code == 200:
        print("Success") 
    else:
        print("There was an error")
    
    payload = response.json()
    
    # reformat the payload to be added to feature layer
    payload_reformatted = []

    for i, x in enumerate(payload['result']['resourceList'][0]['resource']):
        
        # convert datetime in time cols - 'updated', 'created'
        created_time = x['created'][:-3] # shortened epoch to seconds
        # print('Length of created timestamp: {}'.format(len(str(created_time))))
        updated_time = x['updated'][:-3]
        # print('Length of updated timestamp: {}'.format(len(str(updated_time))))
        
        # convert unicode to string
        created_time_str = unicodedata.normalize('NFKD', created_time).encode('ascii', 'ignore')
        updated_time_str = unicodedata.normalize('NFKD', updated_time).encode('ascii', 'ignore')
        created_formatted = datetime.fromtimestamp(float(created_time_str)) 
        updated_formatted = datetime.fromtimestamp(float(updated_time_str)) 


        # copy dict then update formatted time in the dict
        copy_dict = x.copy()
        copy_dict.update({'created': str(created_formatted)[:10]}) # removing timestamp - just date
        copy_dict.update({'updated': str(updated_formatted)[:10]})
        # print('Feature #: {} , was created on {}, and was last updated on {}'.format(i, created_formatted, updated_formatted))

        # create geometry - delete unwanted fields - append to reformatted
        geometry_dict = dict(y = x['lat'], x = x['lng'])
        deleteFields = ['lat', 'lng', 'resourcetype', 'id']
        for x in deleteFields:
            copy_dict.pop(x)
        payload_out = dict(attributes = copy_dict, geometry = geometry_dict)
        payload_reformatted.append(payload_out)
        
    print('Total Number of Incidents: {}'.format(len(payload_reformatted)))
    
    return payload_reformatted

def addIncidentsToFSL(input_payload):
    ''' Adds input payload to the feature service layer via proxy.
    '''
    
    # proxy bypasses authentication 
    proxy_path = "https://servername.example.net/DotNet/proxy.ashx?"
    feature_layer_endpoint = "https://servername.example.com/arcgis/rest/services/National/examplePublishedMXD/FeatureServer/3/addFeatures"

    url = "".join([proxy_path,feature_layer_endpoint ])
    # print(url)
    for i, k in enumerate(input_payload):
        print('\nAdding Incident to Feature Service Layer: {}'.format(i))
        
        payload_body = {'f': 'json', 'features': json.dumps([input_payload[i]])}
        # print(payload_body)
        print('...')
        r = requests.post(url, data = payload_body, verify = False)
        
        # print response
        if r.status_code == 200:
            print('Success')
        else:
            print('Failed')
            
        # wait 3 seconds
        time.sleep(3)

if __name__ == "__main__":
    # define api, get features, reformat, add to feature service layer
    example_api = 'string_with_apiURL' 
    
    reformatted_payload = getFeaturesReformatPayload(example_api)
    addIncidentsToFSL(reformatted_payload)
    print('All Features Added from API to Feature Service Layer')

1 Answer 1

4

I know you can send the following JSON to an addFeatures end point which defines the input coordinates.

[{
  "geometry" : 
   {"x" : -115, "y" : 36, "spatialReference" : {"wkid" : 4326}},
 "attributes" : {
   "id" : 111
  }
}]

It looks like you're creating your geometry with this call:

geometry_dict = dict(y = x['lat'], x = x['lng'])

You can add in the spatial ref and WKID.

# Update 4326 to whatever matches your coordinates.
sr = {"spatialReference" : {"wkid" : 4326}}
{**dict(y = x['lat'], x = x['lng']), **sr}

Output:

{'y': 111, 'x': 222, 'spatialReference': {'wkid': 4326}}

Note - The Python code above assumes 3.5+. If you are using < 3.5, you can read about other techniques to merge dictionaries.

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.