2016-04-21 5 views
2

Скажем, у меня есть JSON байтовой строки, которая выглядит как-тоПолучение коллекции значений из JSON байтовой строки с помощью объектива-эсон

{ 
    messages: [ 
     {...}, 
     {...} 
    ] 
} 

Я хотел бы использовать объектив, чтобы получить список/вектор сообщений из Это. У меня есть функция toMessage, которая может превратить Value в Maybe Message.

Я попробовал эту композицию key "messages" . values . to toMessage (to от Control.Lens.Getter но результат Maybe Message и он просто становится Nothing.

В настоящее время я делаю это

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

(mapMaybe от witherable, toList - это преобразование Vector в список) , но я хотел бы знать, есть ли способ создать различные линзы, чтобы получить один объектив, который делает это.

ответ

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) 
+0

Хм, я придется снова попробовать. Посмотрите, что я сделал неправильно в первый раз. –