2013-06-24 16 views
11

我有一堆與任意鍵嵌套的JSON對象。任意JSON密鑰與艾森 - 哈斯克爾

{ 
    "A": { 
     "B": { 
      "C": "hello" 

     } 
    } 

} 

ABC是提前未知。這三個人中的每一個也可以有 有兄弟姐妹。

我想知道是否有一種方法來解析這個到與艾森在 一些優雅的方式自定義類型。我一直在做的是將它加載到Aeson Object中。

你會如何去執行FromJSON這種JSON 對象?

謝謝!

編輯

{ 
    "USA": { 
     "California": { 
      "San Francisco": "Some text" 
     } 
    }, 
    "Canada": { 
     ... 
    } 
} 

這應該編譯爲CountryDatabase哪裏..​​.

type City   = Map String String 
type Country   = Map String City 
type CountryDatabase = Map String Country 
+1

這不是很清楚*你想怎麼解析這個JSON。它總是隻有3個嵌套鍵,然後是字符串? –

+0

你可以舉一個你想要解析的自定義類型的例子嗎?我想這會澄清這個問題。 –

+0

更新了更具體的數據結構示例的問題。 –

回答

18

您可以重複使用的Map String vFromJSON實例。喜歡的東西了下:

{-# 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) 

輸出:

[email protected]:/tmp/shum$ cat in.js 
{ 
    "A": { 
     "A1": { 
      "A11": "1111", 
      "A22": "2222" 
     } 
    }, 
    "B": { 
    } 
} 
[email protected]:/tmp/shum$ runhaskell test.hs in.js 
Just (DB (fromList [("A",Country (fromList [("A1",City (fromList [("A11","1111"),("A22","2222")]))])),("B",Country (fromList []))])) 
[email protected]:/tmp/shum$ 

PS:你可以不用newtype S,我用它們僅僅是爲了清楚。

+0

這個答案非常有幫助!這可以修改爲忽略非字符串值嗎? (例如,用'1111'代替'1111'''會導致解析失敗。) – davidchambers

+0

ToJSON實例如何看起來像這樣? – AdHominem