2016-04-21 18 views
2

mit Sagen, dass ich ein JSON ByteString habe, das Objektiv verwenden so etwas wieeine Sammlung von Werten aus einem JSON ByteString Ersten linsen Aeson

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

Ich mag sieht eine Liste/Vektor von Nachrichten, um aus es. Ich habe eine Funktion toMessage, die eine Value in eine Maybe Message schalten kann.

Ich habe diese Komposition versucht key "messages" . values . to toMessage (to von Control.Lens.Getter ist aber das Ergebnis ist Maybe Message und es wird einfach Nothing.

Derzeit mache ich das

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

(mapMaybe von witherable ist, toList ist die Vector in eine Liste zu konvertieren) aber ich würde gerne wissen, ob es eine Möglichkeit gibt, verschiedene Linsen zu komponieren, um eine einzige Linse zu bekommen, die tut s dies.

Antwort

1

Hmm, das funktioniert für mich:

{-# 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)] 

Wenn Sie Nothing bekommen, könnte es bedeuten, dass Ihre JSON ungültig ist (Sie können es mit decode json :: Maybe Value testen). Oder dass irgendeine andere Optik in der Zusammensetzung versagt. Bei der langen gepunkteten Optik ist es manchmal schwierig, genau zu sagen, welcher Fehler vorliegt, außer indem Teile vom Ende abgeschnitten und erneut versucht werden. Aber deine komponierte Optik key "messages" . values . to toMessage sollte einfach funktionieren.

By the way:

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

die gleiche wie

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

und

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

und

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

Hmm sein sollte, werde ich Ich muss es noch einmal versuchen. Schau, was ich beim ersten Mal falsch gemacht habe. –