kintoneアプリでJSONファイルを作りたい

こんにちは、キン担ラボの本橋です。

この記事はkintoneアドベントカレンダーの12/8の記事です。

https://qiita.com/advent-calendar/2024/kintone


社内業務のいろんなところにkintoneを適用し始めると、「みなさんに入力してもらいやすいアプリ」と「欲しい結果」との繋ぎこみに頭を楽しませたくなることがあります。

kintoneの良いところの一つは人間が入力する時点で文字列や数値といった書式が定めておける点です。この特徴があるため、集まった入力データをあとから集計する場面が格段に楽になります。

たとえば金額を千単位で区切るカンマに文字列でカンマが入っていて集計できなかったり、なぜか漢数字で入っていたり、単位の文字が入っていたりと、多くの人間から入力を求めようとするとありがちな罠です。

解決策はkintoneに限りませんが、この手の問題を解決できことは多くの方に知っておいていただきたいですね。

さて、もう一歩踏み込みます。

# kintoneアプリの入力から構造化文書を構築したい

kintoneで文字フォーマットの問題が楽になると、次は構造を持たせたくなります。構造といえばツリー構造です。ツリー構造は階層構造（親子関係）とリスト構造（兄弟関係）を持ちます。

- 親子関係
    - HTMLではタグの入れ子で表現
- 兄弟関係
    - HTMLではタグの並列で表現

HTMLやJSONでは親子も兄弟も表現できています。

kintoneではどこまで表現できるでしょうか？

こういった構造化文書はソフトウェアの設定ファイルなどでよく使われます。この記事の『JSONファイルを作りたい』は、そんなソフトウェアの設定ファイルをkintoneから作りたいと挑戦した結果です。

最初にお断りさせていただくと、kintone単体の標準機能だけで作れるJSONは限定的な親子関係までです。兄弟関係を持ったJSONは作れません。そういうことをやりたいがために作った拙作のkinToysというChrome拡張とのコンビネーションで解決して行きます。

https://kintoys.app/

作成するJSONとしては、⇩の記事で作成したvonage用のNCCOという書式のJSONです。

https://note.com/motohasystem/n/n56aa37a29c61

構造としてはシンプルですが、親子関係と兄弟関係は両方とも備えています。

それではお付き合いください。

# シンプルなJSON: 計算機能で親子関係を作る

まずは計算機能だけでどこまで出来るか挑戦してみました。文字列やラジオボタン、チェックボックスなどから取り出したテキストを並べるというところまでならできそうです。

やってみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13915/62a1603e-a2f3-4b02-e2a4-bdec6d007870.png)

このあたりが限界でした。actionはドロップダウン、textは一行文字列、styleは数値で指定します。

計算機能を使って、jsonフィールドにjson文字列を作り出しています。計算式の中にダブルクオートを使えないので、dqというフィールドを作って参照しました。

### 親子関係

親子関係の表現としては、inputアクションとrecordアクションに持たせるプロパティとしてのinput_optionとrecord_optionというフィールドをあらかじめ定義しておくことにしました。

条件分岐は一行文字列フィールドの中で処理しています。行がrecordアクションを持っているとき、optionsにはrecord_optionフィールドの値が取り込まれます。inputアクションを持っているときはinput_optionですね。

### 兄弟関係

兄弟関係を作ろうとするとループが必要です。kintoneではサブテーブルを使います。

しかしサブテーブルから情報を取り出そうとすると、SUM関数で数値を合計するか、CONTAINS関数で単語の存在をチェックするかのどちらかです。CONTAINSを駆使すればある程度は取り出せるかもしれませんが、あんまり現実的ではありません。

仕方がないので、兄弟の数だけフィールドを並べることで実現しました。数を増やすには新しくフィールドを配置するしかなく、こちらもなかなかの無理矢理感です。

『シンプルなJSON』の挑戦はここまでとしておきます。この先はkintoneのフィールドかあるいはサブテーブルから取り出す新しい関数が追加される未来を待ちたいと思います。

### 計算式

一行文字列の計算機能で無理やりJSONを作るとこうなりました、という例です。JSONの中に登場する"の数だけdqフィールドを参照しています。

> "[  {    " & dq & "action" & dq & ": " & dq & action_01 & dq & ",    " & dq & "text" & dq & ": " & dq & text_01 & dq & ",    " & dq & "language" & dq & ": " & dq & "ja-JP" & dq & ",    " & dq & "style" & dq & ": " & dq & style_01 & dq & "  },  {    " & dq & "action" & dq & ": " & dq & action_02 & dq & ",    " & dq & "text" & dq & ": " & dq & text_02 & dq & ",    " & dq & "language" & dq & ": " & dq & "ja-JP" & dq & ",    " & dq & "style" & dq & ": " & dq & style_02 & dq & "  },  {    " & dq & "action" & dq & ": " & dq & action_03 & dq & ",    " & dq & "text" & dq & ": " & dq & text_03 & dq & ",    " & dq & "language" & dq & ": " & dq & "ja-JP" & dq & ",    " & dq & "style" & dq & ": " & dq & style_03 & dq & "  }]"

強引ですが計算結果としてJSONが取り出せました。


### 取り出したJSONを見る

上の計算式で組み上げたJSONを成形したものがこちらです。JSONの構造を持たせることには成功しています。

```
[
  {
    "action": "talk",
    "text": "こんにちは、vonageサンプルです",
    "language": "ja-JP",
    "style": "1"
  },
  {
    "action": "input",
    "text": "折り返しが必要な方は数字の1を押してください",
    "language": "ja-JP",
    "style": "1"
  },
  {
    "action": "record",
    "text": "発信音の後にメッセージをお話しください。",
    "language": "ja-JP",
    "style": "1"
  }
]
```

dqフィールドとか作り始めたあたりで『何やってんだろう』といったん正気には戻っています。大丈夫です。


# 複雑なJSON: カスタマイズで兄弟関係を作る

計算機能でJSONをつくろうとすると、親子関係は作れても兄弟関係が作れないという限界がありました。

その限界の大きな理由としては、kintoneの計算式ではループが表現できないことでした。ループから情報を取り出すには計算式ではなく、外部からカスタマイズを加える必要があります。

そこでカスタマイズを利用して、テーブルに詰め込んだフィールドから情報を取り出してみます。

JSON構築部分をカスタマイズに任せられるので、アプリ自体はシンプルにできました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13915/cbe25e8f-9eee-7b72-8efd-58079e6dc1c9.png)

行を増やせるようになって自由にactionを増やせます。

### 親子関係

シンプルなJSONの場合と同じく、親子関係はテキストフィールドを参照する形で行っています。親子関係の階層を増やしたいときも、親子関係を持った複数のテーブルを組み合わせることで実現できるかと思います。

### 兄弟関係

このあと紹介するkinToysのテンプレートを使うことでサブテーブルからループで情報を取り出せるようになり、兄弟関係の問題も解決しました。シンプルなJSONのときのようにアプリにフィールドを追加する必要はもうありません。


### kinToysでテーブルから情報を取り出す

ここでは、こういう場面で使いたくて開発した拙作のchrome拡張『kinToys』を使います。

https://chromewebstore.google.com/detail/kintoys/johmoplafihagepgbceblbhlmacejoee

他にもjavascriptカスタマイズを書いたり、プラグインを開発したり、他の連携機能を使ったりといろんな手段で取り出すことはできるかと思います。

kinToysのテンプレート機能を使うとフィールドの情報をテンプレートのプレースホルダと置換する形で取り出すことができます。プレースホルダはテーブルにも対応しているので、構造化文書の形で情報を取り出せます。

### テンプレートのループ記法

kinToysのテンプレートでは以下の記述でテーブルから情報を取り出せます。

table / action / text / joint がそれぞれkintoneアプリのフィールドコードです。

```
[
%table{
  {
    "action": "%action%",
    "text": "%text%"
  } %joint%
}%
]
```

> %fieldcode{

から始まって

> }%

までがテーブルを表しています。その間に挟んだテンプレートをレコードが持っているテーブルの行数分だけ繰り返してテンプレート化します。

### jointセパレータ

このとき問題になるのが兄弟関係を示すためのカンマです。JSONでは兄弟関係のカンマは最後の行だけ不要です。条件分岐で表示非表示を切り替えたいところでしたが、kinToys側のテンプレートには条件分岐を持たせていません。

そこでテーブルの行にjointというフィールドを持たせて、これを兄弟のセパレータとしました。あんまりスマートではない気がしますが、最後の行だけセパレータを空欄にすることでなんとかJSON構文に従えるという苦肉の策です。

### 取り出したJSONを見る

kinToysの[グラブコピー](https://kintoys.app/usage.html)という機能を使うことでテンプレートを適用して、以下のようなJSONをクリップボードに取り出すことができました。（kinToysはクリップボードがメインの出力先です）

```
[
  {
    "action": "talk",
    "text": "こんにちは、kintoneサンプルです",
    "language": "ja-JP",
    "style": "2"
  } ,
  {
    "action": "talk",
    "text": "こんなふうにおしゃべりできます",
    "language": "ja-JP",
    "style": "3"
  } ,
  {
    "action": "talk",
    "text": "いろいろな音声を喋らせて遊んでください。",
    "language": "ja-JP",
    "style": "4"
  } 
]
```

今回作成したJSONは実際にvonageのAPIから呼び出せる形でホスティングすることによって、電話の自動応答をさせることができます。

JSONのホスティングについては[Vonageアドベントカレンダー](https://qiita.com/advent-calendar/2024/vonage)の12/1に書かせていただいた記事で紹介しています。

https://qiita.com/motohasystem/items/f00ab5be02fb90cffb05

最後まで読んでいただき、ありがとうございました！