Create custom field type picklist via tooling rest api – which meta information required

custom-fieldpicklistpythonsimple-salesforcetooling

I want to create a new custom field on a custom object on SalesForce.

The custom field type shall be of type 'picklist' (non-global) with a predefined set of values.

I want to use the Salesforce tooling REST API, calling from python via simple-salesforce package.

I can already create a field of type 'Text' successfully – however I'm failing to create a 'picklist'-type field with some initial picklist values. Does anyone know which exact meta information is required to create a picklist field?

Details:

I am using simple-salesforce package to connect to my Salesforce instance

import simple_salesforce

sf = simple_salesforce.Salesforce(
  'username': '[email protected]',
  'password': 'mypersonalpassword',
  'security_token': 'mysecuritytoken',
  'domain': 'test'  # I am running on a sandbox
)

The following REST API call can be used to create custom fields

url = 'tooling/sobjects/CustomField/'
object_api_name = 'MyCustomObject__c'
field_api_name = 'MyNewCustomField__c'

d_meta = {...to be defined...}  # see below

d_payload = {
    'FullName':'%s.%s' % (object_api_name, field_api_name),
    'Metadata':d_meta,
}
  
result = sf.restful(url, method='POST', json=d_payload)

I successfully created a new custom field of type 'Text' on my custom object using the following meta data

# WORKING: Meta input for custom field type 'Text'
d_meta = {
  'type': 'Text',
  'inlineHelpText': 'inline HelpText',
  'label': 'Text Field Test',
  'length': 255,
  'required': True
}

For a custom field of type 'picklist' however I simply cannot figure out which input values are required to define the picklist values. From analyzing the meta data of an existing picklist field, I found the meta info 'picklistValues' present with a list of dictionaries of picklist values with following information.

# NOT WORKING: Meta input for custom field type 'picklist' and 'picklistValues' metaData
d_meta = {
    'type': 'picklist',
    'label': 'PicklistFieldTest',
    'picklistValues':  [
        {
            'defaultValue': False,
            'active': True,
            'label': 'TestValue1',
            'value': 'TestValue1'
        },{
            'defaultValue': False,
            'active': True,
            'label': 'TestValue2',
            'value': 'TestValue2'
        }
    ]
}

This however gives me the error

SalesforceMalformedRequest:
Malformed request https://mysforg.my.salesforce.com/services/data/v42.0/tooling/sobjects/CustomField/.
Response content: [{
'message': 'Cannot deserialize instance of complexvalue from VALUE_STRING value picklist or request may be missing a required field at [line:1, column:15]',
'errorCode': 'JSON_PARSER_ERROR'
}]

Alternative using another synatx I found online using meta information on 'valueSet' doesn't succeed either

# NOT WORKING: Meta input for custom field type 'picklist' and 'valueSet' metaData
d_meta = {
    'type': 'picklist',
    'label': 'PicklistFieldTest',
    'valueSet': {
        'valueSetDefinition': {        
            'value': [
                {
                    'default': False,
                    'isActive': True,
                    'label': 'TestValue1',
                    'valueName': 'TestValue1'
                },{
                    'default': False,
                    'isActive': True,
                    'label': 'TestValue2',
                    'valueName': 'TestValue2'
                }
            ],
            'sorted': True
        }
    }    
}

Any clou which meta data information is required to create picklist field?

Best Answer

After searching and testing two days, finally posting here and searching on I now found the working solution.

So the following code connects to Salesforce Org and adds a new custom field MyNewCustomField__c to an existing custom object MyCustomObject__c as type Picklist with name/label MyNewCustomField with two picklist entries with values TestLabel<i> and API name TestFullName<i>.

import simple_salesforce

# connect to Salesforce
sf = simple_salesforce.Salesforce(
  'username': '[email protected]',
  'password': 'mypersonalpassword',
  'security_token': 'mysecuritytoken',
  'domain': 'test'  # I am running on a sandbox
)

# ingestion setup
url = 'tooling/sobjects/CustomField/'
object_api_name = 'MyCustomObject__c'
field_api_name = 'MyNewCustomField__c'

# meta data for MyNewCustomField
d_meta = {
    'label': 'MyNewCustomField',
    'required': True,
    'type': 'Picklist',
    'inlineHelpText': 'Inline Helptext',  
    'valueSet': {
        'restricted': True,
        'valueSetDefinition': {
            'sorted': False,

            # picklist entries
            'value': [        
                {
                    'fullName': 'TestFullName1',
                    'default': True,
                    'label': 'TestLabel1'
                },{
                    'fullName': 'TestFullName2',
                    'default': False,
                    'label': 'TestLabel2'
                }
            ]
        }
    }
}

# build payload
d_payload = {
    'FullName':'%s.%s' % (object_api_name, field_api_name),
    'Metadata':d_meta,
}

# execute POST request
result = sf.restful(url, method='POST', json=d_payload)
Related Topic