How to copy feature layer schema without downloading?

965
3
07-02-2020 09:28 AM
JoeBryant1
Occasional Contributor III

I'd like to save myself some work by not creating a feature service layer from scratch. I have edit access to the secure feature service layer I'd like to base my new feature service on, but it has not been enabled for downloading (I don't own the service and I don't have publishing rights in the organization that owns it). I don't need the data from the current service - I just want to create an identical feature service layer schema for a similar workflow in another project.

I tried to use AGOL Assistant's copy tool, but I cannot copy an item I do not own.

I then tried copying and pasting the json definition for the service in to a text file, and creating a new service using that json file, but AGOL only accepts GeoJSON as input (the json text does not start with "type": "FeatureCollection"). I'm not a developer, so forgive any gaps in my knowledge regarding JSON files.

What is the easiest way to accomplish this? Any tools in Pro?

Tags (2)
0 Kudos
3 Replies
GeoJosh
Esri Regular Contributor

Hey Joe,

If you have access to the REST endpoint of the service and Python 3, you can get this done using ArcPy. Here's a quick example I spun up. It's not perfect, but I ran it on a few different feature layers and it seems to work.

import requests
import json
import arcpy

# Set variables

featureLayerURL = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessmentStatePlane/FeatureServer/0"
fgdbPath = r"C:\temp\test.gdb"
featureClassName = "TEST1"
featureClassGeometry = "POINT"

# Get feature layer information in JSON format

r = requests.get(featureLayerURL + "?f=json")

# Get field information from the response

fields = json.loads(r.text)["fields"]

# Maps feature layer field types to feature class field types

field_types = {
    "esriFieldTypeString""TEXT",
    "esriFieldTypeDate""DATE",
    "esriFieldTypeDouble""DOUBLE",
    "esriFieldTypeInteger""SHORT"
}

# Creates a new feature class

fc = arcpy.CreateFeatureclass_management(out_path=fgdbPath, out_name=featureClassName, geometry_type=featureClassGeometry)

# Adds a new field to the feature class for each entry in the "fields" variable, except for ObjectID and GlobalID.

for field in fields:
    if field["type"] == "esriFieldTypeOID" or field["type"] == "esriFieldTypeGlobalID":
        pass
    else:
        arcpy.AddField_management(in_table=fc, 
                                  field_name=field["name"],
                                  field_type=field_types[field["type"]],
                                  field_alias=field["alias"],
                                  field_is_nullable=field["nullable"],
                                  field_length=field["length"])
JoeBryant1
Occasional Contributor III

Hi Joshua, thanks for posting this. I'm going to make this code into a python script tool for myself.

I do get a KeyError when trying to run this code in the Python 3 module in ArcGIS Pro (2.5):

Traceback (most recent call last):
   File "<string>", line 18, in <module>
KeyError: 'fields'

Is this because the requests.get method is not passing the json format to 'r'? 

This is a secured service that requires login credentials to access. The first time I ran the code I used the service url with my current token as a url parameter, but this failed because of the bad syntax of appending your additional "?f=json" parameter. After I removed the token from the address, this error went away and I only received the KeyError above.

I'm not sure if Python reads and passes your credentials from ArcGIS Pro automatically when you attempt to access secured services. How should I handle passing the correct permissions to access the feature service? Add a username and password variable? I have tried setting both my Enterprise Portal (where I'll be creating the copy) and the client's ArcGIS site (using our fieldworker account) as the active portal in Pro, and it made no difference. 

0 Kudos
JoeBryant1
Occasional Contributor III

I had limited success writing a script to retrieve a token using user input credentials. I'm sure I'm close, but gave up and manually copied the active token for now.

I altered your script to add a token variable and formatted r as:

r = requests.get(featureLayerURL + "?f=json&token=" + token)

This was able to retrieve and create the feature service field names and types, but did not grab the domain values. I'll have to revisit this script later when I have more time. For now, I will be reverting to copying and pasting the field names and domains to a spreadsheet.

0 Kudos