带有数组数组的 Aeson,其中一些是空的
Aeson with arrays of arrays, of which some are empty
我有不幸的数据要处理:
{ "name": "foo"
, "data": [ []
, ["a", "b", "c", 1]
, ["d", "e", "f", 2] ] }
数据条目可以是空数组,也可以是大小为 4 的数组。
我想解析成:
data ResultRow = ResultRow Text Text Text Int deriving (Show, Generic)
data ResultSet =
ResultSet { f_name :: Text
, f_data :: [Maybe ResultRow] } deriving (Show, Generic)
但是以下不接受空数组:
customOptions = defaultOptions { fieldLabelModifier = drop 2 }
instance FromJSON ResultRow where
parseJSON = genericParseJSON customOptions
instance FromJSON ResultSet where
parseJSON = genericParseJSON customOptions
错误信息是:
Left "Error in $[1].data[0]: When expecting a product of 4 values, encountered an Array of 0 elements instead"
我还尝试在 [Maybe ResultRow]
周围放置一个额外的类型,并将子数组转换为列表并在 []
上进行模式匹配,并将非空情况分派给 ResultRow
解析器,但我无法编译它并迷失在错误消息中。
理想情况下,我希望有一些方法可以跳过空数组,因为它们只是数据中的噪音。我无法控制数据的生产者。
就像 dsvensson,我很困惑这不是 'just work' 开箱即用,因为 [a]
和 Maybe a
是 FromJSON
个实例,而 a
是。因为我已经在这上面花了太多时间,所以我无法提供 解释 ,但我可以提供解决方法。希望有知识的人能给出更好的答案。
您可以定义一个包含 Maybe ResultRow
:
的 newtype
,而不是将 f_data
定义为 [Maybe ResultRow]
newtype MaybeResultRow = MaybeResultRow (Maybe ResultRow) deriving (Show, Generic)
你可以给这个类型特殊的FromJSON
行为:
instance FromJSON MaybeResultRow where
parseJSON v =
case fromJSON v of
Success rr -> return $ MaybeResultRow $ Just rr
_ -> return $ MaybeResultRow Nothing
这显然意味着 ResultSet
的变化:
data ResultSet =
ResultSet { f_name :: Text
, f_data :: [MaybeResultRow] } deriving (Show, Generic)
为了测试,我定义了这个JSON文档:
myJson :: ByteString
myJson =
"{\
\"name\": \"foo\",\
\"data\": [\
\[],\
\[\"a\", \"b\", \"c\", 1],\
\[\"d\", \"e\", \"f\", 2]\
\]\
\}"
正在将其全部加载到 GHCi 中,看起来它正在运行:
*Lib Lib> decode myJson :: Maybe ResultSet
Just (ResultSet {
f_name = "foo"
, f_data = [
MaybeResultRow Nothing,
MaybeResultRow (Just (ResultRow "a" "b" "c" 1)),
MaybeResultRow (Just (ResultRow "d" "e" "f" 2))]})
在这里,我冒昧地格式化了 GHCi 的输出以提高可读性。
我相信您能弄清楚如何展开和过滤 MaybeResultRow
个值的列表...
我从.
偷走了使用fromJSON
和在Success
上匹配的解决方案
我有不幸的数据要处理:
{ "name": "foo"
, "data": [ []
, ["a", "b", "c", 1]
, ["d", "e", "f", 2] ] }
数据条目可以是空数组,也可以是大小为 4 的数组。
我想解析成:
data ResultRow = ResultRow Text Text Text Int deriving (Show, Generic)
data ResultSet =
ResultSet { f_name :: Text
, f_data :: [Maybe ResultRow] } deriving (Show, Generic)
但是以下不接受空数组:
customOptions = defaultOptions { fieldLabelModifier = drop 2 }
instance FromJSON ResultRow where
parseJSON = genericParseJSON customOptions
instance FromJSON ResultSet where
parseJSON = genericParseJSON customOptions
错误信息是:
Left "Error in $[1].data[0]: When expecting a product of 4 values, encountered an Array of 0 elements instead"
我还尝试在 [Maybe ResultRow]
周围放置一个额外的类型,并将子数组转换为列表并在 []
上进行模式匹配,并将非空情况分派给 ResultRow
解析器,但我无法编译它并迷失在错误消息中。
理想情况下,我希望有一些方法可以跳过空数组,因为它们只是数据中的噪音。我无法控制数据的生产者。
就像 dsvensson,我很困惑这不是 'just work' 开箱即用,因为 [a]
和 Maybe a
是 FromJSON
个实例,而 a
是。因为我已经在这上面花了太多时间,所以我无法提供 解释 ,但我可以提供解决方法。希望有知识的人能给出更好的答案。
您可以定义一个包含 Maybe ResultRow
:
newtype
,而不是将 f_data
定义为 [Maybe ResultRow]
newtype MaybeResultRow = MaybeResultRow (Maybe ResultRow) deriving (Show, Generic)
你可以给这个类型特殊的FromJSON
行为:
instance FromJSON MaybeResultRow where
parseJSON v =
case fromJSON v of
Success rr -> return $ MaybeResultRow $ Just rr
_ -> return $ MaybeResultRow Nothing
这显然意味着 ResultSet
的变化:
data ResultSet =
ResultSet { f_name :: Text
, f_data :: [MaybeResultRow] } deriving (Show, Generic)
为了测试,我定义了这个JSON文档:
myJson :: ByteString
myJson =
"{\
\"name\": \"foo\",\
\"data\": [\
\[],\
\[\"a\", \"b\", \"c\", 1],\
\[\"d\", \"e\", \"f\", 2]\
\]\
\}"
正在将其全部加载到 GHCi 中,看起来它正在运行:
*Lib Lib> decode myJson :: Maybe ResultSet
Just (ResultSet {
f_name = "foo"
, f_data = [
MaybeResultRow Nothing,
MaybeResultRow (Just (ResultRow "a" "b" "c" 1)),
MaybeResultRow (Just (ResultRow "d" "e" "f" 2))]})
在这里,我冒昧地格式化了 GHCi 的输出以提高可读性。
我相信您能弄清楚如何展开和过滤 MaybeResultRow
个值的列表...
我从
fromJSON
和在Success
上匹配的解决方案