如何允许数组单个元素在保留其他元素的同时解析失败?
How can I allow array individual elements to fail parsing while retaining others?
我有一个 json 来源不正常。它经常提供意外的 JSON,其中包含格式错误的数组元素。我想解析这个 JSON 并忽略任何格式错误的数组元素。
这是我的尝试:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Applicative ((<$>), (<*>))
import Control.Monad (mzero)
import Data.Aeson
import Data.ByteString.Lazy.Char8 (ByteString, pack)
data Foo = Foo Integer [Maybe Bar] deriving (Show)
data Bar = Bar Integer Integer deriving (Show)
instance FromJSON Foo where
parseJSON (Object v) = Foo <$> (v .: "a") <*> (v .: "b")
parseJSON _ = mzero
instance FromJSON Bar where
parseJSON (Object v) = Bar <$> (v .: "c") <*> (v .: "d")
parseJSON _ = mzero
-- this string is malformed - second array element has an unexpected key
testString = pack "{\"a\":1, \"b\":[{\"c\":11, \"d\":12}, {\"C\":21, \"d\":22}, {\"c\":31, \"d\":32}]}"
-- want this to be:
--
-- Just (Foo 1 [Just (Bar 11 12),Nothing,Just (Bar 31 32)])
--
-- or
--
-- Just (Foo 1 [Just (Bar 11 12),Just (Bar 31 32)])
main = print $ (decode testString :: Maybe Foo)
当teststring
格式错误时,Foo
returnsNothing
的整体解码。我想 Foo
解析,但是 b
的任何格式错误的数组元素都是 Nothing
.
您不能依赖列表的默认实现 FromJSON
,您必须自己做更多的工作:
instance FromJSON Foo where
parseJSON (Object v) = do
a <- v .: "a"
bList <- v .: "b"
return $ Foo a $ map (parseMaybe parseJSON) bList
parseMaybe parseJSON
函数的类型为 FromJSON a => Value -> Maybe a
,因此 bList :: [Value]
表示 map (parseMaybe parseJSON) bList :: [Maybe Bar]
。考虑到 the documentation(参见 "Decoding a mixed-type object")使用类似的方法来解析表现不佳的 JSON,这可能是最好的解决方法。
我有一个 json 来源不正常。它经常提供意外的 JSON,其中包含格式错误的数组元素。我想解析这个 JSON 并忽略任何格式错误的数组元素。
这是我的尝试:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Applicative ((<$>), (<*>))
import Control.Monad (mzero)
import Data.Aeson
import Data.ByteString.Lazy.Char8 (ByteString, pack)
data Foo = Foo Integer [Maybe Bar] deriving (Show)
data Bar = Bar Integer Integer deriving (Show)
instance FromJSON Foo where
parseJSON (Object v) = Foo <$> (v .: "a") <*> (v .: "b")
parseJSON _ = mzero
instance FromJSON Bar where
parseJSON (Object v) = Bar <$> (v .: "c") <*> (v .: "d")
parseJSON _ = mzero
-- this string is malformed - second array element has an unexpected key
testString = pack "{\"a\":1, \"b\":[{\"c\":11, \"d\":12}, {\"C\":21, \"d\":22}, {\"c\":31, \"d\":32}]}"
-- want this to be:
--
-- Just (Foo 1 [Just (Bar 11 12),Nothing,Just (Bar 31 32)])
--
-- or
--
-- Just (Foo 1 [Just (Bar 11 12),Just (Bar 31 32)])
main = print $ (decode testString :: Maybe Foo)
当teststring
格式错误时,Foo
returnsNothing
的整体解码。我想 Foo
解析,但是 b
的任何格式错误的数组元素都是 Nothing
.
您不能依赖列表的默认实现 FromJSON
,您必须自己做更多的工作:
instance FromJSON Foo where
parseJSON (Object v) = do
a <- v .: "a"
bList <- v .: "b"
return $ Foo a $ map (parseMaybe parseJSON) bList
parseMaybe parseJSON
函数的类型为 FromJSON a => Value -> Maybe a
,因此 bList :: [Value]
表示 map (parseMaybe parseJSON) bList :: [Maybe Bar]
。考虑到 the documentation(参见 "Decoding a mixed-type object")使用类似的方法来解析表现不佳的 JSON,这可能是最好的解决方法。