找不到一个好例子.感谢任何帮助.
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")
我该如何定义&使用FromJSON类型从x转换为:
- data Exif = Exif [[(String,String)]]
或类似的数据结构?注意[[]] – 我希望JSON有多个顶级条目.
解决方法
这是一个惯用的解决方案:
- {-# 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:ResolutionUnit": "inches"
- }
- {
- "EXIF:Make": "Canon","EXIF:Model": "Canon PowerShot S995","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",exifResolutionUnit = "inches"}]
或者,这是一个slightly more ugly solution,它为您提供所请求的数据类型([[(Text,Text)]]).