Haskell,Aeson& JSON解析为自定义类型 [英] Haskell, Aeson & JSON parsing into custom type

查看:118
本文介绍了Haskell,Aeson& JSON解析为自定义类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上一篇文章之后,我发现我完全卡住了。我试图将JSON结构解析为我自己的类型,不仅我坚持如何解析数组,我甚至不确定是否按照预期使用了Aeson库。任何帮助将不胜感激。



代码:

 数据Exif = Exif [(T.Text,ExifValue)]派生(显示)
数据ExifValue =
ExifText T.Text |
ExifInt Integer |
ExifDouble Double |
ExifBool Bool |
ExifArray [ExifValue]
deriving(显示)

实例FromJSON ExifValue其中
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 )= ?????

实例FromJSON Exif其中
parseJSON(Object o)= do
x< - sequence $ map f(M.assocs o)
return $ Exif x
其中
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

测试文件:

  [{
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,
文件: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]
}]

一点点d拥有一条兔子踪迹,但一旦你认识到(Array a)表示,它应该是直截了当的。

parseJSON 有类型值 - >解析器a ,所以(Array a)具有类型 Value中的一个变体是 Array Array ,所以 a (Array a)中的c $ c>必须是 Array 类型,它定义为矢量值 Vector 中的 Value s是您要调用的内容 parseJSON on返回你的列表,所以看看你可以用 Vector p

最简单的方法可能是将 a 转换为 Vector.toList 列表,然后使用 mapM



或者,您可以避免 Vector 通过更改您的 ExifArray 变体以保存 Vector ExifValue ,然后使用 Vector.mapM


Following on from a previous post, I've found I'm totally stuck. I'm trying to parse a JSON structure into my own type, and not only am I stuck on how to parse the Array, I'm not even sure if I'm using the Aeson library as intended. Any help would be greatly appreciated.

The code:

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

The test file:

[{
  "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"]
}]

解决方案

You have to follow the type of parseJSON a little bit down a rabbit trail, but once you recognize what (Array a) represents, it should be straightforward.

parseJSON has type Value -> Parser a, so (Array a) has type Value. One of the variants in the Value type is Array Array, so the a in (Array a) must be of the type Array, which is defined as Vector Value. The Values inside that Vector are what you want to call parseJSON on to return your list, so check out what you can do with a Vector.

The easiest approach would probably to convert a to a list with Vector.toList, and then use mapM to parse the Values.

Alternately, you could avoid the Vector to list conversion by changing your ExifArray variant to hold Vector ExifValue, and then using Vector.mapM.

这篇关于Haskell,Aeson&amp; JSON解析为自定义类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆