2012-11-08 3 views
4

을 destructuring 나는하스켈 아이손은 일반적인 구문 분석

{"command":"get","params":{"something":"something else"}} 

의 스타일에 JSON 요청과 Yesod book

{-# LANGUAGE OverloadedStrings #-} 
import Network.Wai (Response, responseLBS, Application, requestBody) 
import Network.HTTP.Types (status200, status400) 
import Network.Wai.Handler.Warp (run) 
import Data.Aeson.Parser (json) 
import Data.Conduit.Attoparsec (sinkParser) 
import Control.Monad.IO.Class (liftIO) 
import Data.Aeson (Value(..), encode, object, (.=)) 
import Control.Exception (SomeException) 
import Data.ByteString (ByteString) 
import Data.Conduit (ResourceT, ($$)) 
import Control.Exception.Lifted (handle) 

main :: IO() 
main = run 3000 app 

app :: Application 
app req = handle invalidJson $ do 
    value <- requestBody req $$ sinkParser json 
    newValue <- liftIO $ modValue value 
    return $ responseLBS 
     status200 
     [("Content-Type", "application/json")] 
     $ encode newValue 

invalidJson :: SomeException -> ResourceT IO Response 
invalidJson ex = return $ responseLBS 
    status400 
    [("Content-Type", "application/json")] 
    $ encode $ object 
     [ ("message" .= show ex) 
     ] 

-- Application-specific logic would go here. 
modValue :: Value -> IO Value 
modValue (Object o) 
    | -- key "command" corresponds to value "get" 
    | otherwise = fail "Invalid command" 

에서이 코드를 가지고하지만 어떻게 것 주위에 내 머리를 정리하고 수 없습니다 생성 된 값 데이터 구조를 파기합니다. 키 등의 값을 얻는 방법은 무엇입니까? 명시 적으로 정의 된 데이터 구조를 구문 분석 할 수 있다는 것을 알았지 만 다른 경우에는 사용 사례에 문제가 발생할 수 있습니다.

modValue에서 나는 무엇을 넣을 지 생각할 수없는 곳에 주석을 달았습니다. 나는 그것을 Aeson 내부에서 구현 한 방법이기 때문에 Map으로 처리하려고 시도했지만 분명히 유형 검사는하지 않습니다.

편집 :

수입에 Data.HashMap 추가 및

| M.lookup "command" o == Just "get" = return $ object [("result" .= (String "YAY"))] 

다음과 같은 오류 메시지가 제공하는 회선을 사용.

main.hs:39:26: 
Couldn't match expected type `M.Map k0 a0' 
      with actual type `aeson-0.6.0.2:Data.Aeson.Types.Internal.Object' 
In the second argument of `M.lookup', namely `o' 
In the first argument of `(==)', namely `M.lookup "command" o' 
In the expression: M.lookup "command" o == Just "get" 

는 EDIT2 : 갑자기 직감에

, 나는 "정렬되지 않은-용기"를 포함하는 앞서있어 오류 메시지를 추적. 이것은 Aeson이 사용하는 패키지입니다. 그러나 패키지 해시 맵이 설치되어 Data.HashMap으로 가져온 것을 알게되었습니다. 정렬되지 않은 컨테이너의 해시 맵은 Data.HashMap.Strict 또는 Lazy!

줄을 import qualified Data.HashMap as M에서 import qualified Data.HashMap.Strict as M으로 변경하면 어쨌든 수정되었습니다. 이제 주어진 답이 작동합니다!

답변

5

aeson JSON object is a Hashmap이므로 Hasmap interface (이 경우 lookup)을 사용할 수 있습니다.

import qualified Data.HashMap.Strict as M 

M.lookup "command" o == Just "get" 
+0

는 내가 전에, 오류 메시지와 함께 업데이트 된 내가, 내가 그래서 올바른 방법이 '의 인스턴스를 생성하는 것입니다 가정합니다'HashMap'로'Object' 치료에 대해 아무것도 좋아 찾을 수 –

+0

가지고 것을 시도 FromJson' 여기 파싱에 대한 http://stackoverflow.com/questions/6090599/parsing-json-string-into-record-in-haskell –

+0

나는 그 예를 보았지만, 나는 일반적으로 직접 작업 할 수 있기를 바랬다. 생성 된 구조. 또한이 링크는 아이슨이 아니라 json 패키지에 관한 링크입니다. –