2012-11-19 69 views
2

你知道任何哈斯克爾庫數據驗證了記錄

  1. 提供了一些簡化備案驗證和(!)
  2. 作品與埃宋的?

我知道我可以寫一些構造函數,但是我想在不重新發明輪子的情況下擦除樣板。

我所尋找的是以下幾點:

我想定義每個領域的「合同」。例如:

data Person = Person { 
    age :: Integer 
    ,email :: Text 
    ,projects :: [Project]} 

現在,我想確保我解析JSON到記錄後,以下成立:

  1. 年齡在[0,天道酬勤)
  2. 電子郵件匹配「^[A-Z0-9 ._%+ - ] + @ [A-Z0-9 .-] + [AZ] {2,6-} $」
  3. 項目包含至少2個項目

如果我嘗試使用ag創建記錄e < 0,我會收到一條錯誤消息,例如「age = 0 no in [0,inf)」。我認爲這樣的應該可以通過模板Haskell派生。

此外,我想將它集成到解析器階段。因此,而不是讓這樣的錯誤消息「預期時的積分,遇到字符串代替」,我想獲得的錯誤消息

  1. 顯示錯誤(不知道的位置,如果這是可能的attoparsec )
  2. 描述錯誤。
+0

請參閱「智能構造函數」 – luqui

+0

@luqui:Thx-有此想法,但我還沒有找到一種簡單的方法將智能構造函數集成到Aeson中 - 另外,我不確定如何將它與鏡頭。 – Chronos

+0

似乎讓構造函數返回一個Monad幫助 - 仍然留下的問題是,Aeson不會報告發生錯誤的位置。謝謝,盧奎,提示。 – Chronos

回答

0

有,age不是的時代,是一個Integermail不是郵件,是Text

我想,你應該創建自己的AgeMail數據類型,並創建適當的ToJSONFromJSON實例(僅一次)。

例如

newtype Age = Age { unAge :: Word8 } deriving (Eq, Generic, Ord, Show) 

instance Bounded Age where 
    minBound = Age 0 
    maxBound = Age 150 

instance FromJSON Age where 
    parseJSON (Number n) = case (toBoundedInteger n >>= makeAge) of 
          Nothing -> fail $ "The number " ++ show n ++ " is not a valid Age value \ 
               \(must to be between " ++ show (minBound :: Age) 
                  ++ " and " ++ show (maxBound :: Age) 
          Just k -> pure k 
    parseJSON o   = typeMismatch "Age" o 

instance ToJSON Age where 
    toJSON = toJSON . unAge 

現在,一個樣本記錄使用Age

> data Test = Test { age :: Age } deriving (Show, Generic) 
> instance ToJSON Test 
> instance FromJSON Test 

當你用錯誤分析,它正確報道

> eitherDecode "{\"age\": -1}" :: Either String Test 
Left "The number -1.0 is not a valid Age value (must to be between Age {unAge = 0} and Age {unAge = 150}" 

還,如果age不提供

> eitherDecode "{\"age1\": 12}" :: Either String Test 
Left "The key \"age\" was not found"