前回の更新からちょっと時間が空いてしまいました 💦
小ネタです。掲題の通りderiveJsonNoPrefixというパッケージをリリースしました。
地味に有用だと思うので、READMEをやや意訳気味に翻訳して記事にします。
十分に単純なので、仕様が変わることもまさかないでしょうし。
以下、こちらのコミットの時点のREADMEの翻訳です。
Link to
herederiveJsonNoPrefix
プレフィックスに優しいToJSON
とFromJSON
のインスタンスを定義するTemplate Haskellのマクロを提供します。
Link to
here例
こんな感じのJSONを作りたいとしましょう:
{
"id": "ID STRING",
"max": 0.789,
"min": 0.123
}
きっとToJSON(おそらくそれに加えてFromJSONも)のインスタンスを自動的に定義するための、次のようなレコード型を定義したくなるでしょう。
{-# LANGUAGE TemplateHaskell #-}
import Data.Aeson.TH
data SomeRecord = SomeRecord
id :: String
{ max :: Double
, min :: Double
,deriving (Eq, Show)
}
$(deriveToJSON defaultOptions ''SomeRecord)
しかし、こんなレコード型は定義すべきではありません。
id
もmax
もmin
も、Prelude
に定義済みなのですから!
この問題を回避するために、レコードラベルに型の名前をプレフィックスとして加える、ということをわれわれはよくやります。
data SomeRecord = SomeRecord
someRecordId :: String
{ someRecordMax :: Double
, someRecordMin :: Double
,deriving (Eq, Show) }
そして、deriveToJSON
にデフォルトと異なるオプションを渡して実行します。
= firstLower . drop (length "SomeRecord") } ''SomeRecord
deriveToJSON Json.defaultOptions { fieldLabelModifier
firstLower :: String -> String
:xs) = toLower x : xs
firstLower (x= error "firstLower: Assertion failed: empty string" firstLower _
fieldLabelModifier
オプションは文字通り、対象のレコードをJSONに変換するとき、あるいはJSONから対象のレコードの値に変換する時、レコードのラベルを変換する関数を設定するために使います。
👆の場合、プレフィックスであるSomeRecord
の文字数分レコードラベルからdrop
して、先頭の文字(someRecordId
で言えばId
のI
に相当します)を小文字に変換しているのがわかるでしょうか?
そう、これがderiveToJsonNoTypeNamePrefix
がやっていることとほぼ同等のことです。
deriveToJsonNoTypeNamePrefix
は、実質次のように定義されています。
deriveToJsonNoTypeNamePrefix :: Name -> Q [Dec]
=
deriveToJsonNoTypeNamePrefix deriver name = dropPrefix name } name
deriveToJSON Json.defaultOptions { fieldLabelModifier
dropPrefix :: Name -> String -> String
= firstLower . drop (length $ nameBase name)
dropPrefix name
firstLower :: String -> String
:xs) = toLower x : xs
firstLower (x= error "firstLower: Assertion failed: empty string" firstLower _
結果、これからはfieldLabelModifier
をもう自分で定義する必要がありません!🙌
import Data.Aeson.DeriveNoPrefix
$(deriveJsonNoTypeNamePrefix ''SomeRecord)
👆 のderiveJsonNoTypeNamePrefix
は deriveJSONと同様に、ToJSON
とFromJSON
のインスタンス、両方を生成します。
もちろん、FromJSON
のインスタンスを生成するときのオプションとしても、プレフィックスを削除するためのfieldLabelModifier
を渡してくれます!
Link to
here同じ問題を解決するほかのライブラリー
- extensible.
- など、
ToJSON
・FromJSON
のインスタンスが定義されたextensible recordを提供するライブラリー
なので、そうしたextensible recordを提供するライブラリーが学習コストや依存関係などの事情で「重たい」と感じたときにこのパッケージを使ってください。