Haskell,Aeson和JSON解析为自定义类型

Sno*_*ual 13 json haskell aeson

继上一篇文章之后,我发现自己完全陷入困境.我正在尝试将JSON结构解析为我自己的类型,而且我不仅坚持如何解析数组,我甚至不确定我是否按预期使用了Aeson库.任何帮助将不胜感激.

代码:

data Exif = Exif [(T.Text, ExifValue)] deriving (Show)
data ExifValue = 
    ExifText T.Text | 
    ExifInt Integer | 
    ExifDouble Double | 
    ExifBool Bool | 
    ExifArray [ExifValue] 
    deriving (Show)

instance FromJSON ExifValue where
    parseJSON (Number (I n)) = return $ ExifInt n
    parseJSON (Number (D n)) = return $ ExifDouble n
    parseJSON (String s)     = return $ ExifText s
    parseJSON (Bool b)       = return $ ExifBool b
    -- parseJSON (Array a)      = ?????

instance FromJSON Exif where
    parseJSON (Object o) = do
        x <- sequence $ map f (M.assocs o)
        return $ Exif x
        where 
        f (t, x) = do
            y <- parseJSON x 
            return ((t, y) :: (T.Text, ExifValue))

parseExifFile = fmap parseExifData . B.readFile

parseExifData :: B.ByteString -> Data.Attoparsec.Result (Data.Aeson.Result [Exif])
parseExifData content = parse (fmap fromJSON json) content
Run Code Online (Sandbox Code Playgroud)

测试文件:

[{
  "SourceFile": "test.jpg",
  "ExifTool:ExifToolVersion": 8.61,
  "File:FileName": "test.jpg",
  "File:FileSize": 2174179,
  "File:FileModifyDate": "2011:07:27 16:53:49-07:00",
  "File:FilePermissions": 644,
  "File:FileType": "JPEG",
  "File:MIMEType": "image/jpeg",
  "File:ExifByteOrder": "MM",
  "File:CurrentIPTCDigest": "32d6a77098a73aa816f2570c9472735a",
  "File:ImageWidth": 2592,
  "File:ImageHeight": 1936,
  "File:EncodingProcess": 0,
  "File:BitsPerSample": 8,
  "File:ColorComponents": 3,
  "File:YCbCrSubSampling": "2 2",
  "XMP:Subject": ["alpha","beta","gamma"]
}]
Run Code Online (Sandbox Code Playgroud)

acf*_*zer 11

你必须遵循parseJSON一条兔子小道的类型,但一旦你认识到(Array a)代表什么,它应该是直截了当的.

parseJSON有类型Value -> Parser a,所以(Array a)有类型Value.该类型中的一个变体ValueArray Array,因此ain (Array a)必须是类型Array,定义为Vector Value.在Value里面,且s Vector是要叫什么parseJSON就来回报您的清单,因此,请检查您可以用做什么Vector.

最简单的方法可能是转换a为一个列表Vector.toList,然后mapM用来解析Values.

或者,您可以Vector通过将ExifArray变体更改为保持Vector ExifValue,然后使用来避免列表转换Vector.mapM.


yih*_*ang 5

我不是母语为英语的人,所以我可能不太了解你.我想你想知道如何将json解析为递归数据类型,就像ExifValue你提出的那样.所以我做了一个简单的例子来展示如何将json解析为递归数据类型.

{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString as B
import Data.Maybe
import Control.Monad
import Control.Applicative
import Data.Attoparsec
import Data.Attoparsec.Number
import Data.Aeson
import qualified Data.Vector as V

data Data = D1 Int | D2 [Data]
    deriving (Show)

instance FromJSON Data where
    parseJSON (Number (I n)) = return $ D1 $ fromInteger n
    parseJSON (Array a)    = D2 <$> mapM parseJSON (V.toList a)

main = do
    let v = fromJust $ maybeResult $ parse json "[1,2,3,[5,3,[6,3,5]]]"
    let v1 :: Data
        v1 = case fromJSON v of
                 Success a -> a
                 Error s   -> error s
    print v1
Run Code Online (Sandbox Code Playgroud)