今天我想解决下一个问题。
假设我们将 typeclassDataWithDefault定义为
class DataWithDefault a where
defaultValue :: a
Run Code Online (Sandbox Code Playgroud)
我们将数据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
]
Run Code Online (Sandbox Code Playgroud)
我知道 Aeson 使用泛型来自动派生FromJSON和ToJSON实例化,但我无法弄清楚如何让它派生FromJSON实例,并为给定 json 中未表示的字段使用默认值。是否可以使用泛型?其实我不问你最终的解决方案,但也许是一些线索?
更新
让我添加有关该问题的更多信息。
假设现在你需要更新你的Example数据,现在它定义为
data Example =
Example { field1 :: Text
, field2 :: Text
, field3 :: Int
} deriving (Show)
Run Code Online (Sandbox Code Playgroud)
所以你想更新DataWithDefault实例声明
instance DataWithDefault Example where
defaultValue = Example "Hello" "World" 12
Run Code Online (Sandbox Code Playgroud)
而我想做的不是写
instance FromJSON Example where
parseJSON (Object v) =
Example <$> v .:? "field1" .!= field1 defaultValue
<*> v .:? "field2" .!= field2 defaultValue
<*> v .:? "field3" .!= field3 defaultValue
parseJSON _ = mzero
Run Code Online (Sandbox Code Playgroud)
并且想自动导出这样的实例定义。更重要的是,我不仅要为Example,还要为DataWithDefault a.
更新 2
结合.:?and 的目的.!=是从给定的 json 中获取尽可能多的字段,并将每个缺失的字段设置为其默认值。所以当我们通过
{ "field1" : "space", "field2" : "ship" }
Run Code Online (Sandbox Code Playgroud)
我希望我的新示例不是field1 = Hello; field2 = World; field3 = 12,而是field1 = space; field2 = ship; field3 = 12。
不要让 Aeson 这样做,只需使用新类型来实现它们的设计目的:
newtype DefaultJSON a = DefaultJSON { unDefaultJSON :: a }
instance (FromJSON a, DataWithDefault a) => FromJSON (DefaultJSON a) where
parseJSON v = DefaultJSON <$> (parseJSON v <|> pure defaultValue)
Run Code Online (Sandbox Code Playgroud)
然后你可以做
> decode "{}" :: Maybe (DefaultJSON Example)
Just (DefaultJSON {unDefaultJSON = (Example {field1 = "Hello", field2 = "World"}})
Run Code Online (Sandbox Code Playgroud)
这与您所要求的有点不同,它提供了一个默认值以防解析失败,但不是每个字段的默认值以防单个字段丢失。
| 归档时间: |
|
| 查看次数: |
760 次 |
| 最近记录: |