容错JSON解析 [英] Fault tolerant JSON parsing

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

问题描述

我使用Data.Aeson将一些JSON解析为Record类型。有时候数据会被添加到JSON中,这会破坏我的代码,因为Aeson会抱怨以下几点:


期望的对象与21
名称/值对,但得到23名称/值

我真的更喜欢解析容错的JSON方式 - 我不关心是否有更多的字段在以后添加到JSON中,只是解析任何你可以!有没有办法实现这种容错?这是我的代码:

  myRecordFromJSONString :: BS.ByteString  - >也许MyRecord 
myRecordFromJSONString s = case Data.Attoparsec.parse $ b $ j的完成_rest res - > Data.Aeson.Types.parseMaybe parseJSON res
_ - > Nothing

我应该补充说我使用Data.Aeson.TH中的deriveJSON来生成解析代码。如果我手动编写FromJSON代码,它是容错的,但我不想那样做......

如果我手动编写FromJSON代码您正在使用GHC 7.2或7.4, aeson 中的新仿制支持不检查额外字段。


$ b

  { - #LANGUAGE DeriveGeneric # - } 
{ - #LANGUAGE OverloadedStrings# - }

导入Data.Aeson
导入限定的Data.Aeson.Types
导入Data.Attoparsec
导入合格的Data.ByteString作为BS
import Data.ByteString.Char8()
import GHC.Generics

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

实例FromJSON MyRecord

myRecordFromJSONString :: BS.ByteString - >也许MyRecord
myRecordFromJSONString s = case Data.Attoparsec.parse $ b $ j的完成_rest res - > Data.Aeson.Types.parseMaybe parseJSON res
_ - > Nothing

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

运行这个会导致TH派生实例失败, field2'不存在于记录中。 Generic 实例返回所需的结果:

  Just(MyRecord {field1 = 1})


I'm using Data.Aeson to parse some JSON into a Record type. From time to time data is added to the JSON and this breaks my code as Aeson complains something to the effect of:

expected Object with 21 name/value pairs but got 23 name/value

I'd really prefer to parse the JSON in a fault tolerant way -- I don't care if more fields are added to the JSON at a later date, just parse whatever you can! Is there a way to achieve this fault tolerance? Here's my code:

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

I should add that I'm using deriveJSON from Data.Aeson.TH to generate the parsing code. If I write the FromJSON code manually it's fault tolerant but I'd like to not have to do that...

解决方案

If you are using GHC 7.2 or 7.4, the new generics support in aeson doesn't check for extra fields. I'm not sure if this is by design or not but we use it for the same reason.

{-# 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

Running this would fail with the TH derived instance due to 'field2' not existing in the record. The Generic instance returns the desired result:

Just (MyRecord {field1 = 1})

这篇关于容错JSON解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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