我在決議表單中的 JSON 文本時遇到問題
{
"Person1": {
"name": "John Doe",
"job" : "Accountant",
"id": 123
},
"Person2": {
"name": "Jane Doe",
"job" : "Secretary",
"id": 321
}}
我定義了一個新的資料型別如下
data Person = Person
{ name :: String
, job :: String
, id :: Int } deriving Show
FromJSON但是在這種情況下我無法定義一個實體。
現在,如果 JSON 文本采用以下形式
{
"People": [
{
"name": "John Doe",
"job": "Accountant",
"id": 123
},
{
"name": "Jane Doe",
"job": "Secretary",
"id": 321
}]
}
我可以寫
instance FromJSON person where
parseJSON = withObject "Person" $ \obj -> Person
<$> obj .: "name"
<*> obj .: "job"
<*> obj .: "id"
但我不知道如何將這種模式轉換為其他格式。
uj5u.com熱心網友回復:
JSON 字典,例如{ "foo" : "bar" }可以Map從容器包或HashMap無序容器中解碼為 Maps。一旦你有了 Person 的 FromJSON 實體,就可以Aeson.decode使用Map Text Person. 如果你想得到[Person]那么你可以進一步使用Data.Map.elems.
例如:
#!/usr/bin/env cabal
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{- cabal:
build-depends: base, aeson, bytestring, containers
-}
import GHC.Generics
import qualified Data.Aeson as Aeson
import Data.Map (Map)
import Data.Maybe (fromMaybe)
import qualified Data.ByteString.Lazy.Char8 as BS
data Person = Person
{ name :: String
, job :: String
, id :: Int
} deriving (Show, Generic, Aeson.ToJSON, Aeson.FromJSON)
main :: IO ()
main = print . decodePersons . BS.pack =<< getContents
decodePersons :: BS.ByteString -> Map String Person
decodePersons = fromMaybe (error "fail") . Aeson.decode
有趣的是它Aeson.decode回傳了一個 type Map String Person。一切都只是為了進行完整的演示。
您可以使用輸入進行測驗:
% ./so.hs <<EOF
{
"Person1": {
"name": "John Doe",
"job" : "Accountant",
"id": 123
},
"Person2": {
"name": "Jane Doe",
"job" : "Secretary",
"id": 321
}}
EOF
查看輸出:
fromList [("Person1",Person {name = "John Doe", job = "Accountant", id = 123}),("Person2",Person {name = "Jane Doe", job = "Secretary", id = 321})]
如果要洗掉Person1andPerson2標記,則只需使用 . 獲取 Map 的元素Data.Map.elems。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/495989.html
