12

Data.Aesonを使用して、JSONをレコードタイプに解析しています。時々データがJSONに追加され、Aesonが次のような影響について不平を言うので、これは私のコードを壊します。

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コードを手動で記述した場合、フォールトトレラントですが、それを行う必要はありません...

4

1 に答える 1

7

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})
于 2012-05-15T20:59:15.780 に答える