Flex Gateway新着情報
Governance新着情報
Monitoring API ManagerDataWeave バージョン 2 では型システムがサポートされます。型システムで実行される型チェックを利用するには、このセクションで説明されている変数および関数の制約式を提供する必要があります。この型の値を定義する方法についての詳細は、「型の値構成」を参照してください。
型システムでは、次のような構成要素のセットに対して一連の制約を定義します。
変数
関数パラメーター
この制約は、型チェックフェーズで、関数コールの変数または引数に割り当てられた値に DataWeave で制約を確実に適用する場合に使用されます。次に例を示します。
%dw 2.0 import * from dw::core::Strings output application/json var userName: String = "John"
userName
の変数定義には、型 String
の値を割り当てるといった制約があります。
他の値のデータ型が割り当てられた場合、型チェックエラーが発生します。
%dw 2.0 import * from dw::core::Strings output application/json fun toUser(id: Number, userName: String): String = "you called the function toUser!"
関数 toUser
のコールに対する制約では、1 番目の引数の型が Number
、2 番目の引数の型が String
である (これらの型に強制変換できるようにする) 必要があります。また、別の制約では、関数の結果の型が String
である必要があります。この制約は toUser
のコールでは使用されません。これは、関数本文で適切な型が生成されたことを検証するための定義に適用されます。
toUser(123, "John") toUser("123", true)
2 番目のコールは失敗することが予想される場合がありますが、自動型強制を使用するとコールを正常終了し、両方のコールを正常に機能させることができます。2 番目の関数コールの場合は、String
値 "123"
を Number
値 123
に変換し、Boolean
値 true
を String
値 "true"
に変換する自動型強制があり、これにより関数をコールすることができます。
型チェックエラーが発生するコールの例として、toUser("a 12", "John")
があります。String (文字列) 値 "a 12"
を Number
型に型強制できないためです。
また、DataWeave は、制約として型が指定されていない場合でも、グローバル型推定アルゴリズムを使用してコードを検証します。
制約の使用は省略可能ですが、大きなスクリプトや複数のスクリプトでは制約が役立つ場合があります。型システムでは型チェックアルゴリズムが実行されるため、DataWeave ロジックのバグを回避するには型システムが役立ちます。また、IDE でスクリプトを記述してこの制約を定義する場合、このツールを使用して型チェックエラーを見つけることができるため、スクリプトが実行されたときにスクリプトが失敗することはありません。 |
DataWeave の型システムでサポートされる型は 3 つのカテゴリに分割されます。
単純型
複合型
複雑型
単純型は文字列やブールなどの値を表します。この値はアトミックです。つまり、この値は他の値から構成されていません。次の型は単純型です。
String
Boolean
Number
Regex
Null
一時的: Date
、DateTime
、LocalDateTime
、LocalTime
、Time
、Period
Null
は 1 つの値 (null
) のみの型です。つまり、null
を、型 Null
を除き、型 String
やその他の型に割り当てることはできません。
たとえば、String モジュール内の repeat
関数にシグネチャー repeat(String, Number): String
があるとします。つまり、この関数は 1 番目のパラメーターとして型 String
の値のみを受け入れ、2 番目のパラメーターとして型 Number.
の値のみを受け入れます。この関数は型 String
の値を返します。
%dw 2.0 import * from dw::core::Strings output application/json --- repeat("a", 3)
これは "aaa"
を返しますが、次の例ではエラーがスローされます。値 null
を、型 String
の値が想定されるパラメーターに割り当てることはできないためです。
%dw 2.0 import * from dw::core::Strings output application/json --- repeat(null, 3)
次の例では、スクリプトは 1 番目のパラメーターに型 Null
の値を割り当てます (この値の型は Type<Null>
)。自動型強制によって値が型 String
("Null"
) に変換されるため、これは "NullNullNull"
を返します。
%dw 2.0 import * from dw::core::Strings output application/json --- repeat(Null, 3)
一部の関数には、null
を使用してコールできるオーバーロード状態のシグネチャーがあります (関数にはさまざまなパラメーター種別の複数の定義があります)。
たとえば、dw::core::Strings
からの isNumeric
関数にシグネチャー isNumeric(String): Boolean
があるとします。これは、文字列を受け取り、その文字列が数値の場合に結果を正常に返しますが、関数は isNumeric(Null): Boolean
としても定義されています。
このため、null
(isNumeric(null)
) を使用して関数 isNumeric
をコールした場合、関数は例外をスローしません。実行時に、ディスパッチアルゴリズムである関数は、使用される値の型に基づいて正しい関数を選択します。null
を引数とする isNumeric
の定義のため、この関数は false
を返します。
複合型には他の値が含まれます。複合型は Array
、Object
、Function
です。
配列の型は Array<T>
です。ここで、T
は、配列内の要素の型を定義する型パラメーターです。たとえば、Number
の Array
型を使用して変数を定義する構文を次に示します。
var idsList: Array<Number> = [1, 22, 333, 4444]
変数 idsList
は、その変数に割り当てられた配列に Number
型の値のみが含まれる場合のみ、型チェックフェーズに合格します。
Object
型は Object
または {}
の 2 つの方法で定義できます。この両方でオープンオブジェクトが定義されますが、キー-値ペアに対する制約は指定されません。「クローズドオブジェクトとオープンオブジェクト」も参照してください。
キー-値ペアに対する一連の制約を使用して Object
型を定義する構文は、Object
型の値を定義する構文によく似ています。
{ keyName @(attrName: AttrType): valueType, ... }
たとえば、firstName
String
、lastName
String
、および age
Number
を使用して User
型を定義する構文を次に示します。
%dw 2.0 output application/json type User = { firstName: String, lastName: String, age: Number }
各キー-値ペアに修飾子を割り当てることで、項目が常に存在することや、項目が反復する可能性があることを指定できます。
反復する項目の場合は、*
を使用します。たとえば、次の型では、複数の lastName
項目を持つことができます。
%dw 2.0 output application/json { firstName: String, lastName*: String, age: Number }
条件付き項目の場合は、?
を使用します。たとえば、次の型では、age
項目は存在してもしなくても構いません。
%dw 2.0 output application/json { firstName: String, lastName*: String, age?: Number }
Object
型はクローズドまたはオープンにすることができます。クローズドオブジェクトでは、型で指定されたキー-値ペア以外の項目がない場合のみ、オブジェクト値を受け入れます。
オープンオブジェクトでは、型で宣言された項目に対してのみ制約が適用され、すべての制約が検証された場合に型は値を受け入れます。この型は、宣言で示された項目とは別の項目を含むオブジェクトを受け入れます。特に指定しない限り、すべての object
型がオープンです。
次の例は、age
が型宣言に含まれていなくても、変数 user
の型がオープンオブジェクトのため、成功します。
%dw 2.0 output application/json var user: {firstName: String, lastName: String} = {firstName: "John", lastName: "Smith", age: 34}
クローズドオブジェクトを指定する構文は {| |}
です。次の例では、User
型でサポートされるキーを firstName
と lastName
のみに限定します。age
項目が受け入れられないため、このスクリプトは例外をスローします。
%dw 2.0 output application/json var user: {|firstName: String, lastName: String|} = {name: "John", lastName: "Smith", age: 34}
DataWeave は関数型言語であり、関数は第一級オブジェクトとみなされます。つまり、関数は、関連付けられた型を持つ値です。
関数型を定義する構文を次に示します。
(paramType: ParamType,...) -> ReturnType
たとえば、型 String
のパラメーター、型 Number
の 2 番目のパラメーター、および Boolean
戻り値を持つ Function
型を制約で定義する場合、正しい構文は次のようになります。
(paramA: String, paramB: Number) -> Boolean
次の例では、別の関数を引数として受け取る関数を定義します。
%dw 2.0 output application/json fun applyIDsChange(ids: Array<Number>, changeTo: (Number) -> Number): Array<Number> = ???
changeTo
の制約 (Number) → Number
に一致しない関数を含む関数 applyIDsChange
をコールすると、DataWeave は型チェックエラーをスローします。
たとえば、次のコールでは、abs
が Number
型の値を取り、changeTo
パラメーターに一致する Number
を返す関数のため、コールは正常に機能します。
applyIDsChange([1,-6, 3, -8], abs)
ただし、次のコールでは、sum
が Array
を取り、パラメーター制約に一致しない Number
を返す関数のため、コールは失敗します。
applyIDsChange([1,-6, 3, -8], sum)
複雑型には、Any
と Nothing
型、Union
型、Intersection
型、および Literal
型が含まれます。この各型の名前は直感的なわかりやすい名前です。
場合によって、型がすべての値を受け入れるために制約を適用できないことがあります。
Any
型は、可能なすべての値を受け入れます。
Nothing
型は値を受け入れませんが、すべての型に割り当てることができます。この型は明示的に使用されることは頻繁にはありませんが、型推定アルゴリズムで使用されます。
Union
型は、型を構成するために使用されます。Union
型を定義する構文を次に示します。
TypeA | TypeB | ...
次の例では、型 String
または Number
の値を受け入れる制約を使用して変数を定義します。
var age: String | Number = if (payload.allStrings) "32" else 32
一般的なパターンでは、Null
型を Union
型と共に使用して、型が null
を値として受け入れることを指定します。次の例では、関数 parseEmail
は型 String
または Null
の入力を許容します。この場合、ペイロードの省略可能な項目 email
を含むオブジェクトを使用でき、payload.email
を使用して関数をコールできます。
fun parseEmail(email: String | Null) = "Code that handles email being of type String or Null"
DataWeave 2.3.0 で導入されました。Mule 4.3 以降でサポートされます。
Intersection
型は Object
型を交差させます。この場合、交差はオブジェクト型の連結 (++
) として機能します。
Intersection
型の構文を次に示します。
TypeA & TypeB & ...
次の例では、Intersection
が 2 つの Object
型を連結し、結果として型 {name: String, lastName: String}
が生成されます。この型は、追加のキー-値ペアを受け入れることができるオープンオブジェクトです。変数は、その変数に割り当てられた値を受け入れます。
var a: {name: String} & {lastName: String} = {name: "John", lastName: "Smith", age: 34}
クローズドオブジェクトの場合、オブジェクト型の連結が返されますが、結果としてクローズドオブジェクトが生成されます。
次の例では、交差により型 {|name: String, lastName: String|}
が生成されますが、オブジェクト内に追加項目 (項目 age
) がある場合、クローズドオブジェクトは Object
値を受け入れないため、例外がスローされます。
var a: {|name: String|} & {|lastName: String|} = {name: "John", lastName: "Smith", age: 34}
DataWeave 2.3.0 で導入されました。Mule 4.3 以降でサポートされます。
リテラル型は 1 つの値を表します。たとえば、String
値 "foo"
は型 "foo"
で表すことができます。
次のリテラル型は型システムに含まれます。
String
リテラル型
Number
リテラル型
Boolean
リテラル型
リテラル型を Union
型と共に使用して、許容される値の有限セットとして型を宣言できます。たとえば、次の型宣言は Union
型とリテラル型の別名です。
type Weekdays = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" type Days = Weekdays | "Saturday" | "Sunday"
次の例では、変数はリテラル型 404
および 500
の値のみを受け入れます。型システムでは、実行前に変数を確実にこれらのリテラル値のいずれかのみとすることができます。
%dw 2.0 output application/json var errorStatusCode: 404 | 500 = payload.statusCode match { case "error 404" -> 404 case "error 500" -> 500 }
関数オーバーロードでは、引数の値に基づいて異なる動作を定義できます。
%dw 2.0 import * from dw::core::Strings output application/json fun errorHandling(errorCode: 404 | 405, response): String = "Code for error 4XX handling here!" fun errorHandling(errorCode: 500 | 501, response): String = "Code for error 5XX handling here!" --- errorHandling(payload.statusCode, payload)
実行時に関数ディスパッチアルゴリズムが payload.statusCode
の値の型に基づいて正しい関数を選択します。関数の動作を変更するために if
ステートメントを使用して引数の値を確認する必要はありません。
型パラメーターを使用すると、関数またはデータ型を汎用的に記述できるため、値の型に依存することなく、値を同様に処理できます。
たとえば、型情報を失うことなく配列の最初の要素を返す関数を定義できます。この例では、head
関数が入力として取る配列内の項目の型を変数定義 firstString:String
と firstNumber:Number
で指定します。
%dw 2.0
fun head<ItemType>(elements: Array<ItemType>): ItemType = elements[0]!
var firstString:String = head(["DataWeave", "Java", "Scala", "Haskell"]) ++ " Rules!!!"
var firstNumber:Number = head([1,2,3])
output application/json
---
firstNumber
スクリプトの本文で、firstNumber
は数値 1
を返します。firstNumber
を firstString
に置き換えると、スクリプトは文字列 "DataWeave Rules!!!"
を返します。
型パラメーターをバインドして、特定の型の値を要求できます。次の例での {name: "DataWeave"}
の追加は有効です。これは、関数定義内の {name: String}
で、name
キーの値は文字列である必要があることが示されているためです。
%dw 2.0
fun addName<User <: {} >(user: User): User & {name: String} = user ++ {name: "DataWeave"}
var myUser: {name: String, developers: Number} = addName({developers: 3})
型パラメーターを使用して、型定義をパラメーター化できます。たとえば、1 つはテキストファイル、もう 1 つはバイナリファイルのファイルのコンテンツをモデル化するデータ構造を定義するとします。型パラメーターを使用して、正しい実装をディスパッチする新しい型を作成できます。
%dw 2.0
type FileData<Content> = {
data: Content,
name: String
}
fun read(file: FileData<String>) = "This is a text file with data " ++ file.data
fun read(file: FileData<Binary>) = "This is a binary file with data " ++ (file.data as String {base: "64"})
---
{
binary: read({data: "Hello World" as Binary, name: "myFile.bin"}),
text: read({data: "Hello World", name: "myFile.txt"})
}