Сериализация значений в массив JSON с каналами
Я хотел бы сериализовать входящие значения в 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"}]
Я нашел трубку-эзон, но я не понимаю, как я должен использовать функции, которые он предоставляет.
РЕДАКТИРОВАТЬ: я изменил ответ ErikR, чтобы получить Consumer
, но не выводит закрывающую скобку:
jsonExporter :: Consumer (FilePath, AnalysisResult) IO ()
jsonExporter = do
lift $ putStr "["
P.map encode >-> insertCommas
lift $ putStr "]"
Я не могу понять почему.
1 ответ
Этот отрезок трубы:
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 "]"