2015-12-03 86 views
0

我試圖解析與aseon休耕JSON:如何在Haskell中解析嵌套的JSON,其中也包含列表?

JSON

{ 
    "response": [ 
    { 
     "id": 5555, 
     "brandId": 10, 
     "productTypeId": 1, 
     "identity": { 
     "sku": "ABCDEF", 
     "ean": "1111", 
     "barcode": "2222" 
     }, 
     "productGroupId": 17, 
     "stock": { 
     "stockTracked": true, 
     "weight": { 
      "magnitude": 0 
     }, 
     "dimensions": { 
      "length": 0, 
      "height": 0, 
      "width": 0, 
      "volume": 0 
     } 
     }, 
     "financialDetails": { 
     "taxable": false, 
     "taxCode": { 
      "id": 7, 
      "code": "T1" 
     } 
     }, 
     "variations": [ 
     { 
      "optionId": 1, 
      "optionName": "option1", 
      "optionValueId": 5, 
      "optionValue": "5" 
     }, 
     { 
      "optionId": 2, 
      "optionName": "option2", 
      "optionValueId": 14, 
      "optionValue": "OS" 
     } 
     ] 
    }, 
    { 
     "id": 9999, 
     "brandId": 10, 
     "productTypeId": 1, 
     "identity": { 
     "sku": "CDEFG", 
     "ean": "111221", 
     "barcode": "2443222" 
     }, 
     "productGroupId": 17, 
     "stock": { 
     "stockTracked": true, 
     "weight": { 
      "magnitude": 0 
     }, 
     "dimensions": { 
      "length": 0, 
      "height": 0, 
      "width": 0, 
      "volume": 0 
     } 
     }, 
     "financialDetails": { 
     "taxable": false, 
     "taxCode": { 
      "id": 7, 
      "code": "T1" 
     } 
     }, 
     "variations": [ 
     { 
      "optionId": 1, 
      "optionName": "option1", 
      "optionValueId": 5, 
      "optionValue": "5" 
     }, 
     { 
      "optionId": 2, 
      "optionName": "option2", 
      "optionValueId": 14, 
      "optionValue": "14" 
     } 
     ] 
    } 
    ] 
} 

我試圖建立的數據結構和實例:以下是我迄今爲止:

CODE

{-# LANGUAGE OverloadedStrings #-} 

import Data.Aeson 
import Control.Applicative 
import qualified Data.ByteString.Lazy.Char8 as BS 



data Response = Response     { response    :: [Body] 
              } deriving (Show) 

instance FromJSON Response where 
    parseJSON (Object v) = Response <$> 
          v .: "response"            

data Body = Body       { idd     :: Int 
              , brandId    :: Int 
              , productTypeId   :: Int 
              , identity    :: Identity 
              , productGroupId  :: Int 
              , stock     :: Stock 
              , financialDetails  :: FinancialDetails 
              , variations   :: [Variation] 
              } deriving (Show) 

instance FromJSON Body where 
    parseJSON (Object v) = Body <$> 
          (e >>= (.: "id")) <*> 
          (e >>= (.: "brandId")) <*> 
          (e >>= (.: "productTypeId")) <*> 
         -- DON'T KNOW HOW TO SET UP IDENTITY 
          (e >>= (.: "productGroupId")) 
         -- DON'T KNOW HOW TO SET UP STOCK 
         -- DON'T KNOW HOW TO SET UP FINANCIAL DETAILS       
         -- DON'T KNOW HOW TO SET UP VARIATIONS 
          where e = (v .: "response")            


data Identity = Identity     { sku     :: String 
              , ean     :: String 
              , barcode    :: String 
              } deriving (Show) 

data Stock = Stock       { stockTracked   :: Bool 
              , weight    :: Weight 
              , dimensions   :: Dimensions 
              } deriving (Show) 

data Weight = Weight      { magnitude    :: Double 
              } deriving (Show) 

data Dimensions = Dimensions    { length    :: Double 
              , height    :: Double 
              , width     :: Double 
              , volume    :: Double 
              } deriving (Show)  

data FinancialDetails = FinancialDetails { taxable    :: Bool 
              , taxCode    :: TaxCode 
              } deriving (Show) 

data TaxCode = TaxCode      { id     :: Int 
              , code     :: String 
              } deriving (Show)  


data Variation = Variation     { optionId    :: Int 
              , optionName   :: String 
              , optionValueId   :: Int 
              , optionValue   :: String 
              } deriving (Show) 

我的問題是,我不知道如何綁定嵌套值我也不能弄清楚如何處理JS名單部分上。我試圖通過文檔和其他stackoverflow問題;但是我無法找到任何幫助解決這種複雜性的事情。

我該如何去獲取嵌套值和列出值的對象。

感謝

回答

2

你只需要完成寫入所有FromJSON情況下,每種類型,但你需要修復您的實例BodyparseJSON每個定義應該是總的功能,所以包括當你的情況下,給出其他的東西比一個Object

data Response = Response 
    { response :: [Body] 
    } deriving (Show) 

instance FromJSON Response where 
    parseJSON (Object v) = Response <$> v .: "response" 
    parseJSON _ = mzero 

data Body = Body 
    { idd    :: Int 
    , brandId   :: Int 
    , productTypeId  :: Int 
    , identity   :: Identity 
    , productGroupId :: Int 
    , stock    :: Stock 
    , financialDetails :: FinancialDetails 
    , variations  :: [Variation] 
    } deriving (Show) 

instance FromJSON Body where 
    parseJSON (Object v) = Body 
     <$> v .: "id" 
     <*> v .: "brandId" 
     <*> v .: "productTypeId" 
     <*> v .: "identity" 
     <*> v .: "productGroupId" 
     <*> v .: "stock" 
     <*> v .: "financialDetails" 
     <*> v .: "variations" 
    parseJSON _ = mzero 

然後你只需要編寫每個解析器爲您的其他類型:

data Identity = Identity 
    { sku  :: String 
    , ean  :: String 
    , barcode :: String 
    } deriving (Show) 

instance FromJSON Identity where 
    parseJSON (Object v) = Identity 
     <$> v .: "sku" 
     <*> v .: "ean" 
     <*> v .: "barcode" 
    parseJSON _ = mzero 

data Stock = Stock 
    { stockTracked :: Bool 
    , weight  :: Weight 
    , dimensions :: Dimensions 
    } deriving (Show) 

instance FromJSON Stock where 
    parseJSON (Object v) = Stock 
     <$> v .: "stockTracked" 
     <*> v .: "weight" 
     <*> v .: "dimensions" 
    parseJSON _ = mzero 

依此類推。我會讓你完成你在這裏的所有不同類型。

最後一點小問題,它看起來好像您的示例JSON文件有複製/粘貼錯誤,第4行和第48行最後需要逗號使其成爲有效的JSON文檔。

或者,您可以包含DeriveGeneric語言擴展名,然後輸入GHC.Generics即可爲您的每個類型deriving (Show, Generic)。那麼你需要寫的是

instance FromJSON Response where 
instance FromJSON Body where 
instance FromJSON Identity where 
instance FromJSON Stock where 
instance FromJSON Weight where 
instance FromJSON Dimensions where 
instance FromJSON FinancialDetails where 
instance FromJSON TaxCode where 
instance FromJSON Variation where 

而不需要指定如何從JSON轉換的實際細節。現在唯一的問題是,你需要JSON使用"idd"而不是"id"代替Body結構,儘管我建議將它重命名爲"bodyId",因爲id是Haskell中的一個內置函數(並且與其他類型類似有一個id字段)。然後,您也可以爲每個類型使用instance ToJSON <type> where,以便自動獲得類型的序列化。

+0

感謝您的回覆。我用修改過的JSON嘗試了你的代碼:'decode json :: Maybe Body' = ** Nothing **。我究竟做錯了什麼? – matthias

+0

@matthias嘗試'解碼json :: Maybe Response',因爲你的JSON文檔包含一個'Response',其中包含多個'Body's。 – bheklilr

+0

是的,這是有效的。我無法直接訪問其他對象嗎? – matthias