Ejemplos de transformaciones

Puedes transformar tus datos de CloudEvents escribiendo expresiones de transformación con CEL. Consulta más información sobre cómo transformar eventos recibidos.

A continuación, se muestran algunos casos prácticos y ejemplos habituales que le indican cómo escribir expresiones CEL para transformar sus datos de eventos.

Casos prácticos estándar

A continuación, se indican algunos casos prácticos habituales para transformar datos de eventos.

Normalización de datos

Debe acoplar una estructura de datos anidada en el mensaje de evento para que un servicio posterior pueda procesarla más fácilmente.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

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

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

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

Dar formato a los datos de salida manualmente. De esta forma, puede enumerar los nombres de los campos y elegir solo los elementos que necesite en el resultado. Este es un enfoque razonable cuando la entrada es predecible y cuando el número de campos es bajo. La función setField añade o sustituye un campo del evento con una clave determinada. Por ejemplo:

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,
})
Solución 2:

Usa una función en la expresión. La función setField añade o sustituye un campo del evento con una clave determinada. La función denormalize aplana las estructuras profundas en una lista de pares clave-valor. Los nombres de los campos se delimitan con un punto (.) para segmentar la jerarquía de la estructura. Por ejemplo:

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

El resultado es el siguiente, que difiere ligeramente de la carga útil esperada. Sin embargo, entre las ventajas se incluyen una expresión CEL más corta que funciona con cualquier entrada y que incluye automáticamente cualquier número de campos entrantes.

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

Enmascaramiento de datos

Debe enmascarar los datos sensibles de la carga útil de un evento antes de enviarlos a un entorno menos seguro.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

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

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

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

Usa una expresión para enmascarar cualquier información sensible, como la dirección de correo electrónico y el número de la tarjeta de crédito. La función setField añade o sustituye un campo del evento con una clave determinada. La función de expresión regular extract sigue la sintaxis de RE2. Por ejemplo:

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"))

Ocultación de datos

Tienes que quitar campos específicos de una carga útil de evento en función de determinadas condiciones.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

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

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

{
  {
  "orderId": "12345",
  "customerType": "gold"
  }
}
Solución:

Usa una expresión que oculte el campo discountCode si customerType es "oro". La función removeFields elimina campos específicos de un evento. Por ejemplo:

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

Conversión de datos

Necesitas convertir datos de un formato o tipo a otro.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

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

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

{
  "data": {
    "orderDate": 1704086400,
    "totalAmount": 1500.00
  }
}
Solución:

Usa una expresión que convierta orderDate en una marca de tiempo UNIX y el tipo totalAmount de string a double (número de punto flotante). La función setField añade o sustituye un campo del evento con una clave determinada. Puedes usar funciones de manipulación de cadenas para convertir los resultados de las cadenas. Por ejemplo:

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

Enrutamiento condicional

Necesita enrutar eventos a diferentes destinos en función de los datos de los eventos.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

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

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

{
  "data": {
    "eventType": "order.created",
    "orderValue": 200,
    "routingKey": "highValue"
  }
}
Solución:

Usa una expresión que añada un campo routingKey con el valor "highValue" si el orderValue es mayor que 100. De lo contrario, "normal". El campo routingKey se puede usar para determinar la ruta. La función setField añade o sustituye un campo del evento con una clave determinada. Por ejemplo:

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

Gestión de valores predeterminados

Debe asegurarse de que determinados campos de la carga útil del evento tengan valores predeterminados si no están presentes.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

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

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

{
  "data": {
    "itemName": "Product A",
    "quantity": 1
  }
}
Solución:

Usa una expresión que añada un campo quantity con el valor predeterminado 1 si el campo aún no existe. La macro has comprueba si un campo está disponible. La función setField añade o sustituye un campo del evento con una clave determinada. Por ejemplo:

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

Manipulación de cadenas

Necesita extraer o modificar partes de un campo de cadena en los datos de evento.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

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

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

{
  "data": {
    "customerEmail": "alex@example.com",
    "emailDomain": "example.com"
  }
}
Solución:

Usa una expresión que extraiga el nombre de dominio ("example.com") del campo customerEmail y lo almacene en un nuevo campo emailDomain. La función setField añade o sustituye un campo del evento con una clave determinada. La función de expresión regular extract sigue la sintaxis de RE2. Por ejemplo:

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

Operaciones de lista y mapa

Necesitas trabajar con listas o mapas en los datos de eventos.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

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

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

{
  "data": {
    "productIds": [
      "product123",
      "product456"
    ],
    "productFound": true
  }
}
Solución:

Usa una expresión que compruebe si "product456" está en la lista productIds y almacene el resultado (true o false) en un nuevo campo productFound. La función setField añade o sustituye un campo del evento con una clave determinada. La macro exists comprueba si un predicado se cumple en todos los elementos de una lista y combina los resultados con el operador "o". Por ejemplo:

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

Gestión de errores

Debes gestionar correctamente los posibles errores o datos inesperados en la carga útil del evento.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

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

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

{
  "data": {
    "quantity": 0,
    "error": "Invalid quantity"
  }
}
Solución:

Usa una expresión que intente convertir el campo quantity en un número entero. Si la conversión falla, asigna el valor 0 al campo quantity y añade un nuevo campo error con el valor "Invalid quantity".

  • La macro has comprueba si un campo está disponible.
  • La función type devuelve el tipo de un valor.
  • La función de expresión regular matches sigue la sintaxis de RE2.
  • La función setField añade o sustituye un campo del evento con una clave determinada.

Por ejemplo:

// 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")

Casos prácticos complejos

A continuación, se indican algunos casos prácticos complejos para transformar datos de eventos.

Transformación de datos

Necesitas realizar varias transformaciones en datos de eventos anidados.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

{
  "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
      }
    ]
  }
}

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

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

Usa una expresión que extraiga la ciudad y el estado de la dirección y que oculte la dirección de correo.

  • La función setField añade o sustituye un campo del evento con una clave determinada.
  • La función toMap convierte una lista de mapas de CEL en un solo mapa de CEL.
  • La función de expresión regular extract sigue la sintaxis de RE2.
  • La función removeFields elimina campos específicos de un evento.
  • La función denormalize aplana las estructuras profundas en una lista de pares clave-valor. Los nombres de los campos se delimitan con un punto (.) para segmentar la jerarquía de la estructura.

Por ejemplo:

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()
)

Formato y enrutamiento de datos

Debe dar formato a los datos de eventos, añadir información de producto y, a continuación, enrutar el mensaje del evento.

Supuesto:

Teniendo en cuenta los siguientes datos de CloudEvents:

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

Quieres escribir una expresión CEL que dé como resultado lo siguiente:

{
  "data": {
    "productId": "electronics-p123",
    "productName": "EXAMPLE PRODUCT",
    "category": "electronics",
    "routingKey": "electronics"
  }
}
Solución:

Usa una expresión que ponga en mayúsculas el nombre del producto, añada un prefijo al ID del producto en función de su categoría e incluya una clave de enrutamiento para el procesamiento posterior. La función setField añade o sustituye un campo del evento con una clave determinada. La función upperAscii devuelve una cadena con todos los caracteres ASCII convertidos a sus correspondientes caracteres en mayúsculas. Por ejemplo:

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