[JSONata] AWS Step Functionsの機能で日付文字列を加工してみる

[JSONata] AWS Step Functionsの機能で日付文字列を加工してみる

Clock Icon2025.05.28

こんにちは。サービス開発室の武田です。

AWS Step FunctionsのJSONata便利ですよね。使ってみると結構感動することが多いので、少しでも皆さんにお届けできればと思っています。

今回のテーマは「日付データの加工」です。

たとえば、ステートマシンのコンテキストには実行開始日時が記録されています。JSONPathであれば$$.Execution.StartTimeでアクセスでき、具体的には2025-05-28T09:00:00.000Zのような文字列データを持っています。

ではこのデータから2025/05/28という文字列を作るにはどう書きますか?Lambda関数などは使わずStep Functionsの機能のみで実現することとします。

JSONPath形式で書くなら

実際のやり方はいくつかありますが、たとえば次のようなPassステートを定義すれば目的の文字列を生成できます。

{
  "Type": "Pass",
  "Next": "Next Pass",
  "Parameters": {
    "date.$": "States.Format('{}/{}/{}', States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 0), States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 1), States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 2))"
  }
}

わかりにくいので式の部分だけ取り出します。

States.Format('{}/{}/{}',
    States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 0),
    States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 1),
    States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 2)
)

新しい文字列を作りたいので、全体のフォーマットはStates.Formatを使用します。次の年月日のデータをそれぞれのプレースホルダーに指定できればOKです。肝心の年月日ですが、States.StringSplit($$.Execution.StartTime, '-T')という式が出てきていますが、これは次のような結果を返します。

["2025", "05", "28", "09:00:00.000Z"]

そのため、States.ArrayGetItemを使用して必要な部分を取り出しているわけです。

結果としてStates.Format('{}/{}/{}', '2025', '05', '28')という形になり、目的の2025/05/28が取得できました。

JSONata形式で書くなら

続いて同じことをJSONataでもやってみましょう。どう書けばいいでしょうか?

一例としては次のような書き方ができます。

{
  "Type": "Pass",
  "Next": "Next Pass",
  "QueryLanguage": "JSONata",
  "Output": "{% {\"date\": $split($states.context.Execution.StartTime, \"T\")[0] ~> $replace(\"-\", \"/\")} %}"
}

こちらも式の部分だけ抜き出してみます。

$split($states.context.Execution.StartTime, "T")[0] ~> $replace("-", "/")

だいぶシンプルになりましたね。$split($states.context.Execution.StartTime, "T")は文字列の分割をしています。先ほどとは違い単純にTだけで分割しているため、次の結果になります。

["2025-05-28", "09:00:00.000Z"]

必要なのは1個目だけなので[0]を指定しています。次に見慣れない~>ですが、Linuxコマンドなどでいうところのパイプ(|)機能です(JSONataでは Chain と呼ぶようです)。関数の実行結果を、次の関数の 第1引数 に渡せます。

つまり、今回の例では次の書き方と同じです。

$replace($split($states.context.Execution.StartTime, "T")[0], "-", "/")

個人的には関数のネストよりChainの方が好みですので、こちらの書き方を推していきたいです。さて、後続の処理は$replace("-", "/")で、文字どおり-/に置換します。結果として2025/05/28が取得できます。

ちなみにJSONataでは正規表現も使えるため、かなり強力な文字列操作が可能です。夢が広がりますね。

また上記は「文字列操作」に主眼を置いた方法でしたが、日時データとしての扱いも知っておくと便利なので紹介しておきます。

JSONataはいわゆるDateTime型というものはサポートしていません。代わりに文字列表現とミリ秒(エポックタイム)との相互変換がサポートされています。そこで次のように書いても、同様の結果が得られます(タイムゾーンの操作などが必要であればこちらの方が好ましいでしょう)。

$toMillis($states.context.Execution.StartTime) ~> $fromMillis("[Y0001]/[M01]/[D01]")

まとめ

JSONPath形式では面倒だった処理を、JSONataでは簡単に実現できました。これまで複数のステートを組み合わせたりLambda関数を挟んでいたような変換処理を記述できる、JSONataは非常に強力なツールです。

ぜひ使いこなしていきましょう!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.