【发布时间】:2014-10-31 21:31:16
【问题描述】:
今天我想解决下一个问题。
假设我们将 typeclass DataWithDefault 定义为
class DataWithDefault a where
defaultValue :: a
我们将数据Example定义为
data Example =
Example { field1 :: Text
, field2 :: Text
} deriving (Show)
instance DataWithDefault Example where
defaultValue = Example "Hello" "World"
instance FromJSON Example where
parseJSON (Object v) =
Example <$> v .:? "field1" .!= field1 defaultValue
<*> v .:? "field2" .!= field2 defaultValue
parseJSON _ = mzero
instance ToJSON Example where
toJSON (Example f1 f2) =
object [ "field1" .= f1
, "field2" .= f2
]
我知道 Aeson 使用泛型自动派生 FromJSON 和 ToJSON 实例,但我不知道如何让它派生 FromJSON 实例,并为给定 json 中未表示的字段提供默认值。可以使用泛型吗?其实我没有问你最终的解决方案,但也许有一些线索?
更新
让我添加有关该问题的更多信息。
现在假设您需要更新您的 Example 数据,现在它定义为
data Example =
Example { field1 :: Text
, field2 :: Text
, field3 :: Int
} deriving (Show)
所以你想更新DataWithDefault 实例声明
instance DataWithDefault Example where
defaultValue = Example "Hello" "World" 12
而我想做的就是不写
instance FromJSON Example where
parseJSON (Object v) =
Example <$> v .:? "field1" .!= field1 defaultValue
<*> v .:? "field2" .!= field2 defaultValue
<*> v .:? "field3" .!= field3 defaultValue
parseJSON _ = mzero
并希望自动派生这样的实例定义。更重要的是,我不仅要为Example 这样做,还要为DataWithDefault a 这样做。
更新 2
结合.:? 和.!= 的目的是从给定的json 中获取尽可能多的字段,并将每个缺失的字段设置为其默认值。所以当我们通过
{ "field1" : "space", "field2" : "ship" }
我希望我的新示例不是field1 = Hello; field2 = World; field3 = 12,而是field1 = space; field2 = ship; field3 = 12。
【问题讨论】:
-
你不能
fromMaybe defaultValue $ decode jsonContents吗? -
如果您正在创建自己的类型类,您可以考虑使用
Data.Default来获取大量结构的实例