8

私がタイプを持っているとしましょうPerson

import GHC.Generics
import Data.Text
import Data.Aeson
import Control.Lens

data Person = Person {
    _firstName :: Text,
    _lastName  :: Text,
    _age       :: Int
} deriving (Show, Generic)

そして、レンズと JSON 型クラスを自動的に派生させたい

makeLenses ''Person
instance FromJSON Person
instance ToJSON Person

これは正しく機能しますが、DeriveGeneric はフィールド名にアンダースコアが含まれていると見なし、JSON がそれに応じてフォーマットされることを期待します。

{ "_firstName": "James" ... etc} -- The underscore doesn't belong here.

明らかに、data定義自体からアンダースコアを削除makeLensesできますが、必要なゲッターとセッターを派生させることはできません。

理想的には、私ができるようになりたいのは、このようなものです

let person = decode blob
let name = person ^. firstName

つまり、使用している JSON-REST Api の値とすべてのフィールド名が正しく並んでいるレンズと JSON インスタンスを、多くのボイラープレートを記述することなく派生できるようにしたいと考えています。

これはとても簡単なことのように思えるので、明らかな何かが欠けていると感じますか?

4

1 に答える 1

16

との両方lensaeson、フィールド名とコンストラクタ名のカスタマイズ可能な処理を可能にする関数があります。aesonのデフォルトはあなたが望むものではなく、レンズ名を JSON フィールド名と同じにしたい場合はとにかく動作しないので、構成を変更しましょうaeson:

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TemplateHaskell #-}

import GHC.Generics
import Data.Text hiding (drop)
import Data.Aeson
import Data.Aeson.TH
import Data.Aeson.Types
import Control.Lens

data Person = Person {
    _firstName :: Text,
    _lastName  :: Text,
    _age       :: Int
} deriving (Show, Generic)

makeLenses ''Person

deriveJSON defaultOptions{fieldLabelModifier = drop 1} ''Person

{- alternative Generic version
instance FromJSON Person where
    parseJSON = genericParseJSON defaultOptions{fieldLabelModifier = drop 1}
instance ToJSON Person where
    toJSON = genericToJSON defaultOptions{fieldLabelModifier = drop 1}
-}

の場合lens、対応する構成可能な機能は になりますmakeLensesWith

于 2015-01-24T09:45:07.730 に答える