DataWeave 変数

DataWeave は変数が関数のように動作する関数型プログラミング言語です。DataWeave では、変数と関数パラメーターに対して先行評価を使用します。さらに、DataWeave 変数は不変です。 開始する前に、Mule 4 アプリケーションでは DataWeave のバージョン 2.x が使用されることに注意してください。Mule 3 アプリケーションでの DataWeave については、​DataWeave バージョン 1.2 のドキュメント​を参照してください。 他の Mule バージョンの場合は、DataWeave の目次のバージョンセレクターを使用できます。

変数には値が割り当てられます。値は定数 (​var msg = "hello"​ など) またはラムダ式 (​() → "hello"​ など) のいずれかです。

DataWeave 1.0 の変数​については、Mule 3 の DataWeave 1.2 のドキュメントを参照してください。

DataWeave の変数割り当て

DataWeave 2.0 の変数割り当てのいくつかの例を以下に示します。

例: DataWeave スクリプトでの変数割り当て
%dw 2.0
output application/json
var msg = "Hello"

var msg2 = (x = "ignore") -> "hello"

var toUpper = (aString) -> upper(aString)

var combined = (function, msg="universe") -> function(msg ++ " WORLD")
---
[
   msg: msg,
   msg2: msg2(),
   toUpper: toUpper(msg),
   combined: combined(toUpper, "hello"),
   combined2: combined(((x) -> lower(x) ++ " Today"), msg)
]

前のスクリプトでは次の出力が生成されます。

例: 出力
[
  {
    "msg": "Hello"
  },
  {
    "msg2": "hello"
  },
  {
    "toUpper": "HELLO"
  },
  {
    "combined": "HELLO WORLD"
  },
  {
    "combined2": "hello world Today"
  }
]

この例の内容を次に示します。

  • msg​ var は定数に割り当てられています。

  • msg2​ は、定数にマップする式に割り当てられているため、​msg2()​ は ​()​ のない ​msg​ と同様に動作します。

  • toUpper​ 変数は入力パラメーターを DataWeave ​upper​ 関数にマップします。そのため、これは、別の言語の従来の関数のように ​toUpper(aString)​ として使用されます。

  • combined​ 変数は関数を入力パラメーターとして受け入れて、その関数名を 2 番目の ​msg​ 引数に適用します。デフォルト値 ​universe​ が指定されているため、2 番目の ​msg​ 引数は省略可能です。

式 ​combined(toUpper, " world")​ の結果では、ヘッダーの前半で定義された ​toUpper​ 関数が ​msg​ パラメーター値 ​world​ に割り当てられます。指定された 2 番目の引数 ​world​ が ​msg="universe"​ デフォルト値を上書きするため、結果は ​HELLO WORLD​ になります。2 番目の引数を省略している式 ​combined(toUpper)​ は、デフォルトの ​msg​ 値を使用して ​"combined": "UNIVERSE WORLD"​ を返します。

combined2: combined(x) → lower(x) ++ " Today", msg)​ は、別のコンテキストで再利用できるラムダ式を定義します。例では、​combined2​ キーは、関数のコール時に式を「インプレース (その場)」で定義します。

このような「インプレース」式の種別は、JavaScript などの言語ではクロージャーと呼ばれます。

DataWeave にはシンタックスシュガーが含まれており、関数として変数に割り当てられるラムダ式に容易にアクセスできます。これを行うには、​var​ ディレクティブを ​fun​ ディレクティブに置き換えて、ラムダ式の矢印 ​​ を等号 (​=​) に置き換えます。また、ラムダ式の引数を関数名の横に移動して、構文を、他の手続き型プログラミング言語の関数宣言のようにします。これにより、変数を関数のように使用できます。前述の例に相当するものは、次のように記述できます。

%dw 2.0
output application/json
var msg = "Hello"

var toUpper = (aString) -> upper(aString)
var toLower = (aString) -> lower(aString)

fun msg2(optParm = "ignore") = "hello"

fun toTitle(text: String) = toLower(text[0]) ++ toUpper(text[1 to -1])

fun combined(function, msg="universe") = function(msg ++ " world")
---
[
   msg: msg,
   msg2: msg2(),
   toUpper: toTitle(msg),
   combined: combined(toUpper, msg),
   combined2: combined((x) -> lower(x) ++ " today", msg)
]

この例は同じ結果を生成します。

[
  {
    "msg": "Hello"
  },
  {
    "msg2": "hello"
  },
  {
    "toUpper": "hELLO"
  },
  {
    "combined": "HELLO WORLD"
  },
  {
    "combined2": "hello world today"
  }
]

DataWeave における重要な相違点は、関数が変数であることと、各関数が、元の ​var​ 構文を単に構文的に名前変更したものであることです。これにより、関数名またはラムダ式を引数として他の関数に渡すことができます。​fun​ 構文を使用すると、DataWeave の強力な関数型プログラミングの側面にアクセスできるほか、より簡単な式を、使い慣れた関数コールとして記述することもできます。

また、DataWeave 変数 (および関数) では、すべての省略可能な引数が引数リストの最後にある限り、デフォルト値を指定することで任意の数の省略可能な引数を指定できます。

例: 配列変数の宣言およびその要素の変換

変数は DataWeave では不変ですが、配列変数を反復処理し、その要素に変換を適用した後、変換した要素を新しい変数に割り当てることができます。次の例では、2 つの配列変数を宣言し、反復処理してその要素を変換した後、変換された要素を含む 2 つの新しい配列が含まれるオブジェクトを宣言します。

DataWeave ソース:

%dw 2.0
import * from dw::core::Strings
output application/json
var numberArray = [1,2,3,4,5,6]
var stringArray = ["max", "astro", "einstein"]
---
{
  "numberArrayUpdated" : numberArray map ((value, index) -> value * value),
  "stringArrayUpdated" : stringArray map ((value, index) -> index ++ " - " ++ capitalize(value))
}

出力:

{
  "numberArrayUpdated": [ 1, 4, 9, 16, 25, 36 ],
  "stringArrayUpdated": [ "0 - Max", "1 - Astro", "2 - Einstein" ]
}

変数の命名規則

有効な識別子である変数名を宣言できます。詳細は、​「有効な識別子を宣言するためのルール」​を参照してください。

変数のスコープ

DataWeave スクリプトでは、グローバル変数とローカル変数の両方を初期化して使用できます。

  • グローバル変数は、DataWeave スクリプトのヘッダーで初期化され、DataWeave スクリプトの本文の任意の場所から名前で参照できます。

    DataWeave スクリプトのヘッダーは、変数を初期化する ​var​ ディレクティブを受け入れます (例: var language='Español'​)。複数のグローバル変数をヘッダーの別々の行で宣言できます。

  • ローカル変数は、DataWeave スクリプトの本文で初期化され、その変数を初期化した式のスコープ内からのみ、名前で参照できます。

    ローカル変数を初期化する構文は、次のようになります。

    do {
          [type <name> = <type expression>]*
          [var <name> = <expression>]*
          [fun <name>(<params>*) = <expression>]*
          [ns <name> <nsUri>]*
          ---
          <body>
    }

DataWeave 変数を再割り当てすることはできません。また、Mule メッセージの一部である変数 (対象変数など) とも異なります。DataWeave 変数は、それを初期化したスクリプトのスコープを超えて存続しません。

例: グローバル DataWeave 変数

この例では、定数値 ​Español​ を使用して ​language​ 変数を初期化し、その定数値を返す ​do​ 操作を定義します。DataWeave スクリプトの本文では、変数 ​myVar​ を使用して ​do​ 操作をコールします。それによって XML 出力の ​<language/>​ 要素に値 ​Español​ が入力されます。

変換
%dw 2.0
output application/xml
var myVar = do {
    var language = "Español"
    ---
    language
}
---
{
  document: {
    language: myVar,
    text: "Hola mundo"
  }
}
出力
<?xml version='1.0' encoding='UTF-8'?>
<document>
  <language>Español</language>
  <text>Hola mundo</text>
</document>

例: ローカル DataWeave 変数

ローカル変数を初期化するには、リテラル式、変数参照式、または関数式のいずれかを使用できます。これらの式では、そのスコープ内の他のローカル変数や、入力変数またはグローバル変数を参照できます。

ベストプラクティスとして、​do​ スコープ内でローカル変数を宣言することをお勧めします (​「DataWeave のフローコントロール」​参照)。​using​ キーワードを使用してスコープを宣言する代替方法は非推奨になり、互換性を提供するためにのみ使用できます。

ローカル変数は、それを初期化した式のスコープ内からのみ名前で参照できます。宣言は任意のリテラル式の先頭に追加できます。リテラルにより変数のスコープが区切られるため、そのスコープの外部にある変数を参照することはできません。

次の例は、ローカル変数の初期化を示しています。

例: 簡単な値へのスコープ設定

次の例では、ローカル変数 ​myVar​ を ​do​ スコープ内で設定します。そして、​do​ を DataWeave スクリプトの本文でコールします。

%dw 2.0
output application/json
---
do {
      var myVar = 2
      ---
      3 + myVar
}

結果は ​5​ になります。

例: 配列リテラルへのスコープ設定

次の例では、ローカル変数 ​myVar​ を ​do​ スコープ内で設定し、それを使用して配列の 2 番目の要素の値を ​2​ に設定します。

%dw 2.0
output application/json
---
do {
      var myVar = 2
      ---
      [1, myVar, 3]
}

結果は ​[ 1, 2, 3]​ になります。

例: オブジェクトリテラルへのスコープ設定

次の例では、すべての変数への参照が有効です。 ​fn​ と ​ln​ は ​do​ スコープ内で定義されてコールされます。グローバル変数 ​myVar​ にもそのスコープからアクセスできます。

%dw 2.0
var myVar = 1234
var myDo =  do {
    var fn = "Annie"
    var ln = "Point"
    ---
    {
      id : myVar,
      firstname : fn,
      lastname : ln
    }
}
output application/xml
---
{ person : myDo }
<?xml version='1.0' encoding='UTF-8'?>
<person>
  <id>1234</id>
  <firstname>Annie</firstname>
  <lastname>Point</lastname>
</person>
例: スコープの外部の​無効な参照

次の例では、​do​ のスコープの外部から ​fromDoScope​ が参照されているため、エラーが生成されます。 その結果、連結操作 (​++​) によって名前-値のペアをコレクションに追加できません。

%dw 2.0
var myVar = 1234
var myDo =  do {
    var fn = "Annie"
    var ln = "Point"
    var fromDoScope = "Platform"
    ---
    {
      id : myVar,
      firstname : fn,
      lastname : ln
    }
}
output application/xml
---
{
    person : myDo ++ { "outsideDoScope" : fromDoScope }
}

この無効な例では、​Unable to resolve reference of fromDoScope.​ のエラーが返されます。

例: 関数内部の参照

次の例では、文字列 ​HELLO​ をヘッダーで定義された関数 ​test​ に渡します。​do​ スコープは文字列を受け取って小文字に変換し、その文字列を ​suffix​ 変数と連結します。この変数もスコープのヘッダー内で定義されています。

%dw 2.0
fun test(param1: String) = do {
    var suffix = "123"
    fun innerTest(str: String) = lower(str)
   ---
   innerTest(param1 ++ suffix)
}
output application/json
---
test("HELLO")

結果は ​"hello123"​ になります。

ラムダ式として割り当てられた変数

変数にラムダ式を割り当てると、変数は関数のように動作します。関数と同様に、変数割り当てのラムダ式には、右側の式で使用できるパラメーターを含めることができます (例: (string) → upper(string)​。これは、任意の文字列を大文字に変換します)。

他の変数を引数として別の変数のラムダ式に渡すこともできます。次の例は、​toUpper​ 変数のラムダ式を名前によって ​addSuffix​ 変数のラムダ式に渡す方法を示しています。

%dw 2.0
output application/json
var toUpper = (aString) -> upper(aString)

var addSuffix = (msg, aFunction, suffix) -> aFunction(msg ++ suffix)
---
addSuffix("hello", toUpper, " world") //result is "HELLO WORLD"

@Lazy() アノテーション

Studio で DataWeave スクリプトを記述しているときに、オートコンプリートの候補に内部アノテーション ​@Lazy()​ が表示されることがあります。このアノテーションは一般的な使用を目的としたものではなく、スクリプトのパフォーマンスが向上することはありません。