2012-04-26 56 views
3

我見過ToJSON每個實例和FromJSON兩種數據類型與單個構造函數,像這樣:如何爲具有多個構造函數的數據類型編寫ToJSON/FromJSON實例?

data RewindConfig = RConfig JobID Phase 
         deriving Show 

instance FromJSON RewindConfig where 
    parseJSON (Object o) = RConfig 
    <$> o .: "JobID" 
    <*> o .: "Phase" 
    parseJSON _ = fail "invalid RewindConfig" 

我以爲我會看埃宋是如何使與多個構造類型的實例,例如Either

instance (FromJSON a, FromJSON b) => FromJSON (Either a b) where 
    parseJSON (Object (H.toList -> [(key, value)])) 
     | key == left = Left <$> parseJSON value 
     | key == right = Right <$> parseJSON value 
    parseJSON _  = fail "" 

在parseJSON模式匹配混淆了我,我不明白是怎麼回事(H.toList -> [(key, value)])

的數據類型我想使實例爲如下所示:

data Foo = Bar String 
     | Baz String 
     | Bin String 

它確實發生了,以我做的東西我知道如何實現

data Foo = (Maybe Bar) (Maybe Baz) (Maybe Bin) 

,但似乎未能如願。有人可以通過解釋Either實例的情況來幫助我解決問題,並且可能會爲Foo的收件人/發件人實例提供一些指導?

更新:我認爲實例Aeson實現的Maybe更清晰,並告訴我需要知道我的需求。不過,我想知道Either是怎麼回事。

回答

4

模式(Object (H.toList -> [(key, value)]))被稱爲view pattern。你可以把它讀作這樣的事:

parseJSon (Object o) = case H.toList o of 
    [(key, value)] 
     | key == left -> Left <$> parseJSON value 
     | key == right -> Right <$> parseJSON value 

它實際上是略有不同,流傳至今的Object時,上面的總是會提交到模式Object o,而當雙方的「Object o匹配的視圖模式只會犯模式「並且」H.toList o匹配[(key, value)]模式「條件成立,但對於此示例無關緊要。

2

json軟件包包含您可能要採用的數據類型的編碼。 如果你只是得到Data你可以使用它。它不是非常快,但非常容易使用。

1

假設每個數據類型都有不同的重點,另一種方法可以使用的鏡頭 - 我喜歡它,因爲它的簡潔和可讀性。例如,如果圍繞A,B和C的所有包含FromJSON實例的包裝:

import Data.Aeson 
import Data.Maybe 
import Data.Aeson.Lens 
import Control.Lens 

data Wrap = WrapA A | WrapB B | WrapC C 

instance FromJSON Wrap where 
    parseJSON json 
     | isJust (json ^? key "A's unique key") = WrapA <$> parseJSON json 
     | isJust (json ^? key "B's unique key") = WrapB <$> parseJSON json 
     | isJust (json ^? key "C's unique key") = WrapC <$> parseJSON json 
     | otherwise = fail "Bad message" 
+1

謝謝!我很欣賞從這篇舊文章中學到新東西 – 2014-09-04 23:03:30

相關問題