Exemples de transformations

Vous pouvez transformer vos données CloudEvents en écrivant des expressions de transformation à l'aide du CEL. Pour en savoir plus, consultez la section Transformer les événements reçus.

Voici quelques cas d'utilisation courants et des exemples qui vous montrent comment écrire des expressions CEL pour transformer vos données d'événement.

Cas d'utilisation standards

Voici quelques cas d'utilisation standards pour la transformation des données d'événement.

Normalisation des données

Vous devez aplatir une structure de données imbriquée dans votre message d'événement pour faciliter le traitement par un service en aval.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "orderId": "12345",
    "customer": {
      "firstName": "Alex",
      "lastName": "Taylor",
      "address": {
        "street": "1800 Amphibious Blvd.",
        "city": "Mountain View"
      }
    }
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  "data": {
    "orderId": "12345",
    "customerFirstName": "Alex",
    "customerLastName": "Taylor",
    "customerStreet": "1800 Amphibious Blvd.",
    "customerCity": "Mountain View"
  }
}
Solution 1 :

Mettez en forme les données de sortie manuellement. Cela vous permet de lister les noms de champ et de ne sélectionner que les éléments nécessaires dans la sortie. Il s'agit d'une approche raisonnable lorsque l'entrée est prévisible et que le nombre de champs est faible. La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée. Exemple :

message.setField("data",
{
  "orderId": message.data.orderId,
  "customerFirstName": message.data.customer.firstName,
  "customerLastName": message.data.customer.lastName,
  "customerStreet": message.data.customer.address.street,
  "customerCity": message.data.customer.address.city,
})
Solution 2 :

Utilisez une fonction dans votre expression. La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée. La fonction denormalize aplatit les structures profondes en une liste de paires clé-valeur. Les noms de champ sont délimités par un point (.) pour segmenter la hiérarchie de la structure. Exemple :

message.setField("data", message.data.denormalize())

Le résultat suivant est légèrement différent de la charge utile attendue. Toutefois, les avantages incluent une expression CEL plus courte qui fonctionne sur n'importe quelle entrée et qui inclut automatiquement un nombre illimité de champs entrants.

{
  "data": {
    "orderId": "12345",
    "customer.firstName": "Alex",
    "customer.lastName": "Taylor",
    "customer.address.street": "1800 Amphibious Blvd.",
    "customer.address.city": "Mountain View"
  }
}

Masquage des données

Vous devez masquer les données sensibles dans la charge utile d'un événement avant qu'il ne soit envoyé à un environnement moins sécurisé.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "userId": "user123",
    "email": "alex@example.com",
    "creditCardNumber": "1234-5678-9012-3456"
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  "data": {
    "userId": "user123",
    "email": "a***@example.com",
    "creditCardNumber": "xxxx-xxxx-xxxx-3456"
  }
}
Solution :

Utilisez une expression pour masquer toute information sensible, telle que l'adresse e-mail et le numéro de carte de crédit. La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée. La fonction d'expression régulière extract suit la syntaxe RE2. Exemple :

message
      .setField("data.email",
          re.extract(message.data.email,
                    "(^.).*@(.*)",
                    "\\1***@\\2"))

      .setField("data.creditCardNumber",
          re.extract(message.data.creditCardNumber,
                    "(\\d{4})\\D*$",
                    "xxxx-xxxx-xxxx-\\1"))

Masquage des données

Vous devez supprimer des champs spécifiques de la charge utile d'un événement en fonction de certaines conditions.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "orderId": "12345",
    "customerType": "gold",
    "discountCode": "VIP"
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  {
  "orderId": "12345",
  "customerType": "gold"
  }
}
Solution :

Utilisez une expression qui masque le champ discountCode si customerType est "gold". La fonction removeFields supprime des champs spécifiques d'un événement. Exemple :

message.data.customerType == "gold" ?
      message.removeFields(["data.discountCode"]) :
      message

Convertir des données

Vous devez convertir des données d'un format ou d'un type à un autre.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "orderDate": "2024-10-31T12:00:00Z",
    "totalAmount": "1500"
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  "data": {
    "orderDate": 1704086400,
    "totalAmount": 1500.00
  }
}
Solution :

Utilisez une expression qui convertit orderDate en code temporel UNIX et le type totalAmount d'un string en double (nombre à virgule flottante). La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée. Vous pouvez utiliser des fonctions de manipulation de chaînes pour convertir les résultats de la chaîne. Exemple :

message
      .setField("data.orderDate", int(timestamp(message.data.orderDate)))
      .setField("data.totalAmount", double(message.data.totalAmount))

Routage conditionnel

Vous devez acheminer les événements vers différentes destinations en fonction des données d'événement.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "eventType": "order.created",
    "orderValue": 200
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  "data": {
    "eventType": "order.created",
    "orderValue": 200,
    "routingKey": "highValue"
  }
}
Solution :

Utilisez une expression qui ajoute un champ routingKey avec une valeur "highValue" si la valeur orderValue est supérieure à 100, sinon "normal". Le champ routingKey peut être utilisé pour déterminer le chemin de routage. La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée. Exemple :

message.data.orderValue > 100 ?
      message.setField("data.routingKey", "highValue") :
      message.setField("data.routingKey", "normal")

Gestion des valeurs par défaut

Vous devez vous assurer que certains champs de la charge utile de l'événement ont des valeurs par défaut s'ils ne sont pas présents.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "itemName": "Product A"
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  "data": {
    "itemName": "Product A",
    "quantity": 1
  }
}
Solution :

Utilisez une expression qui ajoute un champ quantity avec une valeur par défaut de 1 si le champ n'existe pas déjà. La macro has vérifie si un champ est disponible. La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée. Exemple :

has(message.data.quantity)  ?
    message :
    message.setField("data.quantity", 1)

Manipulation de chaînes

Vous devez extraire ou modifier des parties d'un champ de chaîne dans les données d'événement.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "customerEmail": "alex@example.com"
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  "data": {
    "customerEmail": "alex@example.com",
    "emailDomain": "example.com"
  }
}
Solution :

Utilisez une expression qui extrait le nom de domaine ("example.com") du champ customerEmail et le stocke dans un nouveau champ emailDomain. La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée. La fonction d'expression régulière extract suit la syntaxe RE2. Exemple :

message
  .setField("data.emailDomain",
re.extract(message.data.customerEmail, "(^.*@)(.*)", "\\2"))

Opérations de liste et de mappage

Vous devez utiliser des listes ou des cartes dans les données d'événement.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "productIds": [
      "product123",
      "product456"
    ]
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  "data": {
    "productIds": [
      "product123",
      "product456"
    ],
    "productFound": true
  }
}
Solution :

Utilisez une expression qui vérifie si "product456" existe dans la liste productIds et stocke le résultat (true ou false) dans un nouveau champ productFound. La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée. La macro exists vérifie si un prédicat est vrai pour tous les éléments d'une liste et combine les résultats avec l'opérateur "or". Exemple :

message.setField("data.productFound",
        message.data.productIds.exists(id, id == "product123"))

Gestion des exceptions

Vous devez gérer correctement les erreurs potentielles ou les données inattendues dans la charge utile de l'événement.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "quantity": "abc"
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  "data": {
    "quantity": 0,
    "error": "Invalid quantity"
  }
}
Solution :

Utilisez une expression qui tente de convertir le champ quantity en entier. Si la conversion échoue, définissez le champ quantity sur 0, puis ajoutez un nouveau champ error avec la valeur "Quantité non valide".

  • La macro has vérifie si un champ est disponible.
  • La fonction type renvoie le type d'une valeur.
  • La fonction d'expression régulière matches suit la syntaxe RE2.
  • La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée.

Exemple :

// Check if data.quantity exists
has(message.data.quantity) &&
// Check if data.quantity is a string
type(message.data.quantity) == string &&
// Check if string consists of digits
message.data.quantity.matches(r'^-?[0-9]+$') ?
  // If data.quantity is valid, use message
  message :
  // If data.quantity is invalid, set to 0 and generate error
  message
    .setField("data.quantity", 0)
    .setField("data.error", "Invalid quantity")

Cas d'utilisation complexes

Voici quelques cas d'utilisation complexes de la transformation des données d'événement.

Transformation des données

Vous devez effectuer plusieurs transformations sur des données d'événement imbriquées.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "orderId": "12345",
    "customer": {
      "firstName": "Alex",
      "lastName": "Taylor",
      "email": "alex@example.com",
      "address": {
        "street": "1800 Amphibious Blvd.",
        "city": "Mountain View",
        "state": "CA"
      }
    },
    "items": [
      {
        "itemId": "item1",
        "price": 10.00,
        "quantity": 2
      },
      {
        "itemId": "item2",
        "price": 5.00,
        "quantity": 1
      }
    ]
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  "data": {
    "orderId": "12345",
    "customer.firstName": "Alex",
    "customer.lastName": "Taylor",
    "customer.email": "a***@example.com",
    "customer.address.city": "Mountain View",
    "customer.address.state": "CA"
  }
}
Solution :

Utilisez une expression qui extrait la ville et l'état de l'adresse, et qui masque l'adresse e-mail.

  • La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée.
  • La fonction toMap convertit une liste CEL de cartes CEL en une seule carte CEL.
  • La fonction d'expression régulière extract suit la syntaxe RE2.
  • La fonction removeFields supprime des champs spécifiques d'un événement.
  • La fonction denormalize aplatit les structures profondes en une liste de paires clé-valeur. Les noms de champ sont délimités par un point (.) pour segmenter la hiérarchie de la structure.

Exemple :

message
.setField("data",
  message.data.setField("customer.address",
    message.data.customer.address.map(key, key == "city" || key == "state",
          { key: message.data.customer.address[key] }).toMap())
  .setField("customer.email",
        re.extract(message.data.customer.email, "(^..?).*@(.*)", "\\1***@\\2"))
  .removeFields(["items"])
  .denormalize()
)

Mise en forme et acheminement des données

Vous devez mettre en forme les données d'événement, ajouter des informations sur le produit, puis acheminer le message d'événement.

Scénario :

Compte tenu des données CloudEvents suivantes:

{
  "data": {
    "productId": "p123",
    "productName": "Example Product",
    "category": "electronics"
  }
}

Vous souhaitez écrire une expression CEL qui génère le résultat suivant:

{
  "data": {
    "productId": "electronics-p123",
    "productName": "EXAMPLE PRODUCT",
    "category": "electronics",
    "routingKey": "electronics"
  }
}
Solution :

Utilisez une expression qui met en forme le nom du produit en majuscules, ajoute un préfixe à l'ID du produit en fonction de sa catégorie et inclut une clé de routage pour le traitement en aval. La fonction setField ajoute ou remplace un champ de l'événement par une clé donnée. La fonction upperAscii renvoie une chaîne dans laquelle tous les caractères ASCII sont convertis en caractères en majuscules correspondants. Exemple :

message
.setField("data.productId",
message.data.category + "-" + message.data.productId)
.setField("data.productName", message.data.productName.upperAscii())
.setField("data.routingKey", message.data.category)