轉換範例

您可以使用 CEL 編寫轉換運算式,轉換 CloudEvents 資料。詳情請參閱「轉換收到的事件」。

以下列舉一些常見用途和範例,說明如何編寫 CEL 運算式來轉換事件資料。

標準用途

以下列舉幾個轉換事件資料的標準用途。

資料正規化

您需要將事件訊息中的巢狀資料結構扁平化,以便下游服務更輕鬆地處理。

情境:

假設有下列 CloudEvents 資料:

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

您想編寫 CEL 運算式,產生下列輸出內容:

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

手動設定輸出資料格式。這樣一來,您就能列出欄位名稱,並只挑選輸出內容中需要的元素。如果輸入內容可預測,且欄位數量不多,這就是合理的方法。setField 函式會新增或取代具有指定鍵的事件欄位。例如:

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,
})
解決方案 2:

在運算式中使用函式。setField 函式會新增或取代具有指定鍵的事件欄位。denormalize 函式會將深層結構扁平化為鍵/值組合清單。欄位名稱會使用半形句號 (.) 做為分隔符,區隔結構階層。例如:

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

這會產生下列輸出內容,與預期酬載略有不同。不過,這項功能有許多優點,包括可縮短 CEL 運算式,且適用於任何輸入內容,並會自動納入任意數量的傳入欄位。

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

資料遮蓋

您必須先遮蓋事件酬載中的私密資料,再傳送至安全性較低的環境。

情境:

假設有下列 CloudEvents 資料:

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

您想編寫 CEL 運算式,產生下列輸出內容:

{
  "data": {
    "userId": "user123",
    "email": "a***@example.com",
    "creditCardNumber": "xxxx-xxxx-xxxx-3456"
  }
}
解決方法:

使用運算式遮蓋電子郵件地址和信用卡號碼等機密資訊。setField 函式會新增或取代具有指定鍵的事件欄位。extract 規則運算式函式遵循 RE2 語法。 例如:

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

資料遮蓋

您需要根據特定條件,從事件酬載中移除特定欄位。

情境:

假設有下列 CloudEvents 資料:

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

您想編寫 CEL 運算式,產生下列輸出內容:

{
  {
  "orderId": "12345",
  "customerType": "gold"
  }
}
解決方法:

如果 customerType 為「gold」,請使用運算式遮蓋 discountCode 欄位。removeFields 函式會從事件中移除特定欄位。例如:

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

資料轉換

您需要將資料從一種格式或類型轉換為另一種格式或類型。

情境:

假設有下列 CloudEvents 資料:

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

您想編寫 CEL 運算式,產生下列輸出內容:

{
  "data": {
    "orderDate": 1704086400,
    "totalAmount": 1500.00
  }
}
解決方法:

使用可將 orderDate 轉換為 UNIX 時間戳記的運算式,並將 string 型別轉換為 double (浮點數)。totalAmountsetField 函式會新增或取代具有指定鍵的事件欄位。您可以使用字串操作函式轉換字串結果。例如:

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

條件式轉送

您需要根據事件資料,將事件傳送至不同目的地。

情境:

假設有下列 CloudEvents 資料:

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

您想編寫 CEL 運算式,產生下列輸出內容:

{
  "data": {
    "eventType": "order.created",
    "orderValue": 200,
    "routingKey": "highValue"
  }
}
解決方法:

如果 orderValue 大於 100,請使用運算式新增含有「highValue」的 routingKey 欄位;否則請使用 "normal"routingKey 欄位可用於判斷路徑。setField 函式會新增或取代具有指定鍵的事件欄位。例如:

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

預設值處理方式

您必須確保事件酬載中的特定欄位有預設值 (如果沒有)。

情境:

假設有下列 CloudEvents 資料:

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

您想編寫 CEL 運算式,產生下列輸出內容:

{
  "data": {
    "itemName": "Product A",
    "quantity": 1
  }
}
解決方法:

如果欄位尚不存在,請使用運算式新增 quantity 欄位,並將預設值設為 1has 巨集會測試欄位是否可用。setField 函式會新增或取代具有指定鍵的事件欄位。例如:

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

字串操作

您需要擷取或修改事件資料中的字串欄位部分。

情境:

假設有下列 CloudEvents 資料:

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

您想編寫 CEL 運算式,產生下列輸出內容:

{
  "data": {
    "customerEmail": "alex@example.com",
    "emailDomain": "example.com"
  }
}
解決方法:

使用運算式從 customerEmail 欄位擷取網域名稱 (「example.com」),並儲存在新的 emailDomain 欄位。setField 函式會新增或取代具有指定鍵的事件欄位。extract 規則運算式函式遵循 RE2 語法。例如:

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

清單和地圖作業

您需要在事件資料中使用清單或對應。

情境:

假設有下列 CloudEvents 資料:

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

您想編寫 CEL 運算式,產生下列輸出內容:

{
  "data": {
    "productIds": [
      "product123",
      "product456"
    ],
    "productFound": true
  }
}
解決方法:

使用運算式檢查「product456」是否存在於 productIds 清單中,並將結果 (truefalse) 儲存在新的 productFound 欄位中。 setField 函式會新增或取代具有指定鍵的事件欄位。exists 巨集會測試清單中所有元素的述詞是否成立,並使用「or」運算子合併結果。例如:

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

處理錯誤

您必須妥善處理事件酬載中可能發生的錯誤或非預期資料。

情境:

假設有下列 CloudEvents 資料:

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

您想編寫 CEL 運算式,產生下列輸出內容:

{
  "data": {
    "quantity": 0,
    "error": "Invalid quantity"
  }
}
解決方法:

使用運算式嘗試將 quantity 欄位轉換為整數。如果轉換失敗,請將 quantity 欄位設為 0,並新增 error 欄位,值為「Invalid quantity」。

  • has 巨集會測試欄位是否可用。
  • type 函式會傳回值的型別。
  • matches 規則運算式函式遵循 RE2 語法
  • setField 函式會新增或取代具有指定鍵的事件欄位。

例如:

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

複雜用途

以下列舉一些轉換事件資料的複雜用途。

資料轉換

您需要對巢狀事件資料執行多項轉換。

情境:

假設有下列 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
      }
    ]
  }
}

您想編寫 CEL 運算式,產生下列輸出內容:

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

使用運算式從地址擷取城市和州別,並遮蓋電子郵件地址。

  • setField 函式會新增或取代具有指定鍵的事件欄位。
  • toMap 函式會將 CEL 對應清單轉換為單一 CEL 對應。
  • extract 規則運算式函式遵循 RE2 語法
  • removeFields 函式會從事件中移除特定欄位。
  • denormalize 函式會將深層結構扁平化為鍵/值組合清單。欄位名稱會使用半形句號 (.) 做為分隔符,區隔結構階層。

例如:

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

資料格式和轉送

您需要設定事件資料格式、新增產品資訊,然後傳送事件訊息。

情境:

假設有下列 CloudEvents 資料:

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

您想編寫 CEL 運算式,產生下列輸出內容:

{
  "data": {
    "productId": "electronics-p123",
    "productName": "EXAMPLE PRODUCT",
    "category": "electronics",
    "routingKey": "electronics"
  }
}
解決方法:

使用運算式將產品名稱格式設為大寫、根據產品類別為產品 ID 加上前置字元,並加入用於後續處理的遞送金鑰。setField 函式會新增或取代具有指定鍵的事件欄位。upperAscii 函式會傳回字串,並將所有 ASCII 字元轉換為對應的大寫字元。例如:

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