json - 如何将 Text.JSON.Generic 与可选 JSON 字段一起使用?

标签 json haskell data-binding

是否可以将 Text.JSON.Generic 与包含可选字段的 JSON 记录类型一起使用?如果我将 Haskell 类型声明为 Maybe a,我希望这会“正常工作”,例如:

import Text.JSON.Generic

data Record = Record {
   myMandatoryField :: Integer,
   myOptionalField :: Maybe Integer
} deriving (Eq, Show, Data, Typeable)

但这并不正确。

如果无法使可选字段与 Text.JSON.Generic 一起使用,是否有替代的 Haskell-JSON 数据绑定(bind)库可以与可选字段一起使用?

最佳答案

这似乎是基于泛型解析的一个已知问题。 Aeson遇到了同样的问题,维护人员决定弃用该功能,转而支持基于模板 Haskell 的策略:https://github.com/bos/aeson/issues/118

使用 Aeson,您的代码看起来会非常相似:

import Data.Aeson
import Data.Aeson.TH

data Record = Record {
    myMandatoryField :: Integer,
    myOptionalField :: Maybe Integer
} deriving (Eq, Show)

$(deriveJSON id ''Record)

这样,Maybe 字段按预期进行编码和解码:

$ ghci
λ :l Main.hs
Ok, modules loaded: Main.
λ encode $ Record 5 Nothing
"{\"myOptionalField\":null,\"myMandatoryField\":5}"
λ decode it :: Maybe Record
Just (Record {myMandatoryField = 5, myOptionalField = Nothing})

更新:正如评论中提到的,在 Aeson HEAD 中的 Template Haskell 可以省略空字段,但这还没有在 Hackage 上。您现在可以通过手写的 FromJSON/ToJSON 实例来获得这种行为:

instance FromJSON Record where
    parseJSON = withObject "record" $ \o -> Record
        <$> o .: "myMandatoryField"
        <*> o .:? "myOptionalField"

instance ToJSON Record where
    toJSON (Record manf optf) = object $ catMaybes
        [ ("myMandatoryField" .=) <$> pure manf
        , ("myOptionalField" .=) <$> optf ]

关于json - 如何将 Text.JSON.Generic 与可选 JSON 字段一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18144364/

相关文章:

android-studio - Android Studio - 更新到 4.1 后启动时出现插件错误消息

javascript - 有没有更好的方法来遍历这个对象?

node.js - Docker 构建不使用 npm ci 的缓存

haskell - QuickCheck:为什么没有通过测试的功能以及改用什么功能?

haskell - 免费的 Monad Trans Control 实例

wpf - 是否有一组接口(interface)可以实现以避免在 WPF 绑定(bind)中有转换器

javascript - knockout 可观察字段不会在输入值更改时更新

ios - if语句ios检查json参数

javascript - 检查 json 树是否没有更多的 child

haskell - 如何让 ReaderT 与另一个 monad 转换器一起工作?