Scenario: Add JSON Schema Validation to a Digital Twin Model

Use a custom Oracle DTDL validation extension to apply JSON schema data validation rules to device payloads in your digital twin model.

Include dtmi:com:oracle:dtdl:extension:validation;1 in the @context of your digital twin model and add the Validated co-type to the content that needs validation. Use the supported validation properties to constrain incoming values. The examples below include numeric, string, array, and Object-field validation.

For a complete list of supported validation properties rules, see DTMI Validation Extension Reference.

Before you begin

Make sure you have the required permissions and your OCI CLI is configured. For more information, see Prerequisites, Policy Details for the Internet of Things (IoT) Platform, and Using a JSON File for Complex Input.

Understand the code snippets in this scenario

The code snippets below are examples from a digital twin model that's based on DTDL v3 and demonstrates how to use the custom Oracle validation extension.

Step 1: Define the Validation Extension in the @context of the Digital Twin Model

The required digital twin model context indicating the digital twin model uses DTDL specifications v3: dtmi:dtdl:context;3

To define the validation extension, when you create digital twin model or update a digital twin model append the validation extension to the DTMI URI value in the @context. The digital twin model reads these validation blocks to enforce validation rules to incoming device data. Any data that fails a validation rule is rejected. The normalized and rejected data is in the IoT database schema.

{
  "@context": [
    "dtmi:dtdl:context;3",
    "dtmi:com:oracle:dtdl:extension:validation;1"
  ],
  ...
  }

Step 2: Add a validation Property to Elements in a Digital Twin Model

In digital twin models, use JSON Schema Validation Specifications to add validation properties to the validate ingested data.
  • For primitive properties such as strings or integers, validation constraints are added as sibling properties next to the schema field within the property or telemetry definition.
  • For arrays, validations applies to the array itself such as minItems or uniqueItems and defined as siblings of the array schema, while constraints that apply to each element such as value ranges or string patterns are placed inside the array schema, as sibling properties to elementSchema.

Use the following code snippets as examples for your digital twin models. For a complete list of supported validation properties and rules, see DTMI Validation Extension Reference.

Digital Twin Model Example: Optional Sensor Health Field

A sensor might report its status before its first successful reading. In this model, lastSuccessTime can be omitted until a reading succeeds. The health Object still requires errorCount, stale, and state.

{
  "@context": [
    "dtmi:dtdl:context;3",
    "dtmi:com:oracle:dtdl:extension:validation;1"
  ],
  "@id": "dtmi:com:example:SensorHealth;1",
  "@type": "Interface",
  "displayName": "Sensor Health",
  "contents": [
    {
      "@type": ["Telemetry", "Validated"],
      "name": "health",
      "schema": {
        "@type": "Object",
        "fields": [
          { "name": "errorCount", "schema": "integer" },
          { "name": "lastSuccessTime", "schema": "dateTime" },
          { "name": "stale", "schema": "boolean" },
          { "name": "state", "schema": "string" }
        ],
        "required": ["errorCount", "stale", "state"]
      }
    }
  ]
}

The following health value omits the optional field and meets the Object's field requirements. Map your device payload to this content using your digital twin adapter.

{
  "errorCount": 0,
  "stale": true,
  "state": "initializing"
}

After a successful reading, the value can include lastSuccessTime:

{
  "errorCount": 0,
  "lastSuccessTime": "2026-09-24T12:00:00Z",
  "stale": false,
  "state": "ready"
}

Omitting state fails the requirement because it is listed in required. Sending "lastSuccessTime": null is not a substitute for omitting that field. If you remove the required property from the Object schema, all four declared fields are required again.

This avoids inventing a successful-reading timestamp while keeping the other health information mandatory. For the rules, see Required and Optional Object Fields.

Digital Twin Model Snippet: Optional Nested Object

Use this schema for content that has the Validated co-type in a model with the validation extension. The outer Object requires status but allows location to be omitted. If location is present, its own list requires site and building; room remains optional.

{
  "@type": "Object",
  "fields": [
    { "name": "status", "schema": "string" },
    {
      "name": "location",
      "schema": {
        "@type": "Object",
        "fields": [
          { "name": "site", "schema": "string" },
          { "name": "building", "schema": "string" },
          { "name": "room", "schema": "string" }
        ],
        "required": ["site", "building"]
      }
    }
  ],
  "required": ["status"]
}

A value can omit the entire nested Object:

{"status": "ready"}

Or it can supply the nested Object without its optional room:

{
  "status": "ready",
  "location": { "site": "example-campus", "building": "A" }
}

A supplied location without building fails its nested requirement. Listing a field in the outer Object does not control the fields inside the nested Object. Objects in Array elements and Map values follow this same independent validation rule.

Digital Twin Model Snippet: Telemetry with Number Validation

This code snippet from a digital twin model shows how to valid pressures from a sensor between 950.0 and 1050.0 inclusive, and must be a multiple of 0.1.

{
  "@context": [
    "dtmi:dtdl:context;3",
    "dtmi:com:oracle:dtdl:extension:validation;1"
  ],
  "@id": "dtmi:com:example:Sensor;1",
  "@type": "Interface",
  "displayName": "Example Sensor",
  "contents": [
    {
      "@type": ["Telemetry", "Validated"],
      "name": "pressure",
      "schema": "double",
      "displayName": "Pressure",
      "minimum": 950.0,
      "maximum": 1050.0,
      "multipleOf": 0.1
    }
  ]
  }

Digital Twin Model Snippet: String Pattern Validation

This example validates the serial number follows a specific string pattern. In this example, the string pattern is a regular expression that incoming serial number values must match. The serial number value must start with "SN-", followed by 4 to 8 uppercase letters (A-Z) or digits (0-9) and nothing else is allowed before or after:

"pattern": "^SN-[A-Z0-9]{4,8}$"
{
  "@type": ["Property", "Validated"],
  "name": "serialNumber",
  "schema": "string",
  "pattern": "^SN-[A-Z0-9]{4,8}$"
  }

Digital Twin Model Snippet: Array Validation with Element Constraints

Validates the alarm codes must be an array of integers is between 100 and 900. The array must have at least 1, no more than 5 items, and all items must be unique.
{
  "@type": ["Property", "Validated"],
  "name": "alarmCodes",
  "schema": {
    "@type": "Array",
    "elementSchema": "integer",
      "minimum": 100,
      "maximum": 900
  },
  "minItems": 1,
  "maxItems": 5,
  "uniqueItems": true
}

Digital Twin Model Snippet: Double-Precision Telemetry with Explicit Validation

This example validates the value must be a double whole number and must be inclusive between -50.0 and 150.0.
{
  "@type": ["Telemetry", "Validated"],
  "name": "temperature_double",
  "schema": "double",
  "minimum": -50.0,
  "maximum": 150.0
}

Digital Twin Model Snippet: Single-Precision Telemetry with Explicit Validation

This example validates the value must be a float, and the value must be in the specified range between -50.0 and 150.0.
{
  "@type": ["Telemetry", "Validated"],
  "name": "temperature_float",
  "schema": "float",
  "minimum": -50.0,
  "maximum": 150.0
}

Digital Twin Model Snippet: Telemetry with Type, Range, and Step Validation

This example validates the value is a double, a whole number and between 0 and 360 degrees and in increments of 0.1.

{
  "@type": ["Telemetry", "Validated"],
  "name": "angle",
  "schema": "double",
  "minimum": 0.0,
  "maximum": 360.0,
  "multipleOf": 0.1
}