2015-01-24 9 views
5

Diciamo che ho un tipo PersonAeson e lente con DeriveGeneric e makeLenses - nomi non si allineano

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

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

e voglio derivare automaticamente Lenti e typeclasses JSON per esso

makeLenses ''Person 
instance FromJSON Person 
instance ToJSON Person 

Funziona correttamente, tuttavia DeriveGeneric vede i miei nomi di campo con un trattino basso e si aspetta che il mio JSON sia formattato di conseguenza.

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

Ovviamente ho potuto Rimuovere tale definizione data stessa, ma poi makeLenses non sarebbe in grado di derivare i getter e setter richieste.

Idealmente quello che voglio essere in grado di fare è qualcosa di simile

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

cioè io voglio essere in grado di trarre le lenti e le istanze JSON con tutti i nomi dei campi allineando correttamente con i valori nella JSON- REST Api Sto consumando, senza dover scrivere molto standard.

Mi sembra una cosa così semplice che sento che mi manca qualcosa di ovvio?

risposta

8

Entrambe lens e aeson dispongono di funzioni per consentire la gestione personalizzabile dei nomi campo e costruttore. Dal momento che di default aeson s' non è ciò che si vuole, e non avrebbe funzionato in ogni caso se si desidera che i nomi delle lenti per essere lo stesso che i nomi dei campi JSON, cambiamo la configurazione 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} 
-} 

Per lens, il la corrispondente funzione configurabile sarebbe makeLensesWith.

+0

Funziona perfettamente, grazie :) –

Problemi correlati