2015-01-24 4 views
5

Lasst uns sagen, dass ich einen Typ haben PersonAeson und Lens mit DeriveGeneric und makeLenses - Namen Linie nicht bis

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

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

Und ich möchte automatisch ableiten Objektive und JSON typeclasses es

makeLenses ''Person 
instance FromJSON Person 
instance ToJSON Person 

Das funktioniert korrekt, aber DeriveGeneric sieht meine Feldnamen mit einem Unterstrich und erwartet, dass mein JSON entsprechend formatiert ist.

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

Offensichtlich kann ich den Unterstrich vom data Definition selbst entfernen, aber dann makeLenses nicht in der Lage sein, die erforderlichen Getter und Setter abzuleiten.

Im Idealfall, was ich möchte in der Lage sein zu tun, so etwas wie diese

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

dh ich mag in der Lage sein, Linsen und JSON Instanzen abzuleiten mit allen Feldnamen korrekt mit den Werten in den JSON- Schlange REST Api Ich verzehre, ohne viel Text schreiben zu müssen.

Das scheint so eine direkte Sache zu sein, dass ich fühle, dass ich etwas Offensichtliches vermisse?

Antwort

8

Sowohl lens als auch aeson verfügen über Funktionen, die eine anpassbare Bearbeitung von Feld- und Konstruktornamen ermöglichen. Da aeson ‚s Standard ist nicht das, was Sie wollen, und würde sowieso nicht funktionieren, wenn Sie die Linse Namen wollen die gleichen wie die JSON Feldnamen sein, lassen Sie uns die aeson Konfiguration ändern:

{-# 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} 
-} 

Für lens, die entsprechende konfigurierbare Funktion wäre makeLensesWith.

+0

Funktioniert perfekt, danke :) –