使用lens-aeson从JSON ByteString获取值集合

时间:2016-04-21 08:58:37

标签: json haskell lens aeson

假设我有一个类似于

的JSON ByteString
{
    messages: [
        {...},
        {...}
    ]
}

我想使用镜头从中获取消息的列表/向量。我有一个函数toMessage可以将Value转换为Maybe Message

我已尝试过此作文key "messages" . values . to toMessageto来自Control.Lens.Getter,但结果为Maybe Message,只是Nothing

目前我正在这样做

msgsJson <- c ^? key "messages"
let msgs = toList $ mapMaybe message $ msgsJson ^.. values

mapMaybe来自witherabletoList是将Vector转换为列表) 但是我想知道是否有办法组合各种镜头来制作这样的镜头。

1 个答案:

答案 0 :(得分:1)

嗯,这对我有用:

{-# LANGUAGE OverloadedStrings #-}

module Main where

import Data.ByteString (ByteString)

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

newtype Message =
  Message Integer
  deriving (Show)

toMessage :: Value -> Maybe Message
toMessage json_ = do
  i <- json_ ^? key "a" . _Integer
  return (Message i)

input :: ByteString
input = "{\"messages\":[{\"a\":1},{\"a\":2},{\"a\":3}]}"

main :: IO ()
main =
  print (input ^.. (key "messages" . values . to toMessage))
λ> main
[Just (Message 1),Just (Message 2),Just (Message 3)]

如果您收到Nothing,则可能表示您的JSON无效(您可以使用decode json :: Maybe Value进行测试)。或者组合物中的任何其他光学器件都失效。对于长点缀光学器件,有时很难确切地知道哪一个失效,除非从末端切掉部件并重试。但是你的组合光学key "messages" . values . to toMessage应该是Just Work™。

顺便说一下:

msgJson <- c ^? key "messages"
let msgs = toList $ mapMaybe message $ msgsJson ^.. values

应与

相同
msgJson <- c ^? key "messages"
let msgs = toList $ msgsJson ^.. (values . to message . _Just)

msgJson <- c ^? key "messages"
let msgs = msgsJson ^.. (values . to message . _Just)

let msgs = c ^.. (key "messages" . values . to message . _Just)