使用管道将值序列化为 JSON 数组

Serializing values to JSON array with pipes

我想将传入值序列化为 JSON。每个值都有一个 toJSON 实例。最终结果应该是一个列表。当前代码如下:

import Pipes
import qualified Pipes.Prelude as P

-- assume a source of elements
main :: IO ()
main = runEffect $ source >-> P.map encode >-> P.stdoutLn

问题是这样每一行都包含一个有效的 JSON 对象,但我希望整个结果是可解析的。我希望在第一个对象之前输出一个 [ 字符,然后每个元素后跟一个逗号,最后是另一个 ]。我怎样才能用管道做到这一点?

当前输出:

$ prog
{"key": "value"}
{"key": "value"}

期望的输出:

$ prog
[{"key": "value"},
{"key": "value"}]

我找到了pipes-aeson,但我不明白我应该如何使用它提供的功能。

编辑:我修改了 ErikR 的答案以获得 Consumer,但它不输出右括号:

jsonExporter :: Consumer (FilePath, AnalysisResult) IO ()
jsonExporter = do
    lift $ putStr "["
    P.map encode >-> insertCommas
    lift $ putStr "]"

我不明白为什么。

这个管段:

for cat $ \x -> lift $ do { putStr ", "; putStrLn x }

将在管道中的每个元素之前发出一个逗号。

为了对第一个元素进行特殊处理,我们只展开一次循环:

insertCommas = do
  x1 <- await
  lift $ putStrLn x1      -- print first element w/o a comma
  for cat $ \x -> lift $ do { putStr ", "; putStrLn x }

现在您可以将流 JSON 管道编写为:

putStr "["
runEffect $ source >-> P.map encode >-> insertCommas
putStrLn "]"