🔄 Node-RED Changeノード ガイド

このガイドでは、Node-REDのChangeノードについて、初心者の方でも理解できるように詳しく説明します。

📚 1. Changeノードとは?

🤔 「Change」って何?

Changeノードは、メッセージのプロパティを変更・設定・削除・移動するノードです。 日常生活で例えると、郵便物の宛名書き換えや転送サービスのようなものです。

📮 郵便局の仕分け作業に例えると:

📦 基本的な動作

Inject Change Debug

Changeノードは、入力メッセージを受け取り、指定したルールに従って プロパティを変更して出力します。 Functionノードを使わずに、シンプルなデータ操作が可能です。

入力
msg.payload = 1702345678901
(タイムスタンプ)
↓ Change ↓
出力
msg.payload = "Hello World!"
(文字列に変更)

⚙️ 2. Changeノードの4つの操作

Set 値の代入

プロパティに新しい値を設定

msg.payload = "Hello World!" msg.topic = "greeting"

Change 値の置換

文字列の一部を検索して置換

"Hello" → "Hi" 正規表現も使用可能

Delete 値の削除

プロパティを完全に削除

delete msg.payload delete msg._msgid

Move 値の移動

プロパティを別の場所に移動

msg.topic → msg.payload (元のtopicは削除される)

📋 設定項目一覧

設定項目 説明 使用例
操作タイプ Set/Change/Delete/Moveから選択 代入、置換、削除、移動
対象プロパティ 操作対象のプロパティを指定 msg.payload, flow.count
プロパティタイプ msg/flow/global から選択 メッセージ、フロー変数、グローバル変数
設定する値(Setの場合) "Hello", 123, true
値のタイプ 値の型を指定 文字列、数値、JSONata等
検索文字列 置換対象(Changeの場合) "old", /pattern/g
置換文字列 置換後の値(Changeの場合) "new"
移動先 移動先プロパティ(Moveの場合) msg.data, msg.result

🎯 値のタイプ一覧

Changeノードの「Set」操作では、様々なタイプの値を設定できます。

タイプ 説明
str 文字列 "Hello World!"
num 数値 123, 3.14
bool 真偽値 true, false
JSON JSONオブジェクト {"name": "Alice", "age": 30}
msg. 他のmsgプロパティの値 msg.topic, msg.payload.name
flow. フローコンテキスト変数 flow.count, flow.config
global. グローバルコンテキスト変数 global.settings
env 環境変数 HOME, NODE_ENV
JSONata JSONata式で動的に計算 payload & ", World!"

🎯 3. 実用的な使用パターン

📥 サンプルフローのインポート方法:

  1. 下のサンプルフローJSONをコピー
  2. Node-REDエディタで メニュー → 読み込み を選択
  3. JSONをペーストして「読み込み」をクリック

このサンプルフローには、以下で説明する全パターンの実例が含まれています。

📋 サンプルフロー(クリックで展開)

参照元:NodeREDエディター内サンプルフロー

[ { "id": "9feb177422142bb3", "type": "tab", "label": "change", "disabled": false, "info": "", "env": [] }, { "id": "87bd706a.aec93", "type": "comment", "z": "9feb177422142bb3", "name": "Set message property to a fixed value", "info": "Change node can set value to message payload.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/set-message-property-fixed).", "x": 270, "y": 120, "wires": [] }, { "id": "ac4c748f.fd1bc8", "type": "inject", "z": "9feb177422142bb3", "name": "", "repeat": "", "crontab": "", "once": false, "topic": "", "payload": "", "payloadType": "date", "x": 240, "y": 180, "wires": [ [ "67974c84.7ca2c4" ] ] }, { "id": "67974c84.7ca2c4", "type": "change", "z": "9feb177422142bb3", "name": "", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "Hello World!", "tot": "str" } ], "onlyset": false, "x": 440, "y": 180, "wires": [ [ "6b23a342.86d9cc" ] ] }, { "id": "6b23a342.86d9cc", "type": "debug", "z": "9feb177422142bb3", "name": "", "active": true, "console": "false", "complete": "false", "x": 650, "y": 180, "wires": [] }, { "id": "26e7643f.13ebcc", "type": "comment", "z": "9feb177422142bb3", "name": "Set any property value", "info": "Change node can set value to any message property.", "x": 220, "y": 280, "wires": [] }, { "id": "4da2494d.9aff68", "type": "inject", "z": "9feb177422142bb3", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 240, "y": 340, "wires": [ [ "5111e689.62e838" ] ] }, { "id": "58ea5868.0596e8", "type": "debug", "z": "9feb177422142bb3", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 590, "y": 340, "wires": [] }, { "id": "5111e689.62e838", "type": "change", "z": "9feb177422142bb3", "name": "set payload & topic", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "Hello, World!", "tot": "str" }, { "t": "set", "p": "topic", "pt": "msg", "to": "Title", "tot": "str" } ], "onlyset": false, "x": 420, "y": 340, "wires": [ [ "58ea5868.0596e8" ] ] }, { "id": "a9039cda.3649e", "type": "comment", "z": "9feb177422142bb3", "name": "Set value using JSONata", "info": "Change node can set value to using JSONata expression.", "x": 230, "y": 440, "wires": [] }, { "id": "bdcdd579.cfe668", "type": "inject", "z": "9feb177422142bb3", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 240, "y": 500, "wires": [ [ "28d110a7.ce3e2" ] ] }, { "id": "c6677fa5.8c111", "type": "debug", "z": "9feb177422142bb3", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 590, "y": 500, "wires": [] }, { "id": "28d110a7.ce3e2", "type": "change", "z": "9feb177422142bb3", "name": "use JSONata", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "Hello", "tot": "str" }, { "t": "set", "p": "payload", "pt": "msg", "to": "payload & \", World!\"", "tot": "jsonata" } ], "onlyset": false, "x": 400, "y": 500, "wires": [ [ "c6677fa5.8c111" ] ] }, { "id": "e9143349.a64f7", "type": "comment", "z": "9feb177422142bb3", "name": "Set value from environment variable", "info": "Change node can set value from environment variable.", "x": 260, "y": 600, "wires": [] }, { "id": "a7c2725.a631f9", "type": "inject", "z": "9feb177422142bb3", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 240, "y": 660, "wires": [ [ "e455c302.2f795" ] ] }, { "id": "6f203119.21895", "type": "debug", "z": "9feb177422142bb3", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 590, "y": 660, "wires": [] }, { "id": "e455c302.2f795", "type": "change", "z": "9feb177422142bb3", "name": "set env var", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "HOME", "tot": "env" } ], "onlyset": false, "x": 400, "y": 660, "wires": [ [ "6f203119.21895" ] ] }, { "id": "6ecac54d.c43ffc", "type": "comment", "z": "9feb177422142bb3", "name": "Set flow context", "info": "Change node can set flow context.", "x": 200, "y": 760, "wires": [] }, { "id": "80e966d3.9d7a78", "type": "inject", "z": "9feb177422142bb3", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 260, "y": 934, "wires": [ [ "abaee298.2d77e" ] ] }, { "id": "60ab671d.b0bbf8", "type": "debug", "z": "9feb177422142bb3", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 630, "y": 934, "wires": [] }, { "id": "abaee298.2d77e", "type": "change", "z": "9feb177422142bb3", "name": "increment count", "rules": [ { "t": "set", "p": "count", "pt": "flow", "to": "$flowContext(\"count\")+1", "tot": "jsonata" }, { "t": "set", "p": "payload", "pt": "msg", "to": "count", "tot": "flow" } ], "onlyset": false, "x": 440, "y": 934, "wires": [ [ "60ab671d.b0bbf8" ] ] }, { "id": "2de2bb38.f20ff4", "type": "inject", "z": "9feb177422142bb3", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 260, "y": 840, "wires": [ [ "7b96521e.a3cb0c" ] ] }, { "id": "597b63cd.b3218c", "type": "debug", "z": "9feb177422142bb3", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 630, "y": 840, "wires": [] }, { "id": "7b96521e.a3cb0c", "type": "change", "z": "9feb177422142bb3", "name": "set count to 0", "rules": [ { "t": "set", "p": "count", "pt": "flow", "to": "0", "tot": "num" }, { "t": "set", "p": "payload", "pt": "msg", "to": "count", "tot": "flow" } ], "onlyset": false, "x": 440, "y": 840, "wires": [ [ "597b63cd.b3218c" ] ] }, { "id": "3d8cdc6d.2620e4", "type": "comment", "z": "9feb177422142bb3", "name": "↑ Initialize", "info": "", "x": 260, "y": 800, "wires": [] }, { "id": "d8069121.80de7", "type": "comment", "z": "9feb177422142bb3", "name": "↑ Count up", "info": "", "x": 260, "y": 894, "wires": [] }, { "id": "670fff8d.c60e2", "type": "comment", "z": "9feb177422142bb3", "name": "Delete message property", "info": "Change node can delete a message property.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/delete-message-property).", "x": 230, "y": 1020, "wires": [] }, { "id": "6708b393.04895c", "type": "inject", "z": "9feb177422142bb3", "name": "", "repeat": "", "crontab": "", "once": false, "topic": "", "payload": "", "payloadType": "date", "x": 240, "y": 1080, "wires": [ [ "d8757f71.765a9" ] ] }, { "id": "d8757f71.765a9", "type": "change", "z": "9feb177422142bb3", "name": "", "rules": [ { "t": "delete", "p": "payload", "pt": "msg" } ], "onlyset": false, "x": 450, "y": 1080, "wires": [ [ "20c077b.e11c188" ] ] }, { "id": "20c077b.e11c188", "type": "debug", "z": "9feb177422142bb3", "name": "", "active": true, "console": "false", "complete": "false", "x": 650, "y": 1080, "wires": [] }, { "id": "6e779a3b.4fdc24", "type": "comment", "z": "9feb177422142bb3", "name": "Move message property", "info": "Change node can move a message property to a different property.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/move-message-property).", "x": 230, "y": 1180, "wires": [] }, { "id": "bae6cb28.2ac588", "type": "inject", "z": "9feb177422142bb3", "name": "", "repeat": "", "crontab": "", "once": false, "topic": "Hello", "payload": "", "payloadType": "date", "x": 260, "y": 1240, "wires": [ [ "436d3311.248cdc" ] ] }, { "id": "436d3311.248cdc", "type": "change", "z": "9feb177422142bb3", "name": "", "rules": [ { "t": "move", "p": "topic", "pt": "msg", "to": "payload", "tot": "msg" } ], "onlyset": false, "x": 460, "y": 1240, "wires": [ [ "7865b104.64061" ] ] }, { "id": "7865b104.64061", "type": "debug", "z": "9feb177422142bb3", "name": "", "active": true, "console": "false", "complete": "false", "x": 650, "y": 1240, "wires": [] } ]

パターン1: 固定値の設定(Set)

用途: メッセージのプロパティに固定の値を設定

Inject Change
(Set)
Debug

📌 動作の流れ:

  1. Injectノードがタイムスタンプを送信
  2. Changeノードでmsg.payloadを "Hello World!" に書き換え
  3. Debugノードで "Hello World!" が表示

設定例:

ルール: 値の代入 対象: msg.payload 値: "Hello World!" (文字列) 入力: msg.payload = 1702345678901 出力: msg.payload = "Hello World!"

パターン2: 複数プロパティの同時設定

用途: 1つのChangeノードで複数のプロパティを一度に設定

Inject Change
(2ルール)
Debug
(完全msg)

設定例:

ルール1: msg.payload = "Hello, World!" (文字列) ルール2: msg.topic = "Title" (文字列) 出力: msg.payload = "Hello, World!" msg.topic = "Title"

パターン3: JSONata式での動的設定

用途: 既存の値を加工して新しい値を設定

Inject Change
(JSONata)
Debug

📌 JSONataの活用例:

設定例:

ルール1: msg.payload = "Hello" (文字列) ルール2: msg.payload = payload & ", World!" (JSONata) 処理: "Hello" + ", World!" 出力: msg.payload = "Hello, World!"

パターン4: 環境変数の取得

用途: システムの環境変数をメッセージに設定

Inject Change
(env)
Debug

設定例:

ルール: 値の代入 対象: msg.payload 値: HOME (環境変数) 出力: msg.payload = "/home/pi" (Raspberry Piの場合)

パターン5: フローコンテキストの操作

用途: フロー内で共有する変数の設定・参照

初期化 Change
(count=0)
Debug

カウント Change
(count+1)
Debug

📌 カウンターの実装:

  1. 初期化: flow.count を 0 に設定
  2. カウントアップ: JSONataで $flowContext("count")+1
  3. 結果をmsg.payloadに代入して出力

設定例(初期化):

ルール1: flow.count = 0 (数値) ルール2: msg.payload = flow.count 出力: msg.payload = 0

設定例(カウントアップ):

ルール1: flow.count = $flowContext("count")+1 (JSONata) ルール2: msg.payload = flow.count 出力: msg.payload = 1, 2, 3, ... (クリックごとに増加)

パターン6: プロパティの削除(Delete)

用途: 不要なプロパティをメッセージから削除

Inject Change
(Delete)
Debug
(完全msg)

設定例:

ルール: 削除 対象: msg.payload 入力: msg = {payload: 1702345678901, topic: "", _msgid: "xxx"} 出力: msg = {topic: "", _msgid: "xxx"} (payloadが消える)

パターン7: プロパティの移動(Move)

用途: プロパティを別の場所に移動(元は削除される)

Inject
(topic="Hello")
Change
(Move)
Debug

設定例:

ルール: 移動 移動元: msg.topic 移動先: msg.payload 入力: msg.topic = "Hello", msg.payload = 1702345678901 出力: msg.payload = "Hello" (topicは削除される)

🏋️ 4. 実践演習

演習1: 基本的な値の設定初級

📝 課題:

ChangeノードでJSONオブジェクトをmsg.payloadに設定してください。

🎯 要求仕様:

📊 期待される動作:

✅ 成功の条件:

💡 ヒント

Injectノードの設定:

  • payload: タイムスタンプ(デフォルト)でOK

Changeノードの設定:

  • ルール: 値の代入(Set)
  • 対象: msg.payload
  • 値のタイプ: JSON
  • 値: {"name": "Alice", "age": 25}

Debugノードの設定:

  • 出力: msg.payload
✅ 解答例フロー
[ { "id": "ex1_inject", "type": "inject", "name": "実行", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 110, "y": 100, "wires": [["ex1_change"]] }, { "id": "ex1_change", "type": "change", "name": "JSONを設定", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "{\"name\": \"Alice\", \"age\": 25}", "tot": "json" } ], "onlyset": false, "x": 280, "y": 100, "wires": [["ex1_debug"]] }, { "id": "ex1_debug", "type": "debug", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 450, "y": 100, "wires": [] } ]

演習2: ネストしたプロパティの設定中級

📝 課題:

JSONオブジェクトの一部のプロパティだけを変更してください。

🎯 要求仕様:

📊 期待される動作:

✅ 成功の条件:

💡 ヒント

1つ目のChangeノードの設定:

  • ルール: 値の代入(Set)
  • 対象: msg.payload
  • 値のタイプ: JSON
  • 値: {"sensor": {"temp": 0, "humidity": 0}}

2つ目のChangeノードの設定:

  • ルール: 値の代入(Set)
  • 対象: msg.payload.sensor.temp(ネストしたパス)
  • 値のタイプ: 数値
  • 値: 25
✅ 解答例フロー
[ { "id": "ex2_inject", "type": "inject", "name": "実行", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 110, "y": 100, "wires": [["ex2_change1"]] }, { "id": "ex2_change1", "type": "change", "name": "基本JSON設定", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "{\"sensor\": {\"temp\": 0, \"humidity\": 0}}", "tot": "json" } ], "onlyset": false, "x": 280, "y": 100, "wires": [["ex2_change2"]] }, { "id": "ex2_change2", "type": "change", "name": "temp変更", "rules": [ { "t": "set", "p": "payload.sensor.temp", "pt": "msg", "to": "25", "tot": "num" } ], "onlyset": false, "x": 460, "y": 100, "wires": [["ex2_debug"]] }, { "id": "ex2_debug", "type": "debug", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 610, "y": 100, "wires": [] } ]

演習3: 文字列の置換(Change操作)中級

📝 課題:

メッセージ内の文字列を検索して置換してください。

🎯 要求仕様:

📊 期待される動作:

✅ 成功の条件:

💡 ヒント

Injectノードの設定:

  • payload: 文字列型
  • 値: Hello, Node-RED!

Changeノードの設定:

  • ルール: 置換(Change)
  • 対象: msg.payload
  • 検索: Node-RED
  • 置換: World
  • 正規表現: オフ
✅ 解答例フロー
[ { "id": "ex3_inject", "type": "inject", "name": "テスト文字列", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Hello, Node-RED!", "payloadType": "str", "x": 140, "y": 100, "wires": [["ex3_change"]] }, { "id": "ex3_change", "type": "change", "name": "文字列置換", "rules": [ { "t": "change", "p": "payload", "pt": "msg", "from": "Node-RED", "fromt": "str", "to": "World", "tot": "str" } ], "onlyset": false, "x": 320, "y": 100, "wires": [["ex3_debug"]] }, { "id": "ex3_debug", "type": "debug", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 490, "y": 100, "wires": [] } ]

演習4: センサーデータの整形上級

📝 課題:

複数のルールを組み合わせて、センサーデータを整形してください。

🎯 要求仕様:

📊 期待される動作:

✅ 成功の条件:

💡 ヒント

Injectノードの設定:

  • payload: JSON型
  • 値: {"raw_temp": 2550, "raw_humidity": 650}

Changeノードの設定(複数ルール):

  • ルール1: msg.payload.temp = payload.raw_temp / 100 (JSONata)
  • ルール2: msg.payload.humidity = payload.raw_humidity / 10 (JSONata)
  • ルール3: msg.payload.raw_temp を削除
  • ルール4: msg.payload.raw_humidity を削除
  • ルール5: msg.payload.timestamp = $now() (JSONata)

JSONata式のポイント:

  • 計算: payload.raw_temp / 100
  • 現在時刻: $now()
✅ 解答例フロー
[ { "id": "ex4_inject", "type": "inject", "name": "センサー生データ", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "{\"raw_temp\": 2550, \"raw_humidity\": 650}", "payloadType": "json", "x": 150, "y": 100, "wires": [["ex4_change"]] }, { "id": "ex4_change", "type": "change", "name": "データ整形", "rules": [ { "t": "set", "p": "payload.temp", "pt": "msg", "to": "payload.raw_temp / 100", "tot": "jsonata" }, { "t": "set", "p": "payload.humidity", "pt": "msg", "to": "payload.raw_humidity / 10", "tot": "jsonata" }, { "t": "delete", "p": "payload.raw_temp", "pt": "msg" }, { "t": "delete", "p": "payload.raw_humidity", "pt": "msg" }, { "t": "set", "p": "payload.timestamp", "pt": "msg", "to": "$now()", "tot": "jsonata" } ], "onlyset": false, "x": 360, "y": 100, "wires": [["ex4_debug"]] }, { "id": "ex4_debug", "type": "debug", "name": "整形結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 530, "y": 100, "wires": [] } ]

🎓 5. まとめ

Changeノードの重要ポイント

⚠️ よくある間違い

📚 次のステップ

Changeノードをマスターしたら、以下のノードも学んでみましょう:

🔧 6. トラブルシューティング

よくある問題と解決方法

問題 原因 解決方法
値が設定されない プロパティパスの誤り msg.を含めた完全なパスを確認
JSONataでエラー 構文エラー JSONataエディタ(J:アイコン)で検証
数値計算ができない 値が文字列になっている 値タイプを「数値」に変更、または$number()で変換
置換が動作しない 大文字小文字の違い 正規表現で /pattern/i を使用
flow変数が取得できない 初期化されていない デフォルト値を設定、または初期化フローを作成
ネストしたプロパティが作れない 親オブジェクトが存在しない 先に親オブジェクトを作成してから子を設定

💡 7. 実務での活用例

ケース1: MQTTメッセージの整形

MQTTで受信: "25.5,65,1013" (CSV形式) ↓ Changeノードで整形: msg.payload = { "temperature": 最初の値, "humidity": 2番目の値, "pressure": 3番目の値, "device_id": msg.topic, "timestamp": $now() } ↓ データベースに保存 or ダッシュボードに表示

ケース2: API応答の加工

HTTP Request → 大量のJSONデータを受信 ↓ Changeノード: 1. 必要なフィールドだけ抽出 (Set) 2. 不要なフィールドを削除 (Delete) 3. フィールド名を変更 (Move) 4. 単位変換 (JSONata) ↓ 軽量化されたデータを次の処理へ

ケース3: Raspberry Piセンサーデータの処理

GPIOノード → 生のセンサー値 (0-4095) ↓ Changeノード: 1. ADC値を実際の電圧に変換 (JSONata: payload * 3.3 / 4095) 2. 電圧を温度に変換 (JSONata: 変換式) 3. キャリブレーション値を適用 (flow変数から取得) 4. アラート閾値チェック用のフラグを追加 ↓ ダッシュボード表示 + アラート処理

ケース4: ユーザー設定の管理

Webフォームから設定受信 ↓ Changeノード: 1. global.settings に設定を保存 2. 検証済みフラグを追加 3. 更新日時を記録 ↓ 別のフロー: global.settings を参照して動作を変更 (再起動しても設定が維持される)

📖 8. JSONata活用テクニック

JSONata は、JSONデータを変換・問い合わせするための軽量な式言語です。Changeノードの値タイプで 「J:」(JSONata式) を選択すると、動的な値の計算やデータ変換を1つのルールで実現できます。

JSONataの基本ルール:

以下では、このサイトの各ノードガイドの演習問題で実際に使われているJSONata式をカテゴリ別に紹介します。

8.1 文字列操作

関数 / 演算子 説明 実用例 使用箇所
&(結合) 文字列を連結する演算子。+ ではなく & を使う "処理済: " & payload Commentガイド演習2、UDPガイド演習2
$string() 数値やその他の型を文字列に変換する payload.host & ":" & $string(payload.port) YAMLガイド演習3、Watchガイド演習3、Splitガイド演習3、Debugガイド演習3
$uppercase() 文字列をすべて大文字に変換する $uppercase(payload) Splitガイド演習4
$trim() 文字列の前後の空白・改行を除去する $trim(payload) Execガイド演習2
$join() 配列の要素を結合して1つの文字列にする $join(['テストメール送信時刻: ', $now()]) Emailガイド演習1
文字列結合のポイント: JSONataでは文字列結合に + ではなく & を使います。+ は数値の加算専用です。数値を文字列に結合する場合は $string() で明示的に変換してください。

例: topic & ": " & $string(payload) & "円"Splitガイド演習3で使用)

8.2 数値計算

関数 / 演算子 説明 実用例 使用箇所
四則演算
+ - * /
加算・減算・乗算・除算 payload.raw_temp / 100 本ガイド演習4
$floor() 小数点以下を切り捨てて整数にする $floor($random() * 40 + 20) Dashboard2 Layoutガイドサンプル
$random() 0以上1未満のランダムな数値を返す $floor($random() * 100) Dashboard2 Layoutガイドサンプル
$round() 指定した桁数に四捨五入する $round(payload, 1) Sortガイド演習
$count() 配列の要素数を返す $count(payload.users) YAMLガイド演習4
ランダム整数の生成パターン: $floor($random() * N) で0からN-1のランダム整数を生成できます。テストデータの生成に便利です。

例: $floor($random() * 30 + 10) → 10から39のランダム整数

8.3 日時関数

$now() は現在の日時を返す関数です。オプションでフォーマットパターンを指定できます。

出力例 使用箇所
$now() 2024-12-16T10:30:00.000Z 本ガイド演習4
$now('[Y0001]-[M01]-[D01]') 2024-12-16 (参考)
$now('[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01].[f001]Z') 2024-12-16T10:30:00.000Z Watchガイド演習3
$now('[D01]/[M01]/[Y0001] [H01]:[m01]') 16/12/2024 10:30 (参考)
フォーマットパターンの記号: [Y0001]=年4桁、[M01]=月2桁、[D01]=日2桁、[H01]=時2桁、[m01]=分2桁、[s01]=秒2桁、[f001]=ミリ秒3桁

8.4 オブジェクト操作

パターン 説明 実用例 使用箇所
オブジェクト構築 新しいオブジェクトを組み立てる {"host": payload.database.primary.host, "port": payload.database.primary.port} YAMLガイド演習3、XMLガイド演習3
ネストアクセス 深い階層のプロパティにドットでアクセス payload.database.primary.host YAMLガイド演習3
バッククォート 特殊文字を含むプロパティ名をエスケープ payload.item.`$`.id XMLガイド演習3
XMLノードとバッククォート: XMLノードの出力では、属性は $、テキストコンテンツは _ というプロパティ名に格納されます。JSONataでこれらにアクセスするには、バッククォート(`)で囲む必要があります。

例: {"id": payload.item.`$`.id, "name": payload.item.name[0], "price": payload.item.price[0].`_`}
XMLガイド演習3で使用)

8.5 配列操作

パターン 説明 実用例 使用箇所
フィルタリング 条件に合う要素だけを抽出する payload.users[role="admin"].name YAMLガイド演習4
プロパティ抽出 配列の各要素から特定のプロパティを取り出す payload.users.name YAMLガイド演習4
$append() 配列に要素を追加する $append($A, [payload]) Joinガイドサンプル
配列フィルタリングの構文: 配列[条件] で条件に合う要素を抽出し、.プロパティ名 を続けることで特定のフィールドだけを取り出せます。SQLの SELECT name FROM users WHERE role = 'admin' に近い感覚で使えます。

8.6 コンテキスト・環境変数

関数 説明 実用例
$flowContext("変数名") フローコンテキストの値を取得 $flowContext("count") + 1
$globalContext("変数名") グローバルコンテキストの値を取得 $globalContext("config")
$env("変数名") 環境変数の値を取得 $env("API_KEY")
使い分け: Changeノードの「Set」ルールでは、対象に flow.変数名global.変数名 を直接指定する方法もあります。$flowContext() などの関数は、JSONata式の中で他の計算と組み合わせたい場合に使います(例: $flowContext("count") + 1)。

8.7 条件式

パターン 説明 実用例
三項演算子 条件に応じて異なる値を返す payload > 30 ? "高温" : "正常"
複合条件 and / or で複数条件を組み合わせ payload >= 20 and payload <= 30 ? "適温" : "注意"
SwitchノードとJSONata条件式の使い分け: 単純な条件分岐(メッセージを振り分ける)には Switchノード が適しています。JSONataの条件式は、1つのChangeノード内で値を動的に切り替えたい場合に便利です。

8.8 よく使うパターン早見表

やりたいこと JSONata式
文字列を結合する "prefix: " & payload
数値を文字列にする $string(payload)
大文字に変換する $uppercase(payload)
空白を除去する $trim(payload)
現在時刻を取得する $now()
小数を切り捨てる $floor(payload)
四捨五入する $round(payload, 2)
ランダムな整数を生成する $floor($random() * 100)
配列の要素数を数える $count(payload)
配列を条件で絞り込む payload[price > 1000]
新しいオブジェクトを作る {"key1": payload.a, "key2": payload.b}
条件で値を切り替える payload > 30 ? "高" : "低"
フロー変数を参照する $flowContext("変数名")

🔗 9. 追加リソース


このガイドが役に立ちましたら、実際のプロジェクトで練習してみてください!
Changeノードはフローの中で最もよく使われる基本ノードの一つです。

参照元:NodeREDエディター内サンプルフロー

🏠