Aeson 解析器为数组字段返回 'Nothing'
Aeson Parser Returning 'Nothing' for Array field
我正在尝试从以下 JSON 输入中提取 'path' 键的第三个元素:
{
"certname": "some.server.name",
"path": [
"networking",
"interfaces",
"eth0",
"bindings",
0,
"address"
],
"name": "networking",
"value": "192.168.1.1",
"environment": "develop"
}
但我得到的只是 'Nothing' 当 运行 这个程序:
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad (mzero)
import Data.Aeson
import Data.ByteString.Lazy (ByteString)
import Data.Text
import qualified Data.Vector as V
data HostNicIp =
HostNicIp { hniHost :: !Text
, hniNic :: !Text
, hniIp :: !Text
} deriving Show
instance FromJSON HostNicIp where
parseJSON (Object o) =
HostNicIp
<$> (o .: "certname")
<*> fmap (V.! 2) (o .: "path")
<*> (o .: "value" )
parseJSON _ = mzero
main :: IO ()
main = print ( decode demo :: Maybe HostNicIp )
demo :: ByteString
demo = "{\"certname\":\"some.server.name\",\"path\":[\"networking\",\"interfaces\",\"eth0\",\"bindings\",0,\"address\"],\"name\":\"networking\",\"value\":\"192.168.1.1\",\"environment\":\"develop\"}"
注释 hniNic
及其相关逻辑使程序解析其他所有内容
编辑:
运行 这与 eitherDecode
使它抱怨遇到 Number
而不是 Text
*Main> eitherDecode demo :: Either String HostNicIp
Left "Error in $.path[4]: expected Text, encountered Number"
而原始 Object
似乎解析正常
*Main> eitherDecode demo :: Either String Object
Right (fromList [("certname",String "some.server.name"),("path",Array [String "networking",String "interfaces",String "eth0",String "bindings",Number 0.0,String "address"]),("environment",String "develop"),("value",String "192.168.1.1"),("name",String "networking")])
异构列表可以用Aeson吗?我该如何处理?
fmap (V.! 2) (o .: "path")
o .: "path"
这里必须有类型 Parser (Vector Text)
但你给的数组包含一个数字。
相反,不要解码数组,即在类型 Parser Value
处使用 o .: "path"
,然后通过模式匹配或使用 withArray
显式破坏值。然后给定一个 Array
(即 Vector Value
,它是异构的)你可以得到第二个元素 (V.! 2)
并将其转换为 Text
(通过模式匹配,用 withText
, 或者 parseJSON
).
(o .: "path") >>= withArray "Path info" (parseJSON . (V.! 2))
我正在尝试从以下 JSON 输入中提取 'path' 键的第三个元素:
{
"certname": "some.server.name",
"path": [
"networking",
"interfaces",
"eth0",
"bindings",
0,
"address"
],
"name": "networking",
"value": "192.168.1.1",
"environment": "develop"
}
但我得到的只是 'Nothing' 当 运行 这个程序:
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad (mzero)
import Data.Aeson
import Data.ByteString.Lazy (ByteString)
import Data.Text
import qualified Data.Vector as V
data HostNicIp =
HostNicIp { hniHost :: !Text
, hniNic :: !Text
, hniIp :: !Text
} deriving Show
instance FromJSON HostNicIp where
parseJSON (Object o) =
HostNicIp
<$> (o .: "certname")
<*> fmap (V.! 2) (o .: "path")
<*> (o .: "value" )
parseJSON _ = mzero
main :: IO ()
main = print ( decode demo :: Maybe HostNicIp )
demo :: ByteString
demo = "{\"certname\":\"some.server.name\",\"path\":[\"networking\",\"interfaces\",\"eth0\",\"bindings\",0,\"address\"],\"name\":\"networking\",\"value\":\"192.168.1.1\",\"environment\":\"develop\"}"
注释 hniNic
及其相关逻辑使程序解析其他所有内容
编辑:
运行 这与 eitherDecode
使它抱怨遇到 Number
而不是 Text
*Main> eitherDecode demo :: Either String HostNicIp
Left "Error in $.path[4]: expected Text, encountered Number"
而原始 Object
似乎解析正常
*Main> eitherDecode demo :: Either String Object
Right (fromList [("certname",String "some.server.name"),("path",Array [String "networking",String "interfaces",String "eth0",String "bindings",Number 0.0,String "address"]),("environment",String "develop"),("value",String "192.168.1.1"),("name",String "networking")])
异构列表可以用Aeson吗?我该如何处理?
fmap (V.! 2) (o .: "path")
o .: "path"
这里必须有类型 Parser (Vector Text)
但你给的数组包含一个数字。
相反,不要解码数组,即在类型 Parser Value
处使用 o .: "path"
,然后通过模式匹配或使用 withArray
显式破坏值。然后给定一个 Array
(即 Vector Value
,它是异构的)你可以得到第二个元素 (V.! 2)
并将其转换为 Text
(通过模式匹配,用 withText
, 或者 parseJSON
).
(o .: "path") >>= withArray "Path info" (parseJSON . (V.! 2))