DataWeave 言語ガイド

DataWeave は、データ変換を実行するために Mule アプリケーションで使用される関数型言語です。 DataWeave を使用して独自の強力で複雑なデータ変換をコーディングする前に、プログラミングの基本概念と関数型プログラミング言語のコア機能を理解する必要があります。

DataWeave を使用すると、次のような関数型プログラミングの利点を活用できます。

  • 同じ入力に対して常に同じ出力を生成する純粋関数により、デバッグが容易になる。

  • 実行中に値が変更されない不変変数により、コードの安定性が増す。

  • 純粋関数では結果の生成に入力パラメーターのみが使用されるため、関数シグネチャーによって関数の実行に影響する要素に関するその他の透明性を示す。

  • 関数型言語はコードが簡潔明瞭であるため、保守が容易なコードが生成される。

  • 式は必要な場合にのみ評価され、入力パラメーターが同じ場合に式が複数回評価されないように結果が保存されるため、必要呼び戦略 (​遅延評価​とも呼ばれる) によりパフォーマンスが向上する。

DataWeave 言語の基本概念

DataWeave には、ほとんどのプログラミング言語に共通する概念が組み込まれています。すべての DataWeave スクリプトは、変換の出力形式などの重要なディレクティブを含む​ヘッダー​、および結果を生成する式を含む​本文​で構成されます。

DataWeave では、​単純型​、​複雑型​、​複合型​など、さまざまな​データ構造​がサポートされます。ほとんどの DataWeave 変換では、​データセレクター​、​データ演算子​、および​関数​を​配列​や​オブジェクト​と一緒に使用して、データのマッピングまたは変換を実行します。

事前作成済み DataWeave ​モジュール​をインポートして、スクリプトで使用できる関数のセットを拡張することもできます。

DataWeave スクリプトのアーキテクチャ

DataWeave スクリプトは、3 つのダッシュ (​---​) で区切られた​ヘッダー​と​本文​で構成されます。 ヘッダーには、言語ディレクティブ (​import​ など) が含まれ、変換の出力形式を定義し、変数および関数の宣言を含めることもできます。 本文には、結果の出力を生成する式 (通常はデータマッピングまたは変換) が含まれます。

次に、基本的な DataWeave 変換の例を示します。

%dw 2.0
output application/json
---
payload

データ型

DataWeave では値を使用してデータを表します。値にはそれぞれデータ型が関連付けられています。 型システムを使用すると、変数と関数パラメーターに制約を適用できます。サポートされるデータ型には、​String​、​Boolean​、​Number​、​Date​ などの単純型、および ​Array​、​Object​、​Any​ などの複合型と複雑型が含まれます。

サポートされるすべてのデータ型の完全なリストについては、​「型システム」​を参照してください。

データセレクター

データセレクターを使用すると、データ構造内の項目にアクセスできるため、DataWeave スクリプトの実行中に作成されたペイロードまたはその他の変数からデータを取得できます。 異なる種別のセレクターには、構造からデータを抽出するために使用できるさまざまなオプションがあります。

たとえば、​単一値​セレクター ​payload.userName​ を使用して単一値 ​userName​ を取得できます。​userName​ は、入力メッセージの実際のキーを表します。

データセレクターとその使用法の完全なリストについては、​「セレクター」​を参照してください。

関数

関数は、アプリケーションで関数がコールされたときに実行される操作のグループを含むコードブロックです。関数は、さまざまなパラメーターを入力として受け入れ、関数で定義された操作でそれらを使用できます。さらに、すべての関数は処理の終了後に値を返し、この値を別の関数の入力として使用できます。

コンポーネント (Transform Message コンポーネントや Set Payload コンポーネント) で記述する各 DataWeave スクリプトは、独立したプログラムとして機能します。つまり、すべての関数の定義とコールは、コンポーネントで定義されたスクリプトに固有です。

関数定義についての詳細は、​「DataWeave 関数の定義」​を参照してください。

関数定義と関数コール

DataWeave を使用して、スクリプトのヘッダーで​独自の関数を定義​し、関数コール時に実行される操作を定義するプロセスのブループリントを作成できます。​DataWeave のマッピングおよびモジュールファイル​で定義することもできます。

DataWeave 式から関数を​コール​する場合、スクリプトの実行の正確な時点で、その関数で定義されたすべての操作を実行するように DataWeave に指示することになります。

たとえば、​upper​ は String モジュールで定義された組み込み関数です。この関数をコールして、テキスト値を大文字に変換できます。また、セレクターを使用してペイロードから値を取得し、この値を入力パラメーター ​upper(payload.someKey)​ として ​upper()​ 関数コールを実行することもできます。

DataWeave では、関数コールの​前置​表記 (​function (param1, param2)​) と​中置​表記 (​param1 function param2​) の両方がサポートされます。中置表記は、2 つのパラメーターのみを受け入れる関数でのみ使用できます。

「関数シグネチャー」​も参照してください。

データ演算子

データ演算子は、データの操作を実行して結果を生成できるようにする記号です。DataWeave では、数学演算子 (​+​、​-​、​/​、​*​)、比較演算子 (​<​、​>​、​<=​、​>=​、​==​、​~=​)、論理演算子 (​not​、​!​、​and​、​or​) など、ほとんどのプログラミング言語で一般的な演算子がサポートされています。

DataWeave では次の演算子もサポートされています。

  • 追加 (​<<​<<`, ​+​)、先頭に追加 (>>​>>`​、削除 (​-​)。配列内のデータを管理できます。

  • スコープおよびフローコントロール演算子 (​do​、​using​、​if​、​else​)。新しい変数および関数を宣言可能なスコープを作成したり、条件に基づいて式を実行したりできます。

  • 更新 (​update​)。データ構造の特定の項目を更新できます。

サポートされる演算子、その使用法、および例の完全なリストについては、​「DataWeave の演算子」​を参照してください。

関数モジュールのインポート

デフォルトでは、DataWeave スクリプトは ​dw::Core​ 関数モジュールをインポートします。異なるモジュールの関数を使用するには、​import​ ディレクティブを追加してモジュールをスクリプトにインポートします。

import​ ディレクティブの使用については、​「DataWeave リファレンス」​を参照してください。

配列

配列は、サポートされる DataWeave 型の要素をいくつでも含めることができるデータ構造です。配列を宣言するには、括弧 (​[​ および ​]​) を使用して要素のカンマ区切りのリストを囲みます (​[1,2,3]​ など)。

配列では、条件付き要素 (​[(value1) if condition]​など) を定義する条件付きロジックの適用もサポートされます。たとえば、式 ​[(1) if true, (2) if false, (3) if payload != null]​ は配列 ​[1,3]​ を定義します (​payload​ が ​null​ でない場合)。

オブジェクト

オブジェクトは、0 個以上の ​Key​ と ​value​ のペアのコレクションです。

  • Key​: 次の要素で形成されます。

    • Name​: ローカル名としての ​String​ 値と省略可能な ​Namespace​ で構成されます。

    • Attributes​: 0 個以上の ​Name:value​ ペアのコレクション。​value​ には使用可能な任意の値を指定できます。

  • Value​: 別のオブジェクト、関数コール、または配列を含む、サポートされる任意の種別で構成されます。

オブジェクトを宣言するには、括弧 (​{​ および ​}​) を使用して ​Key:value​ ペアのカンマ区切りのリストを囲みます。

{
  keyName @(keyAttributeName :"keyAttributeValue"): "value",
  User @(role:"admin"): upper("max the mule"),
  myArray: [1,2,3]
}

オブジェクトでは、条件付き要素の定義もサポートされています。

{
 (userName: name) if !isBlank(name),
 (userRole: role) if !isBlank(role)
}

関数型プログラミングの原則

関数型プログラミングのパラダイムにより、開発者は純粋関数合成と不変データを使用してアプリケーションを構築できます。関数型プログラミングは宣言型であるため、DataWeave の関数はプログラムの状態を変更する命令ステートメントではなく、値を返す単なる式です。

DataWeave は、純粋関数、第一級関数、高階関数、関数合成、ラムダ式、不変データなど、関数型プログラミングの基本原則に従います。

純粋関数

プログラミングの純粋関数は、特定の入力に対して常に同じ出力を返す点で、数学の純粋関数に似ています。また、関数の実行は、結果を生成すること以外はプログラムの他の部分に影響しません。 DataWeave のすべての関数は純粋です。実行の結果を変更する可能性がある外部値には影響されません。

第一級関数

DataWeave の純粋関数は、変数に保存され、パラメーターとして渡され、結果として返されるなど、他のデータ型で使用できる操作がサポートされているという点で「第一級関数」でもあります。

高階関数

プログラミングの高階関数も、数学での概念と同じです。これらの関数は、1 つ以上の関数をパラメーターとして取り、結果として関数を返します。高階関数の結果は、別の関数の入力パラメーターとして使用でき、​関数合成​の概念を可能にします。

関数合成

関数合成は、関数を組み合わせて複雑な操作を作成するプロセスです。この場合、1 つの関数を実行した結果は、次の関数の入力パラメーターとして機能します。DataWeave では、すべてのデータ変換は式のチェーンであり、必要に応じてデータを出力する最終結果を取得するために構成された関数です。

関数合成の例

次の例では、関数 ​pluck​ を使用してオブジェクトを配列にマップします。次に、結果の配列が関数 ​filter​ の入力として機能し、​Role​ が ​ADMIN​ の配列内の要素を選択します。マッピングプロセス中に、関数 ​upper​ は ​role​ 値を変換します。

%dw 2.0
output application/json
var collaborators =
{
    Max: {role: "admin", id: "01"},
    Einstein: {role: "dev", id: "02"},
    Astro: {role: "admin", id: "03"},
    Blaze: {role: "user", id: "04"}
}
---
collaborators pluck ((value,key,index)->  {
        "Name": key,
        "Role": upper(value.role),
        "ID": value.id
    })
    filter ((item, index) -> item.Role == "ADMIN")

次の例は同じ式を示していますが、前置表記を使用しています。 この構文は、​filter​ が ​pluck​ の結果を最初のパラメーターとして取る方法を視覚化するのに役立ちます。

%dw 2.0
output application/json
var collaborators =
{
    Max: {role: "admin", id: "01"},
    Einstein: {role: "dev", id: "02"},
    Astro: {role: "admin", id: "03"},
    Blaze: {role: "user", id: "04"}
}
---
filter(
   pluck(
       collaborators, (value,key,index)->
       {
           "Name": key,
           "Role": upper(value.role),
           "ID": value.id
       }),
   (item, index) -> item.Role == "ADMIN")

両方の式の出力は次のようになります。

[
  {
    "Name": "Max",
    "Role": "ADMIN",
    "ID": "01"
  },
  {
    "Name": "Astro",
    "Role": "ADMIN",
    "ID": "03"
  }
]

ラムダ式

ラムダ式は​匿名関数​または​関数リテラル​とも呼ばれ、識別子名を持たない関数定義であり、パラメーターとして高階関数に渡すことができます。ラムダ構文は、「特定の入力 (​a​ および ​b​) に基づいて次 (​c​) を実行する」ことを示す、​(a,b) → c​ 形式で表されます。

たとえば、DataWeave の ​map​ 関数は、パラメーターの 1 つとしてラムダ式 ​map(Array<T>, (item: T, index: Number) → R): Array<R>​ を受け入れます。 map​ は配列内の項目を反復処理し、パラメーターとして渡されるラムダ式を実行します。このラムダ式は、実行中の各配列要素の値 (​item​) とインデックス (​index​) を表す 2 つのパラメーター、および反復 ​R​ 中に実行する関数定義で構成されます。

次のコード例は、ラムダ式を受け取り、反復処理する配列内の各要素のインデックスと値を連結し、それらの値を新しい配列として返す、​map​ 関数を示しています。

ソース

%dw 2.0
output application/json
---
["Max", "the", "Mule"] map (item, index) -> index ++ " - " ++ item

出力

[
    "0 - Max",
    "1 - the",
    "2 - Mule"
]

ラムダ式についての詳細は、​「DataWeave での関数とラムダの操作」​を参照してください。

不変データ

DataWeave では、変数は定義後に割り当てられた値を変更できません。これにより、関数の実行で予期しない結果が発生しなくなります。操作の結果の新しい値を保存する場合は、新しいデータ構造を宣言する必要があります。

命令型プログラミングとの違い

オブジェクト指向プログラミング言語を使用した開発の経験がある場合、関数型プログラミングではデータと関数が分離され、ループ制御ステートメントは使用されないことを理解することが重要です。

データと関数の分離

DataWeave は代入ステートメントを使用しないため、データは不変のままです。getter メソッドと setter メソッドはなく、データ構造と動作を含むクラスもないため、各関数は入力として指定したデータでのみ機能します。既存のデータ構造を変更する必要がある場合は、新しいコピーを作成し、関数を適用してその値を変更します。

フローの制御ステートメント

DataWeave には ​for​ や ​while​ のようなループ制御ステートメントはありません。DataWeave では、反復を使用して手順を実行する方法を定義する代わりに、式を記述するときに現在の要件に焦点を絞ります。

たとえば、リストに変更を加えるには、​map​ 関数を使用してコレクション内の要素に変更を適用します。さらに、​filter​ 関数を使用してリストから特定の要素を削除したり、​reduce​ 関数を使用して配列のすべての値を 1 つの単一値にまとめたりすることができます。

ただし、​if-else​ ステートメントを使用して、式の実行時に条件を適用できます。

%dw 2.0
var myVar = { country : "FRANCE" }
output application/json
---
if (myVar.country == "USA")
  { currency: "USD" }
else { currency: "EUR" }

DataWeave の例

map​、​reduce​、および ​filter​ の使用例については、以下を参照してください。