Posted at

Node-redのJSONata事例 ~ある配列の値を使って、別配列中のObjectを処理する~(ボツネタだけど動くよ)


概要

Node-redのJSONata式のボツネタだけど事例なので載せます。


背景

・HTMLフォームから最大3つの画像(URLかファイルで、1、2、3とナンバリングされる)を受け取りたい。

・ユーザーはラジオボタンでURLかファイルを選択する。

・ユーザーは一度ファイルをブラウザ上で指定した後に「やっぱURLで」と気が変わったらURLを指定してSubmitできる。

→この場合に、ラジオボタンの選択内容と実際にPOSTで受け取るファイルの個数がずれる場合が出てくる可能性があるので、要らないデータは保存したく無い!というのがやりたい事。


さて

(色々すっ飛ばして、)以下の様なmsg.req.filesmsg.msgsが存在する。

{

"req":{
"files":[
{
"fieldname": "msg_1_img_file",
"originalname": "hogehoge.png",
"encoding": "7bit",
"mimetype": "image/png",
"size": 60708
}
]},
"msgs": [
{
"index": 0,
"type": "image",
"imgtype": "url",
"img": {
"url": "http://hogehoge.com/"
},
"text": ""
},
{
"index": 1,
"type": "image",
"imgtype": "file",
"img": {
"url": ""
},
"text": ""
},
{
"index": 2,
"type": "text",
"imgtype": "url",
"img": {
"url": ""
},
"text": ""
}
]
}

msg.req.filesはPOSTでブラウザから渡された画像が入ってくる。(ここではbufferは省略)

msg.msgsには、背景でいうところのラジオボタンの値(imgtype)が入っている。


JSONata

これらを使って、msg.msgsでファイル形式としてユーザーがUpしてきたファイルのみをmsg.payloadにコピーしたい。

(
$filenames := $map(
$.msgs[
type="image" and imgtype="file"
] ,
function($v,$i,$a){
"msg_" & $v.index & "_img_file"
}
);

$map(
$filenames,
function($v,$i,$a){
$.req.files[ fieldname = $v ]
}
);
)


解説

最初のfilenamesは、msg.req.files配列の中のfieldnameに存在するはずの名前を配列として作成する。

そして、そのfilenamesの配列でmapをかけて、それがmsg.req.filesにある場合はそれが配列として戻る様にする。


ボツの理由

1、HTML側でラジオボタンを操作した時に、片方の中身を消してしまう方が良くね?

2、仮にこの方式でやった場合に、データ保存した後にそのID/URLをどうやって正しい場所に入れるかを考えるのがまためんどくさい

3、というかmsg.req.filesを使ってsplitした方が一回に一つのファイルしか評価しなくて良いからシンプルなんじゃね?


以上です

という事で、サラッと書いたので万人向けの優しい記事では無いですが、node-redのJSONataの事例として上げておきました。