找不到一个好例子.感谢任何帮助.
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)]]).