我正在使用Data.Aeson将一些JSON解析为Record类型。有时会将数据添加到JSON中,这会破坏我的代码,因为Aeson抱怨了以下内容:
预期的对象21 名称/值对但有23个名称/值
我真的更愿意以容错的方式解析JSON - 我不在乎日后是否有更多的字段添加到JSON中,只需解析你能做的任何事情!有没有办法实现这种容错?这是我的代码:
myRecordFromJSONString :: BS.ByteString -> Maybe MyRecord
myRecordFromJSONString s = case Data.Attoparsec.parse json s of
Done _rest res -> Data.Aeson.Types.parseMaybe parseJSON res
_ -> Nothing
我应该补充说我正在使用Data.Aeson.TH中的deriveJSON来生成解析代码。如果我手动编写FromJSON代码,它是容错的,但我不想这样做......
答案 0 :(得分:6)
如果您使用的是GHC 7.2或7.4,则aeson
中的新通用支持不会检查额外的字段。我不确定这是否符合设计要求,但我们也是出于同样的原因使用它。
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import qualified Data.Aeson.Types
import Data.Attoparsec
import qualified Data.ByteString as BS
import Data.ByteString.Char8 ()
import GHC.Generics
data MyRecord = MyRecord
{ field1 :: Int
} deriving (Generic, Show)
instance FromJSON MyRecord
myRecordFromJSONString :: BS.ByteString -> Maybe MyRecord
myRecordFromJSONString s = case Data.Attoparsec.parse json s of
Done _rest res -> Data.Aeson.Types.parseMaybe parseJSON res
_ -> Nothing
main :: IO ()
main = do
let parsed = myRecordFromJSONString "{ \"field1\": 1, \"field2\": 2 }"
print parsed
由于记录中不存在“field2”,因此运行此操作会导致TH派生实例失败。 Generic
实例返回所需的结果:
Just (MyRecord {field1 = 1})