我有一堆带有任意键的嵌套 JSON 对象。
{
"A": {
"B": {
"C": "hello"
}
}
}
其中
A
、 B
、 C
提前未知。这三个中的每一个也可以有 sibling 。
我想知道是否有办法将其解析为带有 Aeson 的自定义类型
一些优雅的方式。我一直在做的是将它加载到 Aeson
Object
中。您将如何为这种 JSON 实现
FromJSON
目的?谢谢!
编辑 :
{
"USA": {
"California": {
"San Francisco": "Some text"
}
},
"Canada": {
...
}
}
这应该编译为
CountryDatabase
,其中...type City = Map String String
type Country = Map String City
type CountryDatabase = Map String Country
最佳答案
您可以重复使用 FromJSON
的 Map String v
实例。类似下一个:
{-# LANGUAGE OverloadedStrings #-}
import Data.Functor
import Data.Monoid
import Data.Aeson
import Data.Map (Map)
import qualified Data.ByteString.Lazy as LBS
import System.Environment
newtype City = City (Map String String)
deriving Show
instance FromJSON City where
parseJSON val = City <$> parseJSON val
newtype Country = Country (Map String City)
deriving Show
instance FromJSON Country where
parseJSON val = Country <$> parseJSON val
newtype DB = DB (Map String Country)
deriving Show
instance FromJSON DB where
parseJSON val = DB <$> parseJSON val
main :: IO ()
main = do
file <- head <$> getArgs
str <- LBS.readFile file
print (decode str :: Maybe DB)
输出:
shum@shum-lt:/tmp/shum$ cat in.js
{
"A": {
"A1": {
"A11": "1111",
"A22": "2222"
}
},
"B": {
}
}
shum@shum-lt:/tmp/shum$ runhaskell test.hs in.js
Just (DB (fromList [("A",Country (fromList [("A1",City (fromList [("A11","1111"),("A22","2222")]))])),("B",Country (fromList []))]))
shum@shum-lt:/tmp/shum$
PS:你可以在没有
newtype
的情况下做到这一点,我使用它们只是为了清楚起见。关于json - 带有 Aeson 的任意 JSON key - Haskell,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17278472/