2014-10-08 89 views
1

我正在爲大學課程REST API我的記錄只有一個字段:覆蓋Data.Aeson如何處理

data Course = Course { 
    id :: Maybe Text, 
    name :: Text, 
    deleted :: Bool 
} deriving(Show, Generic) 

instance FromJSON Course 
instance ToJSON Course 

我想允許deleted是在序列化JSON結構可選,但不是在我的應用程序。如果解析時沒有指定,我想將deleted設置爲False

我可以爲FromJSON寫一個手動實例,但我不想寫出所有的字段。我想聲明如何處理刪除,並讓自動實例處理其他所有內容。

我該怎麼做?

回答

2

據我所知,沒有自定義泛型實例的方式,但你可以組織你的類型有點不同:

data Course = Course 
    { courseId :: Maybe Text -- Don't use `id`, it's already a function 
    , name :: Text 
    } deriving (Show, Generic) 

data Deletable a = Deletable 
    { deleted :: Bool 
    , item :: a 
    } deriving (Show) 

instance FromJSON Course 
instance ToJSON Course 

instance FromJSON a => FromJSON (Deletable a) where 
    parseJSON (Object v) = do 
     i <- parseJSON (Object v) 
     d <- v .:? "deleted" .!= False 
     return $ Deletable d i 
    parseJSON _ = mzero 

現在你可以做

> let noDeleted = "{\"name\":\"Math\",\"courseId\":\"12345\"}" :: Text 
> let withDeleted = "{\"name\":\"Math\",\"courseId\":\"12345\",\"deleted\":true}" :: Text 

> decode noDeleted :: Maybe (Deletable Course) 
Just (Deletable {deleted = False, item = Course {courseId = Just "12345", name = "Math"}}) 

> decode noDeleted :: Maybe Course 
Just (Course {courseId = Just "12345", name = "Math"}) 

> decode withDeleted :: Maybe (Deletable Course) 
Just (Deletable {deleted = True, item = Course {courseId = Just "12345", name = "Math"}}) 

> decode withDeleted :: Maybe Course 
Just (Course {courseId = Just "12345", name = "Math"}) 

,現在你可以只需在需要時將課程標記爲可刪除,並且FromJSON實例負責處理所有內容。