I am currently trying to figure out how to elicit an object relationship tree from Salesforce, so I can export test data to use in my Scratch-Orgs. Basically what I want to do is poll to produce a data structure via Apex or other some other means that defines all related sObjects types for each sObject type, and the respective field(s) used to traverse many-to-one/one-to-many (or both) for each relationship. Any ideas on how best to achieve this?
2 Answers
Your best option migt be the pilot of MetadataComponentDependency REST resource in Tooling API. Read the linked doc and the associated Trailblazer group for more info.
Looked around for bits and pieces and put the following together:
@RestResource(urlMapping='/SchemaApi/*')
global with sharing class ObjectRelApi {
@HttpGet
global static void GetSchemaInfo() {
// Defaulting
Map<String,Map<String,String>> objectRelationships = new Map<String,Map<String,String>>();
Map<String,List<String>> objectFields = new Map<String,List<String>>();
Map<String,Object> finalMap = new Map<String,Object>();
// Collect all objects
Map<String, SObjectType> allSObjectTypes = Schema.getGlobalDescribe();
// Each object type
for (string key : allSObjectTypes.keySet()) {
// Defaulting
Map<String,String> fieldChildMap = new Map<String,String>();
List<String> fieldNames = new List<String>();
// Obtain child schema details
string objectTypeName = allSObjectTypes.get(key).getDescribe().getName();
List<ChildRelationship> childRelationships = allSObjectTypes.get(key).getDescribe().getChildRelationships();
// Each child relationship
for (ChildRelationship thisChildRelationship : childRelationships) {
// Record childhood entry
string accrossFieldName = thisChildRelationship.getField().getDescribe().getName();
string forChildObjectTypeName = thisChildRelationship.getChildSObject().getDescribe().getName();
fieldChildMap.put(accrossFieldName, forChildObjectTypeName);
}
// Append result
objectRelationships.put(objectTypeName, fieldChildMap);
// Object field schema details
Map<String, Schema.SobjectField> fieldMap = allSObjectTypes.get(key).getDescribe().fields.getMap();
// Each field
for (string fieldKey : fieldMap.keySet()) {
// Record field entry
fieldNames.add(fieldKey);
}
// Append result
objectFields.put(objectTypeName, fieldNames);
}
// Add to final map
finalMap.put('FieldSet', objectFields);
finalMap.put('RelationshipSet', objectRelationships);
// Return result
RestContext.response.responseBody = Blob.valueOf(JSON.serializePretty(finalMap));
}
}