2012-11-19 71 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"