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

jch*_*chl 3 data-binding json haskell

是否可以使用Text.JSON.Generic包含可选字段的JSON记录类型?我希望如果我宣布Haskell类型为"只是工作" Maybe a,例如:

import Text.JSON.Generic

data Record = Record {
   myMandatoryField :: Integer,
   myOptionalField :: Maybe Integer
} deriving (Eq, Show, Data, Typeable)
Run Code Online (Sandbox Code Playgroud)

但这不是正确的事情.

如果无法使用可选字段Text.JSON.Generic,是否有可选的Haskell-JSON数据绑定库可以使用可选字段?

Mik*_*aig 7

这似乎是基于泛型的解析的已知问题.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)
Run Code Online (Sandbox Code Playgroud)

这样,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})
Run Code Online (Sandbox Code Playgroud)

更新:正如评论中所提到的,在Aeson HEAD中,模板Haskell可以使用null-field omission,但是还没有在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 ]
Run Code Online (Sandbox Code Playgroud)