找不到一个好例子。感谢任何帮助。 JSON如下:
[{
"EXIF:Make": "Canon",
"EXIF:Model": "Canon PowerShot S95",
"EXIF:Orientation": "Horizontal (normal)",
"EXIF:XResolution": 180,
"EXIF:YResolution": 180,
"EXIF:ResolutionUnit": "inches"
}]
我使用的代码如下:
import Data.Aeson
import Data.Attoparsec
import Data.ByteString
x <- fmap (parse json) (Data.ByteString.readFile "json.txt")
我如何定义&amp;使用FromJSON
类型将x
转换为:
data Exif = Exif [[(String, String)]]
或类似的数据结构?请注意[[]]
- 我希望JSON有多个顶级条目。
答案 0 :(得分:15)
这是一个惯用的解决方案:
{-# LANGUAGE OverloadedStrings #-}
module Main
where
import Control.Applicative
import Control.Monad
import Data.Aeson
import Data.Attoparsec
import qualified Data.ByteString as B
import qualified Data.Text as T
data ExifEntry = ExifEntry { exifMake :: T.Text,
exifModel :: T.Text,
exifOrientation :: T.Text,
exifXResolution :: Int,
exifYResolution :: Int,
exifResolutionUnit :: T.Text
} deriving (Eq, Show)
instance FromJSON ExifEntry
where
parseJSON (Object v) = ExifEntry <$>
v .: "EXIF:Make" <*>
v .: "EXIF:Model" <*>
v .: "EXIF:Orientation" <*>
v .: "EXIF:XResolution" <*>
v .: "EXIF:YResolution" <*>
v .: "EXIF:ResolutionUnit"
parseJSON _ = mzero
parseAll :: B.ByteString -> [ExifEntry]
parseAll s = case (parse (fromJSON <$> json) s) of
Done _ (Error err) -> error err
Done ss (Success e) -> e:(parseAll ss)
_ -> []
main :: IO ()
main = do s <- B.readFile "json.txt"
let p = parseAll s
print p
测试:
$ cat json.txt
{
"EXIF:Make": "Canon",
"EXIF:Model": "Canon PowerShot S95",
"EXIF:Orientation": "Horizontal (normal)",
"EXIF:XResolution": 180,
"EXIF:YResolution": 180,
"EXIF:ResolutionUnit": "inches"
}
{
"EXIF:Make": "Canon",
"EXIF:Model": "Canon PowerShot S995",
"EXIF:Orientation": "Horizontal (normal)",
"EXIF:XResolution": 180,
"EXIF:YResolution": 180,
"EXIF:ResolutionUnit": "inches"
}
$ ./dist/build/test/test
[ExifEntry {exifMake = "Canon", exifModel = "Canon PowerShot S95", exifOrientation = "Horizontal (normal)", exifXResolution = 180, exifYResolution = 180, exifResolutionUnit = "inches"},ExifEntry {exifMake = "Canon", exifModel = "Canon PowerShot S995", exifOrientation = "Horizontal (normal)", exifXResolution = 180, exifYResolution = 180, exifResolutionUnit = "inches"}]
或者,这是slightly more ugly solution,它为您提供所请求的数据类型([[(Text,Text)]]
)。