在使用lens-aeson提取JSON字段时组合棱镜

时间:2016-10-14 23:04:50

标签: json haskell lens aeson lenses

我有一个类似于以下内容的JSON blob:

[
  {
    "version": 1
  },
  {
    "version": "3"
  },
  ...
]

请注意,某些版本是数字,有些是字符串。 我想获得一个版本列表。 我可以使用以下镜头组合来提取数字版本:

v1 :: [String]
v1 = obj ^.. AL.values . AL.key fieldName . AL._Number . to show

以下提取字符串

v2 :: [String]
v2 = obj ^.. AL.values . AL.key fieldName . AL._String . to T.unpack

但是,如何通过列表中的一次传递获取版本列表? 是否有任何镜头组合器需要镜头AL._Number . to showAL._String . to T.unpack并返回一个组合的吸气剂,以便如果第一个失败,尝试第二个?透镜的msum之类的东西?

2 个答案:

答案 0 :(得分:4)

实际上有一个组合器可以尝试光学器件并在第一个失效时进入备份。它被称为failing

请注意,您描述的情况应满足条件。即使它不是,组合器仍然会起作用,它在重构时会表现得不规则。 (使用filtered作为'foo', 'bar', 'baz'的主要问题是。)

答案 1 :(得分:0)

在你应该使用的Carl's answer之前,我建议outside作为一种方法,用这些棱镜进行案例分析:

tryNumberThenString :: AL.AsPrimitive t => t -> [String]
tryNumberThenString =
    outside AL._Number .~ (:[]) . show $
    outside AL._String .~ (:[]) . T.unpack $
    const []
v1 = obj ^.. AL.values . AL.key fieldName . folding tryNumberThenString

请注意,除非我缺少其他一些技巧,否则这不仅比Carl建议的更复杂,而且灵活性也更低 - 我只能从普通函数{{1}获得Fold } {,tryNumberThenString将棱镜合并为failing