Configure config.json for DMO-to-DMO Transforms

For data model object (DMO)-to-DMO transforms (transforms that read from and write to DMOs), don't use the sf data-code-extension script scan command because you must pass the DMO schema. Instead, follow the schema standards to configure the config.json file manually.

Schema Structure Overview

This schema example demonstrates the structure of a config.json file for DMO-to-DMO transforms:

{
  "entryPoint": "entry_point.py", // Root-level: Entry point file
  "dataspace": "default", // Root-level: Dataspace name
  "permissions": {
    // Root-level: Permissions object
    "read": {
      // Permissions: Read permissions
      "dmo": ["SourceAccount__dlm"] // Permissions: Input DMO array
    },
    "write": {
      // Permissions: Write permissions
      "dmo": ["EnrichedAccount__dlm"] // Permissions: Output DMO array
    }
  },
  "dataObjects": [
    // Root-level: Data objects array
    {
      // dataObjects: Object definition
      "name": "EnrichedAccount__dlm", // Object: DMO name (required)
      "label": "Enriched Account", // Object: Human-readable label (optional)
      "type": "dataModelObject", // Object: Object type (optional)
      "category": "profile", // Object: Category (required)
      "fields": [
        // Object: Fields array (required)
        {
          // Field: Field definition
          "name": "Id__c", // Field: Field name (required)
          "label": "Account ID", // Field: Human-readable label (optional)
          "dataType": "text", // Field: Data type (required)
          "isPrimaryKey": true, // Field: Primary key flag (required)
          "keyQualifierFieldName": "Name__c" // Field: Key qualifier (optional)
        }
      ]
    }
  ]
}

Root-Level Properties

Your config.json file must include these root-level properties.

Property Required Description
entryPoint Yes The main script file that is executed when your code extension runs.
dataspace Yes The data space that contains the DMOs to read from and write to (typically "default").
permissions Yes Read and write permissions for data objects.
dataObjects Yes Schema definitions for each DMO your script writes to.

Permissions Schema

The permissions object defines which DMOs your script reads from and writes to. It must follow this schema structure.

"permissions": {
  "read": {
    "dmo": ["SourceDMO__dlm"]
  },
  "write": {
    "dmo": ["TargetDMO__dlm"]
  }
}

Schema Requirements:

  • Include both read and write permissions.
  • Use dmo for DMOs.
  • Use different object names for read and write operations.
  • Every DMO in the write list must have a corresponding schema definition in dataObjects. You don't have to define schemas for DMOs in the read list.

dataObjects Schema

The dataObjects array contains schema definitions for each output DMO that your script writes to. Each object in the array defines the complete structure of a DMO, including its fields, data types, and primary keys.

Object-Level Schema

Each object in the dataObjects array represents one DMO and must include these properties.

Property Required Type Description
name Yes String DMO name. Must match a name in permissions.write.dmo.
category Yes String Set to "profile", "engagement", or "other" (case-insensitive).
fields Yes Array Array of field definitions. Include at least one field.
timeEventField Conditional String Required when category is "engagement". Name of a dateTime field defined in fields that holds the event time.
label No String Human-readable label.
type No String The object type for the schema entry. Set to "dataModelObject" for DMOs.
description No String Description of the DMO.
Supported DMO Categories

You can write to DMOs in any of these categories.

  • profile - Profile data, such as accounts or contacts.
  • engagement - Time-series engagement data, such as events or interactions. An engagement DMO must include a timeEventField at the object level that names a dateTime field in fields.
  • other - Data that doesn't fit the profile or engagement categories.

For an engagement DMO, supply the timeEventField property at the object level and define the referenced field as a dateTime field in the fields array.

{
  "name": "testing_engagement__dlm",
  "label": "Testing Engagement",
  "type": "dataModelObject",
  "category": "engagement",
  "timeEventField": "EventTime__c",
  "fields": [
    {
      "name": "Id__c",
      "label": "Account Id",
      "dataType": "text",
      "isPrimaryKey": true,
      "keyQualifierFieldName": "KQ_Id1__c"
    },
    {
      "name": "KQ_Id1__c",
      "label": "Key Qualifier Account Id",
      "dataType": "text",
      "isPrimaryKey": false,
      "keyQualifierFieldName": null
    },
    {
      "name": "Description__c",
      "label": "Account Description",
      "dataType": "text",
      "isPrimaryKey": false,
      "keyQualifierFieldName": null
    },
    {
      "name": "EventTime__c",
      "label": "Event Time",
      "dataType": "dateTime",
      "isPrimaryKey": false,
      "keyQualifierFieldName": null
    }
  ]
}

Field-Level Schema

Each field in the fields array defines a property of the DMO. Each field must include these properties.

Property Required Type Description
name Yes String Field name. Can't be blank.
dataType Yes String Data type. Can't be blank.
isPrimaryKey Yes Boolean Whether this field is a primary key
label No String Human-readable label
keyQualifierFieldName No String Name of the key qualifier field

Supported Data Types

Use these data type values in the dataType property for your DMO fields.

  • text - Text or string values
  • email - Email addresses
  • dateTime - Date and time values
  • number - Numeric values
  • boolean - True or false values

Primary Keys and Key Qualifiers

When defining primary keys for your DMO, use keyQualifierFieldName to reference another field that provides more context for the primary key.

{
  "name": "Id__c",
  "dataType": "text",
  "isPrimaryKey": true,
  "keyQualifierFieldName": "Name__c"
},
{
  "name": "Name__c",
  "dataType": "text",
  "isPrimaryKey": false,
  "keyQualifierFieldName": null
}

Multiple DMOs

If your script writes to multiple DMOs, define a schema for each one in the dataObjects array. Each DMO must have its own object definition with a complete field schema.

{
  "permissions": {
    "write": {
      "dmo": ["Accounts__dlm", "Contacts__dlm"]
    }
  },
  "dataObjects": [
    {
      "name": "Accounts__dlm",
      "category": "profile",
      "fields": [
        /* ... */
      ]
    },
    {
      "name": "Contacts__dlm",
      "category": "profile",
      "fields": [
        /* ... */
      ]
    }
  ]
}

config.json Example

This example shows a complete config.json file that follows all the required schema standards for a DMO-to-DMO transform.

{
  "entryPoint": "entry_point.py",
  "dataspace": "default",
  "permissions": {
    "read": {
      "dmo": ["SourceAccount__dlm"]
    },
    "write": {
      "dmo": ["EnrichedAccount__dlm"]
    }
  },
  "dataObjects": [
    {
      "name": "EnrichedAccount__dlm",
      "label": "Enriched Account",
      "type": "dataModelObject",
      "category": "profile",
      "fields": [
        {
          "name": "Id__c",
          "label": "Account ID",
          "dataType": "text",
          "isPrimaryKey": true,
          "keyQualifierFieldName": "Name__c"
        },
        {
          "name": "Name__c",
          "label": "Account Name",
          "dataType": "text",
          "isPrimaryKey": false,
          "keyQualifierFieldName": null
        },
        {
          "name": "Email__c",
          "label": "Email",
          "dataType": "email",
          "isPrimaryKey": false,
          "keyQualifierFieldName": null
        },
        {
          "name": "LastModified__c",
          "label": "Last Modified Date",
          "dataType": "dateTime",
          "isPrimaryKey": false,
          "keyQualifierFieldName": null
        }
      ]
    }
  ]
}

Schema Validation Requirements

Your config.json file must meet these validation requirements.

Configuration Level

  • Read and write permissions must not be empty.
  • Dataspace must not be blank.
  • Don't read and write the same object.

Schema Level

  • dataObjects must be present and not empty.
  • Every DMO in permissions.write.dmo must have a matching schema in dataObjects.
  • Each object's name must not be blank.
  • Each object's category must be "profile", "engagement", or "other".
  • Each object with the "engagement" category must include a timeEventField that names a dateTime field defined in fields.
  • Each object must have at least one field.

Field Level

  • Each field's name must not be blank.
  • Each field's dataType must not be blank.
  • isPrimaryKey must be specified for each field.

Troubleshoot Common Errors

These errors occur during package validation when your config.json doesn't follow the required schema standards.

Error Message Solution
No DMO schema found Add dataObjects array with schemas for all write DMOs
Some DMO write targets do not have a schema Ensure all DMO names in write.dmo have matching entries in dataObjects
Invalid DMO Schema: name missing Add name property to data object
Invalid DMO Schema: invalid object category Set category to "profile", "engagement", or "other"
Invalid DMO fields schema Ensure all fields have name and dataType
Can't read and write from/to the same entity Use different DMO names for read vs write

note: Currently, all these validation errors surface to the Connect API as error code 2999 ("Unknown error occurred"). The preceding error messages are available in the logs for debugging.

Best Practices

  1. Start with write targets: List all DMOs you write to in permissions.write.dmo.
  2. Create matching schemas: Make sure that each DMO has a corresponding entry in dataObjects with the same name.
  3. Define all output fields: Include all fields that your script writes.
  4. Set primary keys correctly: Identify primary keys and mark them with isPrimaryKey: true.
  5. Match your script output: Ensure field names match what your Python script produces.
  6. Use descriptive labels: While optional, labels improve readability and debugging.