読者です 読者をやめる 読者になる 読者になる

F# のJSON事情

F#

現時点でF#のJSON事情をぱっと思い出せなかったので、知っている範囲でメモしておくことにします。

あらかじめ断っておくと、私見にまみれているかつ抜けているライブラリがあるかもしれません。

DataContractJsonSerializer

標準にあるやつ。 当然ながらF#のいくつかの型には対応していない(意図しない出力になったりエラーになったり?)。

一つのプロジェクトに閉じていて他のライブラリを使うまでもないくらい小さいJSONを扱いたい時に使える? FSDNはまさにそんなJSONだったのでこいつを採用しています。

*** 追記

拡張を用意してあげればもちろんF#の型も対応できます(ただ拡張ライブラリ入れるなら別のライブラリを選ぶ…)。

余談

Suave本体に含まれているSuave.Jsonモジュールは内部でDataContractJsonSerializerを使っています。 例外はmapJsonWith関数で、こいつはdeserializeとserialize用の関数を渡す形になっています。 つまり、Suaveで他のJSONライブラリを使いたいならmapJsonWithを用いて各ライブラリの関数を作るか、直接そのライブラリを使うかになります。 まぁ、mapJsonWithを使わない場合もライブラリの入れ替えが楽になるようにオレオレJsonモジュールを作るのが良いと思います。

Json.NET

http://www.newtonsoft.com/json

.NETでJSONといえばこれでしょ、みたいなやつです。 いろんなライブラリ、フレームワークがこいつを使っているので必然利用頻度が高まります。

素の状態でF#の型をシリアライズすると望んだものでないデータが出来上がるので注意が必要です。

個人的なあれをいうと、こいつを使う場合はclassや.NET標準のデータ型のみで型を定義しますね。 F#用の拡張を用意するのは面倒だし、かといって他のライブラリがメンテナンスされているかというとうーん…となりやすいので。 レコードやlist、その他もろもろを使わない覚悟が必要になりますが、まぁAPI用の型と内部で使う型って別物になりがちなので入口出口くらいしかきにならないというか。

FSharpLu.Json

https://www.nuget.org/packages/Microsoft.FSharpLu.Json/

珍しくMicrosoft organizationに存在するF#プロジェクトでJson.NETに依存しています。 存在感は薄い。

Newtonsoft.Json.FSharp

https://github.com/haf/Newtonsoft.Json.FSharp

SuaveコミッターのHenrik Feldtさん作……ですがdescriptionに以下の注意書きがあります。

I recommend using Chiron instead of Newtonsoft

どうやら後述するChiron推しのようです。 使う機会はないでしょう。

Chiron

https://github.com/xyncro/chiron

HaskellのAeson的なライブラリです。 Lensがおまけでついてきます。

そっち系に慣れている人は(アプリカティブスタイルも使えるので)使いやすいかもしれませんが、慣れない人は敬遠しそうな感じ。

FSharp.Data

https://github.com/fsharp/FSharp.Data

TypeProviderの例としてよく知られているやつですね。 型を自動生成してくれるのはこいつくらいじゃないでしょうか(JSONは往々にして自動生成が役立つことってあまりない気もしますが…)。

解析向けに使うには強いけどAPIに使うには向かない印象を私は持っています(あくまで個人の感想です)。

FsPickler.Json(番外)

https://www.nuget.org/packages/FsPickler.Json/

機能がモリモリなバイナリシリアライザのFsPicklerのJSONプラグイン的なやつ。 JSONライブラリというわけではないので番外扱い。

ドキュメントに以下の記載があります。

FsPickler is NOT:

  • a general-purpose XML/JSON/BSON framework.
  • a library designed for cross-platform communication.
  • a library designed with version tolerance in mind. Avoid using for long-term persistence.

まぁ、そりゃそうですよね。

パフォーマンス

知らぬ。

いや、重要なのは理解しているのですがよっぽど遅くない限りは速度気にならない部分でしか使わない…真面目に速度が必要ならバイナリシリアライザを使うからなぁ。

真面目に使うつもりの人は計測しましょう。

まとめてきな何か

正直、SuaveでJSON APIを組み立てる時にいつもライブラリ選定に悩まされます。 どれも一長一短あるし、他の言語を触っている身としては「auto deriveしつついい感じに使わせてくれ〜」みたいな気分になるわけですよ。

一応個人的な使い分けを書いておくと

  • Chiron
    • 個人的な慣れの問題で使う
  • FSharp.Data
    • Readerしか必要ない時
  • Json.NET
    • 他のライブラリがこれに依存している時は問答無用で採用
    • 同じプロジェクトで複数のJSONライブラリを使いたくない
  • DataContractJsonSerializer
    • 上記を使うことすら億劫なとき

こんな感じですかねぇ。

結局F#でもJSONライブラリは氾濫しているのでした…つらい。