SML#のJSONサポートについては[Ohori et al., ECOOP'16]に詳しく書かれているので,読んで試してみました.
今回はSML# 3.2.0を使用しました.
パース
json.smiに定義されているJSONストラクチャのimport関数は,JSON文字列をパースして,型付きJSONを計算します.
val json = JSON.import "[1, 2]"
型付きJSONの値であるjsonはJSON.void JSON.dynという謎の型を持っていて,このままだと使えません.
使いやすい型に変換
_json e as τという構文を使うことで,型τに変換することができます.
型τに変換可能かどうかは動的にチェックされます.
val list = _json JSON.import "[1, 2]" as int list;
val record = _json JSON.import "{\"foo\": 1, \"bar\": \"2\"}" as { foo: int, bar: string };
val heterogeneousList = _json JSON.import "[42, \"57\"]" as JSON.void JSON.dyn list;
val a = _json List.nth (heterogeneousList, 0) as int;
val b = _json List.nth (heterogeneousList, 1) as string;
heterogeneousなリストも扱うことができています.
パターンマッチ
_jsoncase e of jp1 => e1 | · · · | jpn => enという構文を使うことで,型付きJSONの値に対してパターンマッチを行うことができます.
val heterogeneousList = _json JSON.import "[{\"pi\": 3.141592, \"grothendieck\": 57}, \"42\"]" as JSON.void JSON.dyn list;
val result = map (fn x => _jsoncase x of
{pi : real, grothendieck : int} => Real.toString pi ^ " " ^ Int.toString grothendieck
| str : string => str
| _ => "")
heterogeneousList;
まとめ
型の恩恵を受けつついい感じにJSONを処理できます.
とても良い.