概要
quicktype の Haskell 出力を実装しました。
https://github.com/quicktype/quicktype
quicktype の機能と使い方を紹介します。
quicktype とは
quicktype は JSON などのデータを入力として、各プログラミング言語から JSON を呼び出すコードとそのデータに対応する強い型付きのモデルを自動的に生成してくれるライブラリです。
ライブラリ本体は TypeScript で書かれています。
データからモデルを正しく生成するのは地味で面倒な単純作業が必要ですが、その手間を大幅に削減してくれます。
入力データ
JSON 以外の形式も入力データに使うことができます。
- JSON
- JSON Schema
- TypeScript
- GraphQL query
出力言語
Haskell の出力を今回実装しました。それ以外にも以下の言語やフォーマットに出力できます。
- Haskell (New!)
- Ruby
- JavaScript
- Flow
- Rust
- Kotlin
- Dart
- Python
- C#
- Go
- C++
- Java
- TypeScript
- Swift
- Objective-C
- Elm
- JSON Schema
- Pike
- Prop-Types
使い方
ここでは Web UI と CLI による2つの実行方法をそれぞれ紹介します。
Web UI
Web で quicktype の機能を試すことができます。
https://app.quicktype.io/
たとえば JSON データから Haskell のコードを生成したいとします。
- データ型の指定
画面左の "Source Type" に "JSON" を指定して、"Name" にトップレベルの名前を入力します。 - データの入力
JSON データを画面左下の項目に入力します。 - 出力フォーマットの指定
画面上のメニューで "Options" をクリックすると、右側に表示されるモーダルで "Language" で "Haskell" を選択します。
エラーがなければ画面右に Haskell のコードが生成されます。
入力データ (JSON)
{
"greeting": "Welcome to quicktype!",
"instructions": [
"Type or paste JSON here",
"Or choose a sample above",
"quicktype will generate code in your",
"chosen language to parse the sample data"
]
}
出力コード (Haskell)
{-# LANGUAGE StrictData #-}
{-# LANGUAGE OverloadedStrings #-}
module QuickType
( Welcome (..)
, decodeTopLevel
) where
import Data.Aeson
import Data.Aeson.Types (emptyObject)
import Data.ByteString.Lazy (ByteString)
import Data.HashMap.Strict (HashMap)
import Data.Text (Text)
import Data.Vector (Vector)
data Welcome = Welcome
{ greetingWelcome :: Text
, instructionsWelcome :: Vector Text
} deriving (Show)
decodeTopLevel :: ByteString -> Maybe Welcome
decodeTopLevel = decode
instance ToJSON Welcome where
toJSON (Welcome greetingWelcome instructionsWelcome) =
object
[ "greeting" .= greetingWelcome
, "instructions" .= instructionsWelcome
]
instance FromJSON Welcome where
parseJSON (Object v) = Welcome
<$> v .: "greeting"
<*> v .: "instructions"
CLI
コマンドラインでも quicktype を実行できます。
実行環境に node.js がインストールされているものとします。
- インストール
npm install -g quicktype
- 実行
echo '{ "hello": "Haskell" }' | quicktype -l haskell
オプション -l
で出力言語を指定します。
ファイル入力や JSON Schema (オプション -s
) による型の定義もできます。
詳しい使い方やその他のCLIオプションについては公式リポジトリのドキュメントを参照してください。
Haskell 版の実装の特徴
- Enum, Union, GraphQL にも対応した
他の一部の言語では対応していません。 -
Aeson を使って JSON に対応した
個人的によく使っているライブラリなので使うことにしました。型安全なモデルを作るという quicktype の思想にもあっているはずです。 -
Lens Aeson は使わなかった
Template Haskell を使って簡易に実装する方法も検討しましたが、例外的なデータに柔軟な対応ができなかったので今回は使いませんでした。もし需要があれば後から付け足すかもしれません。 -
StrictData言語拡張を使った
遅延評価によるパフォーマンス低下を防ぐために入れました(全部のフィールドに "!" をつけるのが面倒だった)
コメント
- Haskell 版は最初のバージョンで荒削りなので一部の例外的なデータ型を正しく出力できないことがあります。実装に対する疑問や改善は Issue や PR にして公式リポジトリに送ってください。レスポンスが早いのですぐに対応してくれると思います。