gpt4 book ai didi

json - 防止 Aeson parseJSON 中的未知字段名称

转载 作者:行者123 更新时间:2023-12-05 03:42:08 32 4
gpt4 key购买 nike

具有以下类型和实例派生:

{-# LANGUAGE RecordWildCards #-}

import Data.Aeson
import Data.Text

data MyParams = MyParams {
mpFoo :: Maybe Text,
mpBar :: Maybe Text
} deriving Show

instance FromJSON MyParams where
parseJSON = withObject "MyParams" $ \q -> do
mpFoo <- q .:? "foo"
mpBar <- q .:? "bar"
pure MyParams {..}

我如何确保以下 JSON 会失败?

{
"foo": "this is a valid field name",
"baa": "this is an invalid field name"
}

使用上面的代码,这个 JSON 成功了,因为 1. bar 是可选的,所以 parseJSON 如果找不到它也不会提示,以及 2. baa不会抛出任何错误,而是会被忽略。 (1) 和 (2) 的组合意味着字段名称中的拼写错误无法被捕获并且会被默默接受,尽管生成了不正确的结果 (MyParams { foo = Just(this is a valid field name), bar = Nothing ).

事实上,这个 JSON 字符串也应该失败:

{
"foo": "this is fine",
"bar": "this is fine",
"xyz": "should trigger failure but doesn't with the above code"
}

TL;DR:当 JSON 包含与 foobar< 不匹配的任何字段名称时,我如何使 parseJSON 失败?

最佳答案

不要忘记您在withObject 中访问的q 只是一个HashMap。所以,你可以这样写:

import qualified Data.HashMap.Strict as HM
import qualified Data.HashSet as HS
import Control.Monad (guard)

instance FromJSON MyParams where
parseJSON = withObject "MyParams" $ \q -> do
mpFoo <- q .:? "foo"
mpBar <- q .:? "bar"
guard $ HM.keysSet q `HS.isSubsetOf` HS.fromList ["foo","bar"]
pure MyParams {..}

这将确保 json 最多 元素 "foo""bar"

但是,考虑到 aeson 免费为您提供这一切,这确实有点过分了。如果您可以派生 Generic,那么您只需调用 genericParseJSON,如下所示:

{-# LANGUAGE DeriveGeneric #-}

data MyParams = MyParams {
mpFoo :: Maybe Text,
mpBar :: Maybe Text
} deriving (Show, Generic)

instance FromJSON MyParams where
parseJSON = genericParseJSON $ defaultOptions
{ rejectUnknownFields = True
, fieldLabelModifier = map toLower . drop 2
}

这里我们通过两种方式调整默认解析选项:首先,我们告诉它拒绝未知字段,这正是您所要求的,其次,我们告诉它如何获取 "foo" 来自字段名称 "mpFoo"(同样适用于 bar)。

关于json - 防止 Aeson parseJSON 中的未知字段名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67375099/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com