我正在为大学课程制作REST API:
data Course = Course {
id :: Maybe Text,
name :: Text,
deleted :: Bool
} deriving(Show, Generic)
instance FromJSON Course
instance ToJSON Course
我想允许deleted
在序列化的JSON结构中是可选的,但不是在我的应用程序中。如果在解析时未指定deleted
,我想将False
设置为FromJSON
。
我可以为{{1}}编写一个手动实例,但我不想为所有字段写出来。我想声明如何处理删除并让自动实例处理其他所有内容。
我该怎么做?
答案 0 :(得分: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
实例可以处理所有内容。