使用 lens-aeson 提取 JSON 场时结合棱镜

Combining prisms when extracting JSON fields with lens-aeson

我有一个 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 和 returns 组合成 getter 以便如果第一个失败,请尝试第二个?像 msum 这样的镜头?

实际上有一个组合器尝试光学器件并在第一个失败时转到备份。它被称为 failing

请注意,您所描述的情况应满足其条件。即使不是,组合器仍然可以运行,只是在重构时表现不规则。 (这是使用 filtered 作为 Traversal 的主要问题。)

, which is what you should use, I was going to suggest 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 所建议的更复杂,而且更不灵活——我只能从普通函数 tryNumberThenString,而 failing 将棱镜组合成 Traversal