2012-05-15 11 views
11

Data.Aesonを使用して、JSONの一部を解析してレコードタイプにしています。随時データをJSONに追加され、アイソーンはの効果に何かを文句を言うので、これは私のコードを壊す:フォールトトレランスのJSON解析

予想21 名前/値のペアを持つオブジェクトが、得た23名/値

JSONをフォールトトレラントな方法で解析する方が好きです。後でJSONに追加されるフィールドが増えれば気にしません。このフォールトトレランスを実現する方法はありますか?私のコードは次のとおりです。

myRecordFromJSONString :: BS.ByteString -> Maybe MyRecord 
myRecordFromJSONString s = case Data.Attoparsec.parse json s of 
    Done _rest res -> Data.Aeson.Types.parseMaybe parseJSON res 
    _    -> Nothing 

私はData.Aeson.THのderiveJSONを使って解析コードを生成しています。 FromJSONコードを手作業で書くとフォールトトレラントですが、私はそれをする必要はありません。

答えて

6

GHC 7.2または7.4を使用している場合、aesonの新しいジェネリックサポートは追加フィールドをチェックしません。私はこれが設計によるものかどうかはわかりませんが、同じ理由でそれを使用しています。

{-# LANGUAGE DeriveGeneriC#-} 
{-# LANGUAGE OverloadedStrings #-} 

import Data.Aeson 
import qualified Data.Aeson.Types 
import Data.Attoparsec 
import qualified Data.ByteString as BS 
import Data.ByteString.Char8() 
import GHC.Generics 

data MyRecord = MyRecord 
    { field1 :: Int 
    } deriving (Generic, Show) 

instance FromJSON MyRecord 

myRecordFromJSONString :: BS.ByteString -> Maybe MyRecord 
myRecordFromJSONString s = case Data.Attoparsec.parse json s of 
    Done _rest res -> Data.Aeson.Types.parseMaybe parseJSON res 
    _    -> Nothing 

main :: IO() 
main = do 
    let parsed = myRecordFromJSONString "{ \"field1\": 1, \"field2\": 2 }" 
    print parsed 

これは、レコードに 'field2'が存在しないため、TH派生インスタンスでは失敗します。 Genericインスタンスは、希望する結果を返します。

Just (MyRecord {field1 = 1})