13

以前の投稿に続いて、私は完全に立ち往生していることがわかりました。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

テストファイル:

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

3 に答える 3

11

parseJSONうさぎの小道を少し下るタイプをたどる必要がありますが、何(Array a)が表されているかを理解すれば、それは簡単なはずです。

parseJSONタイプValue -> Parser aがあり、(Array a)タイプがありValueます。タイプのバリアントの1つは、であるため、inはValueタイプがである必要があります。これは。として定義されます。その中のsは、リストを返すために呼び出したいものなので、で何ができるかを確認してください。Array Arraya(Array a)ArrayVector ValueValueVectorparseJSONVector

最も簡単なアプローチは、おそらく、を使用aしてリストに変換し、Vector.toListを使用mapMしてを解析することValuesです。

または、バリアントをholdに変更してから、を使用することで、 Vectortoリストの変換を回避できます。ExifArrayVector ExifValueVector.mapM

于 2011-08-03T20:46:17.733 に答える
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
于 2011-08-04T02:33:07.670 に答える
3

aesonライブラリの少し新しいビルド(0.3.2.12)は、JSONインスタンスの自動生成をサポートしています。

{-# LANGUAGE TemplateHaskell #-}

import Data.Aeson
import Data.Aeson.TH (deriveJSON)
import Data.Attoparsec
import qualified Data.ByteString as B
import qualified Data.Text as T

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

deriveJSON id ''Exif
deriveJSON id ''ExifValue

parseExifFile = fmap parseExifData . B.readFile

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

生産:

instance ToJSON Exif where
  { toJSON
      = \ value_a1Va
          -> case value_a1Va of { Exif arg1_a1Vb -> toJSON arg1_a1Vb } }
instance FromJSON Exif where
  { parseJSON
      = \ value_a1Vc
          -> case value_a1Vc of {
               arg_a1Vd -> (Exif Data.Functor.<$> parseJSON arg_a1Vd) } }

instance ToJSON ExifValue where
  { toJSON
      = \ value_a1Wd
          -> case value_a1Wd of {
               ExifText arg1_a1We
                 -> object [(T.pack "ExifText" .= toJSON arg1_a1We)]
               ExifInt arg1_a1Wf
                 -> object [(T.pack "ExifInt" .= toJSON arg1_a1Wf)]
               ExifDouble arg1_a1Wg
                 -> object [(T.pack "ExifDouble" .= toJSON arg1_a1Wg)]
               ExifBool arg1_a1Wh
                 -> object [(T.pack "ExifBool" .= toJSON arg1_a1Wh)]
               ExifArray arg1_a1Wi
                 -> object [(T.pack "ExifArray" .= toJSON arg1_a1Wi)] } }
instance FromJSON ExifValue where
  { parseJSON
      = \ value_a1Wj
          -> case value_a1Wj of {
               Object obj_a1Wk
                 -> case Data.Map.toList obj_a1Wk of {
                      [(conKey_a1Wl, conVal_a1Wm)]
                        -> case conKey_a1Wl of {
                             _ | (conKey_a1Wl == T.pack "ExifText")
                               -> case conVal_a1Wm of {
                                    arg_a1Wn
                                      -> (ExifText Data.Functor.<$> parseJSON arg_a1Wn) }
                               | (conKey_a1Wl == T.pack "ExifInt")
                               -> case conVal_a1Wm of {
                                    arg_a1Wo
                                      -> (ExifInt Data.Functor.<$> parseJSON arg_a1Wo) }
                               | (conKey_a1Wl == T.pack "ExifDouble")
                               -> case conVal_a1Wm of {
                                    arg_a1Wp
                                      -> (ExifDouble Data.Functor.<$> parseJSON arg_a1Wp) }
                               | (conKey_a1Wl == T.pack "ExifBool")
                               -> case conVal_a1Wm of {
                                    arg_a1Wq
                                      -> (ExifBool Data.Functor.<$> parseJSON arg_a1Wq) }
                               | (conKey_a1Wl == T.pack "ExifArray")
                               -> case conVal_a1Wm of {
                                    arg_a1Wr
                                      -> (ExifArray Data.Functor.<$> parseJSON arg_a1Wr) }
                               | otherwise -> Control.Monad.mzero }
                      _ -> Control.Monad.mzero }
               _ -> Control.Monad.mzero } }
于 2011-11-06T21:29:58.993 に答える