jsonの差分には規格がある

2023-06-23

はじめに

こんにちは。株式会社 Belong で Data Platform チーム所属の taketsuru です。

Data Platform チームに配属されるもキャッチアップの日々で部内における新規アウトプットが乏しく、今回は前職でのお話です。

今回は json 差分の規格と、当時の活用例についてです。

Data 文脈なのといずれ使えるかなという思いからこちらに投稿させていただきます。

ネタについては新しい(且つ部内で新規性のある)やつを見つけないと枯渇してしまいそうな危機感を抱えています。

json 差分の規格とは

json はデータのシリアライズ及び受け渡しによく使われます。

差分を取ること自体もたまにあるかと思われます。

しかし規格まで必要か?というのが当時の自分の考えでした。

大体の場合必要な差分は都度実装で

  • 特定のキーの値が変わっているか
  • 特定の配列の要素の増減、変更があるか

程度で充分だと思います。

ただ、上記において共通しているのは特定のという prefix です。

つまり不定形の json の差分を全てリストアップしたい、というのがニーズになります。

当然ですが収集側の独自規格だと活用側が困ります。

どんな規格なんですか

RFC6902 JSON patchになります。

json の差分を json で表現するというものです。

例えば以下 2 つの json の差分を考えます。

{
  "foo": "bar",
  "bar": [0, 1]
}
{
  "foo": "bar",
  "bar": [0, 1, 2],
  "baz": "qux"
}

この差分を表現する json は以下のようになります。

[
  { "op": "add", "path": "/bar/2", "value": 2 },
  { "op": "add", "path": "/baz", "value": "qux" }
]

opは操作の種類を表し、pathは操作対象の json のパスを表します。

json のネストが深くなると path が伸びていくイメージです。

今回は要素が増えた例(op:add)を挙げましたが、他にも

  • キーの削除:remove
  • キーの変更:move
  • 値の変更:replace
  • 値の複製:copy

などがあります。

規格だと何が嬉しいんですか

誰かがライブラリを実装してくれるところです(他力本願)。

これ割と重要で、特定のライブラリ/言語に依存しないで済むというのは大きいです。

あとは規格があるということは、その規格に準拠していれば他のライブラリ/言語でも同じように動くということです。

既存のコードへの組み込みや用途に応じた言語選択などに効果を発揮します。

またライブラリごとの readme を熟読しなくていいのも嬉しいです。

私が使用していた時は差分取得はpython、差分適応はブラウザ上でjavascript(nuxt)のライブラリを使用して実装していました。

当時の需要

当時の自分が直面したのは将来どう扱うか何の方針もないiot機器のログをとりあえず溜めておくでした。

何の方針もないけどとりあえず溜めておかないとデータが消失するので良くない。

しかし都度都度フルで取得するとデータサイズが大きいし検索もしにくい。

なんか無いかなと探していたら json 差分の規格を見つけました。

どう扱っていたのか

機器からのログは json で送られてきました。

変更前の状態と変更後の状態がそれぞれ json でインフラ層に送られてくる仕様です。

機器のファームウェア更新によってキーの増減があったりします。

この時差分を取って集約、クラウドストレージに流し込んでいました。

必要に応じて BigQuery で検索する運用です。

長所と短所

長所は、上記に挙げたデータサイズ以外にも以下があります。

  • 履歴として使いやすい
    • 特定の機器に対する差分 json を時系列に表示するだけで履歴になる
    • 非エンジニア向けには簡単な日本語に変換するだけでいい
      • keyaddされました、的な
  • json のフォーマットに依存していないので仕様変更に強い
    • 機器側(データソース側)の更新にインフラ層が連動しなくて良い
    • 一度仕組みを作れば手間がかからない(超重要)

欠点としては長所の裏返しの他に以下です。

  • スナップショットとしては使いにくい
    • スナップショットとしての参照が多いのであれば不向きかと思います
  • 特定の値を持つものの検索がしにくい
    • SQL(BigQuery)において json 型を扱う関数は複雑になりがち

履歴としての運用が最初の用途であったため簡単に解決できました。

これを RDBMS でやろうとしたら

  • 変化のないカラムまで毎回保存
  • 履歴表示の際に前後のレコードとの比較が必要
  • json の形状変更に伴うスキーマの変更が発生

などなど結構大変だったはずです。

ちょっと話がそれますが、クラウドストレージ -> BigQuery の形とすることで RDBMS のお世話もしなくて済みました。

この辺は社内向け(リクエストはごく僅か、レスポンス速度にも寛容)であるという前提も出てきます。

まとめ

json の差分の規格と活用例について執筆させていただきました。

database にも向き不向きがあるので、データ構造や用途に合わせて使い分けを考えるのが楽しいと感じています。

単に楽しいだけでなく適切な選択をすればパフォーマンス向上やコスト削減にも繋がります。

ただ用途が変わったりすることはあり得るのであまりに依存した実装も避けるバランス感が難しいですね。

弊社 Belong では一緒にサービスを育てる仲間を募集しています。 もし弊社に興味を持っていただけたら https://entrancebook.belonginc.dev/ をご覧いただけたら幸いです。