2016-02-15 19 views
5

Tôi có đoạn JSON sau:Làm cách nào để phân tích cú pháp JSON này với Aeson?

{ 
    "weather": [ 
    { 
     "id": 803, 
     "main": "Clouds", 
     "description": "broken clouds", 
     "icon": "04n" 
    } 
    ], 
    "main": { 
    "temp": 271.979, 
    "pressure": 1024.8, 
    "humidity": 100, 
    "temp_min": 271.979, 
    "temp_max": 271.979, 
    "sea_level": 1028.51, 
    "grnd_level": 1024.8 
    }, 
    "id": 6332485, 
    "name": "Queensbridge Houses", 
    "cod": 200 
} 

Tôi muốn để có được phân tích các loại sau đây từ nó:

data WeatherResponse = WeatherResponse 
    { temp :: Double 
    , humidity :: Double 
    , weatherMain :: T.Text 
    } deriving Show 

Tôi đã cố gắng sử dụng đoạn mã sau để làm điều đó, nhưng tôi tiếp tục gặp lỗi. Cuối cùng tôi đã có tất cả các loại để phù hợp, nhưng nó phân tích không chính xác và không thực sự hiểu nơi nó không.

{-# LANGUAGE OverloadedStrings #-} 
{-# LANGUAGE RecordWildCards #-} 
{-# LANGUAGE ScopedTypeVariables #-} 

import Data.Aeson 
import Data.Aeson.Types (Parser, Array) 
import Data.Time (defaultTimeLocale, formatTime, getZonedTime) 

import qualified Data.ByteString.Lazy as BL 
import qualified Data.Vector as V 
import qualified Data.Text as T 

data WeatherResponse = WeatherResponse 
    { temp :: Double 
    , humidity :: Double 
    , weatherMain :: T.Text 
    } deriving Show 

lambda3 :: Value -> Parser T.Text 
lambda3 o = do 
    withText "main" (\t -> do 
         return t 
       ) o 

parseInner :: Value -> Parser T.Text 
parseInner a = withArray "Inner Array" (lambda3 . (V.head)) a 

instance FromJSON WeatherResponse where 
    parseJSON = 
    withObject "Root Object" $ \o -> do 
    mainO <- o .: "main" 
    temp <- mainO .: "temp" 
    humidity <- mainO .: "humidity" 
    weatherO <- o .: "weather" 
    weatherMain <- parseInner weatherO 
    return $ WeatherResponse temp humidity weatherMain 

getSampleData = BL.readFile "/home/vmadiath/.xmonad/weather.json" 

main = do 
    text <- getSampleData 
    let (result :: Either String WeatherResponse) = eitherDecode text 
    putStrLn . show $ result 

Tôi chỉ nhận được kết quả sau không đủ cho tôi biết mình đã đi sai ở đâu.

$ runhaskell lib/code.hs 
Left "Error in $: expected main, encountered Object" 

Tôi đã đưa toàn bộ điều trong một ý chính có thể xem here

Tôi muốn biết có gì sai với mã này, và làm thế nào tôi có thể sửa chữa nó. Nếu bạn có gợi ý về cách viết điều này theo cách dễ đọc hơn, tôi cũng muốn biết điều đó. Hiện tại tôi hầu như bực mình với hai chức năng riêng biệt lambda3parseInner gây phiền nhiễu)

+0

By 'V.head' bạn có phần tử đầu tiên trong 'mảng weather' đó là một đối tượng, vì vậy nó nên được' lambda3 = withObject "weatherMain" (.: "main") '. – zakyggaps

Trả lời

4

Theo tôi, bạn đang làm quá phức tạp. Một cái gì đó như thế này nên làm việc:

instance FromJSON WeatherResponse where 
    parseJSON (Object v) = do 
     weatherValue <- head <$> v .: "weather" 
     WeatherResponse <$> ((v .: "main") >>= (.: "temp")) 
          <*> ((v .: "main") >>= (.: "humidity")) 
          <*> weatherValue .: "main" 

Đó là đầu ra:

[nix-shell:~/haskell-sample]$ ./weather 
Right (WeatherResponse {temp = 271.979, humidity = 100.0, weatherMain = "Clouds"}) 
Các vấn đề liên quan