[SalesForce] How to query the ‘Metadata’ field from ‘FieldDefinition’ with SOQL

I tried the following SOQL query:

select id, DataType,NamespacePrefix, DeveloperName, Metadata from FieldDefinition where EntityDefinition.QualifiedApiName = 'Account' AND DurableId ='Account.Industry'

I received this error:

INVALID_FIELD:

NamespacePrefix, DeveloperName, Metadata from FieldDefinition where
ERROR at Row:1:Column:53
No such column 'Metadata' on entity 'FieldDefinition'.

Why? According to the documentation the field 'Metadata' is available if the query result contains no more than one record – which is the case here.

How can I access this field?

Best Answer

Tooling API Documentation refers only to Tooling API queries.

This is not obvious that Metadata is available only for Tooling API Calls.

This is not obvious but actually FieldDefinition and ObjectDefinition standard objects are available by usual SOQL queries from usual Apex code.

Except for Metadata field, which is only available for Tooling API Calls.

There was once in the past list of all Salesforce Standard Objects in salesforce documentation, now it is gone. There is only list of Standard Objects available in SOAP API but this is not what we are looking for.

So, let's document ourselves the current behavior.

If we run a query select id, DataType,NamespacePrefix, DeveloperName from FieldDefinition where EntityDefinition.QualifiedApiName = 'Account' AND DurableId ='Account.Industry' in Developer Console Query Editor even without having checked Tooling API checkbox or if we run this query in Apex Code we will receive results without error. enter image description here

If we run a query select id, DataType,NamespacePrefix, DeveloperName, Metadata from FieldDefinition where EntityDefinition.QualifiedApiName = 'Account' AND DurableId ='Account.Industry' in Developer Console Query Editor without having checked Tooling API checkbox or if we run this query in Apex Code we will obtain an error enter image description here Please notice that Tooling API checkbox is unchecked.

If we run a query select id, DataType,NamespacePrefix, DeveloperName, Metadata from FieldDefinition where EntityDefinition.QualifiedApiName = 'Account' AND DurableId ='Account.Industry' in Developer Console Query Editor having checked Tooling API checkbox or if we run this query through callout to Tooling API we will receive results without error. enter image description here Which proves my statements above that:

  1. Standard objects FieldDefinition and ObjectDefinition are available by usual SOQL queries from usual Apex code except for Metadata field.

  2. Field Metadata on FieldDefinition is available only by Tooling API calls.

However in my humble opinion this is useless to run this query in Developer console query editor since Developer Console will not show us any data but only [Object object] string which is not really helpful.

So to get that information in Apex you really need to make self-callout.

Before doing that you need to go to Remote Site Settings by link https://login.salesforce.com/0rp/e?SiteName=self&EndpointUrl=https://yourinstance.salesforce.com/ on production or Developer Edition instance or https://test.salesforce.com/0rp/e?SiteName=self&EndpointUrl=https://yourinstance.salesforce.com/ on any of sandbox instance and input your data and click save like this is done on this screenshot enter image description here

Then you can run the following code to get the field metadata

static String restGet(String endPoint, String method, String sid) {
    Http h = new Http();
    HttpRequest hr = new HttpRequest();
    hr.setHeader('Authorization', 'Bearer ' + sid);
    hr.setTimeout(60000);   
    hr.setEndpoint(endPoint);   
    hr.setMethod(method);
    HttpResponse r = h.send(hr);            
    return r.getBody(); 
}

     String baseURL = URL.getSalesforceBaseUrl().toExternalForm();
     //restGet( baseURL, 'GET', UserInfo.getSessionId() );
     String body = restGet( baseURL + '/services/data/v38.0/tooling/query?q=select+id,+DataType,NamespacePrefix,+DeveloperName,+Metadata+from+FieldDefinition+where+EntityDefinition.QualifiedApiName+=+\'Account\'+AND+DurableId+=\'Account.Industry\'', 'GET', UserInfo.getSessionId() );
     System.debug(LoggingLevel.ERROR, '@@@ v: ' + body );
     String metadata = body.substringBetween('"Metadata":{"', '}}]}');
     System.debug(LoggingLevel.ERROR, '@@@ v: ' + metadata );

However, if you really need metadata you could just run Apex Field Describe methods because this might be more easy than accessing FieldDefinition object Metadata field through callout.