Override how Data.Aeson handles only one field of my record

一个人想着一个人 提交于 2019-12-08 04:46:33

问题


I am making a REST API for university courses:

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

instance FromJSON Course
instance ToJSON Course

I would like to allow deleted to be optional in the serialized JSON structure, but not in my application. I want to set deleted to False if it isn't specified when parsing.

I could write a manual instance for FromJSON, but I don't want to have to write it out for all the fields. I want to declare how deleted is handled and let the automatic instance handle everything else.

How would I do this?


回答1:


To my knowledge there is not a way to customize the generic instance, but you could structure your type a bit differently:

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

Now you can do

> 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"})

And now you can just optionally tag a course as deletable when you need it, and the FromJSON instances take care of everything.



来源:https://stackoverflow.com/questions/26259383/override-how-data-aeson-handles-only-one-field-of-my-record

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!