我正在尝试从以下JSON输入中提取'path'键的第3个元素:
<dom-bind>
但是我在运行这个程序时得到的是“Nothing”:
{
"certname": "some.server.name",
"path": [
"networking",
"interfaces",
"eth0",
"bindings",
0,
"address"
],
"name": "networking",
"value": "192.168.1.1",
"environment": "develop"
}
评论{-# 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
是否可以将Aeson用于异构列表?我该怎么做呢?
答案 0 :(得分:3)
fmap (V.! 2) (o .: "path")
o .: "path"
此处必须包含Parser (Vector Text)
类型,但您提供的数组中包含数字。
相反,不要对数组进行解码,即在类型o .: "path"
处使用Parser Value
,然后通过模式匹配或使用withArray
显式地破坏该值。然后给出一个Array
(即,Vector Value
,这是异构的)你可以获得第二个元素(V.! 2)
并将其转换为Text
(通过模式匹配,{{1} },或withText
)。
parseJSON