DataWeaveでいろいろ変換してみる

Anypoint Platformのデータ変換のためのスクリプトであるDataWeaveを少し触ってみようかと思います。

## 準備
![flow.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/ad5f7285-e141-c0ed-5d72-ab5b4c7da1a6.jpeg)
Anypoint Studioで、こんな感じの簡単なフローを作成します。
※ イベントトリガーは何でも構いません。今回使用するのはTransformMessageだけです。

### DataWeaveのコードを簡単に動作確認する方法
DataWeaveではいちいちフローを動かさなくても簡単に動作の確認を行う方法があります。

まず、Tranform Messageをクリックしてプロパティを表示します。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/8398f279-a3db-b805-5c09-3fe320bc4919.png)
![サンプルペイロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/3f0de932-3cdd-4caa-09a5-84f2aeea10a8.png)

1. DataWeaveのBodyを「[]」から「payload」に変換します。
2. Previewボタンをクリックします。
3. 「create required sample data to execute preview」リンクをクリックします。
4. Inputの「Context」タブの横に「payload」タブが追加されます。

これで準備完了です。このPayloadタブ内にサンプルのInputデータを書き込むと、DataWeaveの内容で変換されたデータが「Preview」に表示されるようになります。

例えば以下のようなJSONデータをサンプルデータとして入力してみてください。

``` json:input
{
	"name": "Carcassonne",
	"publishyear": "2000",
	"price": "3600"
}
```
Previewに以下のような結果が表示されるはずです。
これは上記のJSONをJavaの形式に変換した内容を表現したものとなります。

```JSON:output
{
  name: "Carcassonne" as String {class: "java.lang.String"},
  publishyear: "2000" as String {class: "java.lang.String"},
  price: "3600" as String {class: "java.lang.String"}
} as Object {encoding: "UTF-8", mediaType: "*/*", mimeType: "*/*", class: "java.util.LinkedHashMap"}
```
※ プレビュー機能ですが、DataWeaveの記述（コメント含む）に日本語が含まれるとエラーとなってしまう現象があるようです。

#### テスト用のアウトプット
DataWeaveではアウトプットの形式としてJSONやXML、Java、CSVなどいろいろな形式を指定することができます。
その中で「dw」というDataWeaveのテスト用のアウトプット形式があります。この形式の使用目的は主にエラー内容の判別にあります。DataWeaveでは大きく2つの種類にエラーを区別できます。一つはDataWeaveの記述そのもののエラーで、もう一つが指定されたアウトプットの形式への変換エラーです。エラーが発生した際に、アウトプットを「dw」に変更して確認し、エラーとならない場合は変換エラーとなります。
例えば、先ほどの状態からアウトプットの形式を「java」→「xml」に変換してみてください。エラーとなりプレビューが変更されます。
続いて「xml」→「dw」に変換してみてください。エラーとはならず、以下のようなアウトプットがプレビューに出力されます。

```JSON:output
{
  name: "Carcassonne",
  publishyear: "2000",
  price: "3600"
} as Object {encoding: "UTF-8", mediaType: "application/dw", mimeType: "application/dw", contentLength: 74}
```

## JSON to XML
では、なぜXMLに変換しようとすると変換エラーが発生するのでしょうか。それはXMLはルート要素を持つ必要があるためです。アウトプットの形式を「xml」にもどして、インプットのJSONを以下のように書き換えてみましょう。

```JSON:input
{
	"boardgame": {
		"name": "Carcassonne",
		"publishyear": "2000",
		"price": "3600"
	}
}
```
今度はXMLの形式のアウトプットがプレビューに表示されるようになります。

```XML:output
<?xml version='1.0' encoding='UTF-8'?>
<boardgame>
  <name>Carcassonne</name>
  <publishyear>2000</publishyear>
  <price>3600</price>
</boardgame>
```
インプットの値を変えずに、変換処理でルート要素を追加する場合は、以下のようにDataWeaveで明示的にルート要素を追加することもできます。

```:DataWeave
%dw 2.0
output application/xml
---
{
	boardgame:
		{
			name: payload.name,
			publishyear: payload.publishyear,
			price: payload.price
		}
}
```

#### XMLの属性の表現
DataWeaveでXMLの属性を表現するには「@」を使用します。

```:DataWeave
%dw 2.0
output application/xml
---
{
	boardgame @(name: payload.name):
		{
			publishyear: payload.publishyear,
			price: payload.price
		}
}
```
結果は以下のようになります。

```XML:output
<?xml version='1.0' encoding='UTF-8'?>
<boardgame name="Carcassonne">
  <publishyear>2000</publishyear>
  <price>3600</price>
</boardgame>
```

## 配列を扱う
DataWeaveで配列を扱うには「**map**」関数を使用します。
以下のように「payload map {}」の形で記述します。

```:DataWeave
%dw 2.0
output application/json
---
payload map {
	index: $$,
	name: $.name
}
```

各レコードの内容は「$」で表現されます。（「$$」はインデックス値）
分かりやすく表現するために、ラムダ式を利用することも可能です。

```:DataWeave
%dw 2.0
output application/json
---
payload map(object, index) -> {
	index: index,
	name: object.name
}
```

### フィルターとソート
DataWeaveではさまざまな関数の利用が可能です。
https://docs.mulesoft.com/mule-runtime/latest/dw-functions

特に「core」パッケージに含まれた関数は、自動でインポートされた状態で提供されています。
ここではフィルターとソートを行う関数を利用してみます。

```json:input
[
	{
		"name": "Pandemic",
		"publishyear": "2008",
		"price": "3072",
	},
	{
		"name": "catan",
		"publishyear": "1995",
		"price": "2980",
	},
	{
		"name": "Carcassonne",
		"publishyear": "2000",
		"price": "3600",
	}
]
```

```:DataWeave
%dw 2.0
output application/json
---
payload filter($.price >= 3000)
        orderBy($.publishyear)
        map {
        	inde: $$,
        	name: $.name
        }
```
価格3000円以上でフィルターしたうえで、publishyearでソートしてみました。

```json:output
[
  {
    "index": 0,
    "name": "Carcassonne"
  },
  {
    "index": 1,
    "name": "Pandemic"
  }
]
```

今回はここまでとなります。
まずは少しでも動かしてみて、DataWeaveがどういうものかのイメージができていただけたらと思います。