2013-06-24 8 views
11

मेरे पास मनमानी कुंजी के साथ नेस्टेड JSON ऑब्जेक्ट्स का एक गुच्छा है।एसन के साथ मनमानी JSON कुंजी - हास्केल

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

     } 
    } 

} 

कहाँ A, B, C अज्ञात समय से आगे कर रहे हैं। उनमें से प्रत्येक तीन भाई बहन भी हो सकता है।

मुझे आश्चर्य है कि में कुछ सुरुचिपूर्ण तरीके से एसेन के साथ कस्टम प्रकार में इसे पार्स करने का कोई तरीका है या नहीं। मैं जो कर रहा हूं वह इसे एसन 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 
+1

यह वास्तव में स्पष्ट नहीं है * आप * इस JSON को कैसे पार्स करना चाहते हैं। क्या यह हमेशा 3 नेस्टेड कुंजी और फिर स्ट्रिंग है? –

+0

क्या आप उस कस्टम प्रकार का उदाहरण दे सकते हैं जिसमें आप पार्स करना चाहते हैं? मुझे लगता है कि सवाल स्पष्ट करेगा। –

+0

डेटा संरचनाओं के एक और ठोस उदाहरण के साथ अद्यतन किया गया प्रश्न। –

उत्तर

18

आप Map String v की FromJSON उदाहरण का पुन: उपयोग कर सकते हैं। अगले कुछ:

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

पुनश्च: आप बिना newtype रों यह कर सकते हैं, मैं उन्हें केवल स्पष्टता के लिए इस्तेमाल किया।

+0

यह उत्तर बहुत उपयोगी है! गैर-स्ट्रिंग मानों को अनदेखा करने के लिए इसे संशोधित किया जा सकता है? ('1111 'के साथ' 1111' 'को बदलकर, उदाहरण के लिए, पार्स विफल होने का कारण बनता है।) – davidchambers

+0

इसके लिए एक TOJSON उदाहरण कैसा दिखता है? – AdHominem

संबंधित मुद्दे