{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
module Main where
import Data.Aeson
import Data.Aeson.Encode.Pretty
import Data.Aeson.Types
import Data.ByteString as B
import qualified Data.ByteString.Lazy.Char8 as LC
import GHC.Generics
import Data.Text
data MainWeatherInfo = MainWeatherInfo
{ mainInfo :: Main
} deriving (Show,Generic)
data Main = Main
{ temp :: Double
, pressure :: Int
, humidity :: Int
, temp_min :: Double
, temp_max :: Double
} deriving (Show,Generic)
instance FromJSON MainWeatherInfo
instance FromJSON Main
main :: IO ()
main = do
jsonString <- B.readFile "/home/ashot/test.json"
let result = decodeStrict $ jsonString :: Maybe MainWeatherInfo
case result of
Nothing -> print "error"
Just result -> print result
和JSON文件:
{
"coord": {
"lon": 44.51,
"lat": 40.18
},
"weather": [{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}],
"base": "stations",
"main": {
"temp": 299.15,
"pressure": 1008,
"humidity": 34,
"temp_min": 299.15,
"temp_max": 299.15
},
"visibility": 10000,
"wind": {
"speed": 1.5,
"deg": 190
},
"rain": {
"3h": 0.195
},
"clouds": {
"all": 8
},
"dt": 1528615800,
"sys": {
"type": 1,
"message": 0.0036,
"country": "AM",
"sunrise": 1528594331,
"sunset": 1528648255
},
"id": 616052,
"name": "Yerevan",
"cod": 200
}
我需要Extract“main”信息。我有类型MainWeatherInfo。这个代码是编译的。但是在启动过程中我收到了这个“错误”。如何解决此问题并获取正常信息?
答案 0 :(得分:0)
问题是 aeson 正在文件中寻找名为 mainInfo 的字段,但这样的字段不存在。
最初我认为我们可以通过将 MainWeatherInfo 的类型定义中的 mainInfo 更改为 main 来解决问题。这不起作用,因为已存在具有相同名称的函数!
aeson 提供了一种解决方法,您可以在泛型:自定义字段名称部分的this helpful tutorial中找到说明。
更具体地说,如果你使用turorial的方法,你最终会得到一个 Main.hs ,如下所示:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
module Main where
import GHC.Generics
import Data.Aeson
import Data.Aeson.Types
import qualified Data.ByteString as L
data MainWeatherInfo = MainWeatherInfo
{ mainInfo :: Main
} deriving ( Show
, Generic
)
instance ToJSON MainWeatherInfo where
toJSON = genericToJSON defaultOptions { fieldLabelModifier = take 4 }
instance FromJSON MainWeatherInfo where
parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = take 4 }
data Main = Main
{ temp :: Double
, pressure :: Int
, humidity :: Int
, temp_min :: Double
, temp_max :: Double
} deriving ( Show
, Generic
, ToJSON
, FromJSON
)
main :: IO ()
main = do
contents <- L.readFile "notes/test.json"
let result = (decodeStrict contents) :: Maybe MainWeatherInfo
case result of
Nothing -> putStrLn "error"
Just v -> putStrLn $ show v
我在计算机上试用了它并且工作正常。
更新:我一直非常愚蠢,并认为解决方案只需要限制在一个模块中。拥有一个 Main.hs 可能会更好 :
module Main where
import Data.Aeson
import qualified Data.ByteString as L
import qualified Weather as W
main :: IO ()
main = do
contents <- L.readFile "notes/test.json"
let result = (decodeStrict contents) :: Maybe W.MainWeatherInfo
case result of
Nothing -> putStrLn "error"
Just v -> putStrLn $ show v
还有另一个模块 Weather.hs :
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
module Weather where
import GHC.Generics
import Data.Aeson
import Data.Aeson.Types
data MainWeatherInfo = MainWeatherInfo
{ main :: Main
} deriving ( Show
, Generic
, ToJSON
, FromJSON
)
data Main = Main
{ temp :: Double
, pressure :: Int
, humidity :: Int
, temp_min :: Double
, temp_max :: Double
} deriving ( Show
, Generic
, ToJSON
, FromJSON
)
我测试它只是为了确定,并且它有效。