Informazioni sugli schemi dei messaggi

Il registro degli schemi, una funzionalità del registro dei dispositivi di Azure, è un repository sincronizzato nel cloud e ai margini. Archivia le definizioni dei messaggi provenienti dagli asset perimetrali ed espone un'API per accedere a tali schemi al perimetro.

I flussi di dati usano schemi in tre posizioni:

  • Origine: specificare facoltativamente uno schema per descrivere i messaggi in arrivo. L'esperienza operativa lo usa per visualizzare i campi disponibili.
  • Trasformazione: l'esperienza operativa usa lo schema di origine come punto di partenza quando si compilano trasformazioni.
  • Destinazione: specificare uno schema di output e un formato di serializzazione quando si inviano dati agli endpoint di archiviazione.

Annotazioni

Per i grafici di flusso di dati, configura gli schemi in modo diverso. Vedi Configura gli schemi sulle connessioni dei nodi.

Formati dello schema

Il Registro di sistema dello schema supporta due formati:

Formato Valore della proprietà $schema Usato per
JSON http://json-schema.org/draft-07/schema# Endpoint di origine (MQTT, Kafka)
Delta Delta/1.0 Endpoint di destinazione (archiviazione: ADLS, Fabric, ADX, local)

Entrambi i formati richiedono type: "object" e un properties campo che definisce la struttura dei messaggi.

Esempio di schema JSON

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "temperature": { "type": "number" },
    "humidity": { "type": "number" },
    "deviceId": { "type": "string" },
    "timestamp": { "type": "string" }
  }
}

Esempio di schema Delta

{
  "$schema": "Delta/1.0",
  "type": "object",
  "properties": {
    "type": "struct",
    "fields": [
      { "name": "asset_id", "type": "string", "nullable": true, "metadata": {} },
      { "name": "temperature", "type": "double", "nullable": true, "metadata": {} },
      { "name": "timestamp", "type": "string", "nullable": true, "metadata": {} }
    ]
  }
}

In questo esempio ogni campo viene contrassegnato come nullable: true. Contrassegnare un campo come nullable: false solo quando il mapping produce sempre un valore per esso. Con Parquet e Delta, se un campo è nullable: false ma non è presente in un record, l'intero batch ha esito negativo e viene eliminato. Per altre informazioni, vedere Comportamento di serializzazione dell'archiviazione.

Generare uno schema

Per generare uno schema da un file di dati di esempio, usare l'helper di generazione dello schema.

Per un'esercitazione che usa il generatore di schemi, vedere Esercitazione: Inviare dati da un server OPC UA ad Azure Data Lake Storage Gen 2.

Configurare uno schema di origine

Ogni origine del flusso di dati può facoltativamente specificare uno schema messaggi. Attualmente, i flussi di dati non eseguono la convalida del payload di runtime sugli schemi di origine. L'esperienza operativa usa lo schema per visualizzare i campi disponibili durante la compilazione delle trasformazioni.

Due comportamenti correlati sono facili da perdere:

  • Il riferimento a uno schema nel messaggio può controllare il record. Se un messaggio di origine contiene un riferimento allo schema (la proprietà MQTT dataschema ) e si configura l'origine con le informazioni sullo schema, il flusso di dati confronta i due. Quando sono in conflitto, il messaggio viene confermato ed eliminato senza generare alcun output, e il runtime registra conflicting schema. Questo controllo è separato dalla convalida del payload: il contenuto del messaggio non viene convalidato rispetto allo schema, ma un riferimento non corrispondente arresta ancora il record.
  • Gli schemi JSON configurati non sono validator di runtime. Per l'output JSON, uno schema configurato non viene applicato durante la serializzazione. Il flusso di dati serializza direttamente la struttura del valore in fase di esecuzione insieme ai tipi dedotti. Usare schemi JSON come documentazione in fase di progettazione, non come garanzia che l'output sia conforme allo schema.

Le fonti degli asset hanno uno schema predefinito creato dal connettore per OPC UA. Per le origini del broker di messaggi, è possibile caricare uno schema JSON nell'esperienza operativa o farvi riferimento nella configurazione.

Screenshot che mostra il caricamento di uno schema di messaggio nell'interfaccia utente Web dell'esperienza operativa.

Per fare riferimento a uno schema nella configurazione dell'origine del flusso di dati, usare il schemaRef campo . Per altre informazioni, vedere Configurare un'origine del flusso di dati.

Configurare uno schema di output

Gli schemi di output controllano la modalità di serializzazione dei dati prima che raggiungano la destinazione. Gli endpoint di archiviazione (ADLS Gen2, Fabric OneLake, Esplora dati di Azure, archiviazione locale) richiedono uno schema e supportano i formati di serializzazione Parquet e Delta. Per impostazione predefinita, le destinazioni MQTT e Kafka usano JSON.

Nell'esperienza operativa, quando si seleziona una destinazione di archiviazione, l'interfaccia utente applica tutte le trasformazioni allo schema di origine e genera automaticamente uno schema Delta. Lo schema generato viene memorizzato nel registro degli schemi ed è referenziato nel flusso di dati.

Per le distribuzioni Bicep o Kubernetes, specificare lo schema e il formato di serializzazione nelle impostazioni di trasformazione. Per altre informazioni, vedere Configurare una destinazione del flusso di dati.

Comportamento di serializzazione dell'archiviazione

Quando un flusso di dati scrive in un endpoint di archiviazione (ADLS Gen2, Fabric OneLake, Esplora dati di Azure o archiviazione locale) usando la serializzazione Parquet o Delta, lo schema di output controlla la modalità di scrittura dei record. I comportamenti seguenti possono causare l'eliminazione o la scrittura dei record con valori imprevisti. Esaminarli prima di progettare uno schema o un mapping.

I campi che non ammettono valori Null possono eliminare un intero batch. In fase di scrittura, il codificatore controlla ogni campo nello schema di output. Se un campo è nullable: false e un record non ha un valore per esso (perché il campo non è stato mappato, è stato digitato correttamente o manca dall'origine), il commit ha esito negativo e il flusso di dati elimina l'intero batch in sospeso, non solo quello. Il runtime registra un errore simile a ParquetEncoding found missing property that is not Nullable: <field> quello seguito da failed to commit record into a batch, dropping it. Il flusso di dati continua a funzionare, quindi la perdita passa inosservata a meno che non si controllino i log. Per evitare questo problema, contrassegna un campo nullable: false solo quando la mappatura produce sempre un valore per esso. In caso contrario, usare nullable: true. Un valore null esplicito mappato in un campo nullable: false ha parimenti esito negativo, con l'errore Cannot set null value. Reason: field '<field>' is not nullable.

Eseguire il mapping a ciascun campo foglia, non a un oggetto intero. Per Parquet e Delta, è possibile impostare un valore solo in un campo foglia dichiarato nello schema. Il mapping di un'intera struttura o di un intero oggetto a un percorso padre non scrive i valori annidati ed elimina il record con un errore simile a ParquetEncoding could not set a field <path>, it does not exist by the schema. Eseguire il mapping di ogni foglia di output dichiarata dallo schema.

L'uso dei caratteri jolly richiede che lo schema dichiari ciascun campo in modo espanso. Un mapping * -> * (o qualsiasi carattere jolly, inclusi i criteri di appiattimento e ristrutturazione) si espande fino a ogni foglia nel payload di runtime. Per Parquet e Delta, lo schema di output deve dichiarare ognuna di queste foglie. Se il payload contiene una foglia che lo schema non dichiara, il record viene eliminato. Generare lo schema dai dati di esempio rappresentativi in modo che includa ogni campo prodotto dal flusso di dati.

Uno schema da solo non popola i valori. Uno schema descrive la forma di output, ma non sposta i dati. Senza un mapping, il flusso di dati scrive i record di tutti i valori Null (per i campi nullable) o li elimina (per i campi non nullable). Per popolare i valori, aggiungere un mapping, in genere * -> *e assicurarsi che i campi siano nullable: true quando un valore potrebbe essere assente.

Le conversioni numeriche sono invisibile all'utente e possono perdere precisione. Quando il tipo di un valore mappato non corrisponde al tipo di colonna dello schema, Parquet e Delta lo convertono automaticamente senza generare errori. Le conversioni da float a integer troncano la parte frazionaria e le conversioni di limitazione possono perdere precisione o wrapping. Se è necessario arrotondare, arrotondare in modo esplicito nella mappatura. Per le funzioni disponibili, vedere Funzioni di ridimensionamento e arrotondamento.

Mancante e nullo non sono la stessa cosa. Un campo assente da un record (mancante) viene ignorato durante la serializzazione, mentre un campo impostato in modo esplicito su null viene scritto quando il formato lo consente. Per Parquet e Delta, un valore mancante in un nullable: true campo viene scritto come Null, un valore mancante in un nullable: false campo elimina il batch e anche un valore Null esplicito in un nullable: false campo ha esito negativo. Progettare i mapping e la gestione dei valori Null tenendo conto di questa differenza.

I tipi complessi vengono convertiti in modo diverso in base a ogni formato. Gli oggetti, le mappe, i valori di byte e le matrici non serializzano nello stesso modo nei formati:

  • Mappe (oggetti con chiavi non stringa): Parquet e Delta rifiutano le mappe con l'errore Currently maps are not supported. JSON supporta le mappe solo quando le chiavi sono stringhe. Avro converte le chiavi di mapping in stringhe e, se due chiavi si scontrano dopo la conversione, l'ultimo valore vince.
  • Valori di byte: JSON codifica i byte come stringa base64. Parquet e Delta possono scrivere byte come binario, una stringa base64 o un elenco, a seconda del tipo di colonna dello schema.
  • Matrici: Parquet e Delta scrivono matrici come elenco o come binario, a seconda del tipo di colonna. Se la lunghezza della matrice non corrisponde, una colonna binaria a dimensione fissa ha esito negativo.

Se è necessaria una forma prevedibile per un valore complesso, eseguire il mapping esplicito dei singoli campi foglia anziché basarsi sul pass-through dell'intero oggetto.

Caricare uno schema

È possibile caricare schemi tramite l'interfaccia utente dell'esperienza operativa, l'interfaccia della riga di comando di Azure o una distribuzione Bicep.

Caricare con l'interfaccia della riga di comando di Azure

Usare il gruppo di comandi az iot ops schema per creare e gestire gli schemi.

Creare uno schema da un file:

az iot ops schema create -n myschema -g myresourcegroup --registry myregistry --format json --type message --version-content myschema.json

Creare uno schema dal contenuto inline con una versione specifica:

az iot ops schema create -n myschema -g myresourcegroup --registry myregistry --format delta --type message --version-content '{"hello": "world"}' --ver 14

Suggerimento

Se non si conosce il nome del Registro di sistema, usare il schema registry list comando :

az iot ops schema registry list -g myresourcegroup --query "[].{Name:name}" -o tsv

Al termine del comando, un blob appare nel contenitore del tuo account di archiviazione con il contenuto dello schema. Il nome del BLOB segue il formato schema-namespace/schema/version.

Caricare con Bicep

Definire il contenuto dello schema come variabile e creare la risorsa dello schema:

param schemaRegistryName string = '<SCHEMA_REGISTRY_NAME>'
param schemaName string = 'sensor-data-delta'
param schemaVersion string = '1'

var schemaContent = '''
{
  "$schema": "Delta/1.0",
  "type": "object",
  "properties": {
    "type": "struct",
    "fields": [
      { "name": "temperature", "type": "double", "nullable": true, "metadata": {} },
      { "name": "humidity", "type": "double", "nullable": true, "metadata": {} },
      { "name": "deviceId", "type": "string", "nullable": true, "metadata": {} }
    ]
  }
}
'''

resource schemaRegistry 'Microsoft.DeviceRegistry/schemaRegistries@2026-04-01' existing = {
  name: schemaRegistryName
}

resource schema 'Microsoft.DeviceRegistry/schemaRegistries/schemas@2026-04-01' = {
  parent: schemaRegistry
  name: schemaName
  properties: {
    displayName: 'Sensor Data Delta Schema'
    description: 'Delta schema for sensor telemetry'
    format: 'Delta/1.0'
    schemaType: 'MessageSchema'
  }
}

resource version 'Microsoft.DeviceRegistry/schemaRegistries/schemas/schemaVersions@2026-04-01' = {
  parent: schema
  name: schemaVersion
  properties: {
    description: 'Initial version'
    schemaContent: schemaContent
  }
}

Distribuire il file Bicep. Imposta la RESOURCE_GROUP variabile ambiente al nome del tuo gruppo di risorse, e poi esegui:

az deployment group create --resource-group $RESOURCE_GROUP --template-file schema.bicep