- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
在我们的 GraphQL API 更新中,只有模型 _id
字段是必需的,因此 !
在下面的 SDL 语言代码中。其他字段如name
不必包含在更新中,但也不能有 null
值(value)。目前,不包括 !
从名称字段允许最终用户不必传递 name
在更新中,但它允许他们传递 null
name
的值在,这是不允许的。
A null
值让我们知道需要从数据库中删除一个字段。
下面是一个会导致问题的模型示例 - Name
自定义标量不允许空值,但 GraphQL 仍然允许它们通过:
type language {
_id: ObjectId
iso: Language_ISO
auto_translate: Boolean
name: Name
updated_at: Date_time
created_at: Date_time
}
input language_create {
iso: Language_ISO!
auto_translate: Boolean
name: Name!
}
input language_update {
_id: ObjectId!
iso: Language_ISO!
auto_translate: Boolean
name: Name
}
当传递一个 null 值时,它会绕过我们的标量,因此如果 null 不是允许的值,我们就不会抛出用户输入验证错误。
我知道 !
表示 non-nullable
并且缺少 !
表示该字段可以为空,但令人沮丧的是,据我所知,如果某个字段不是必需/可选的,我们无法为该字段指定确切的值。此问题仅在更新时出现。
有没有什么方法可以通过自定义标量来解决这个问题,而不必将逻辑硬编码到每个更新解析器中,这看起来很麻烦?
应该失败的示例突变
mutation tests_language_create( $input: language_update! ) { language_update( input: $input ) { name }}
变量
input: {
_id: "1234",
name: null
}
2018 年 9 月 11 日更新: 作为引用,我找不到解决此问题的方法,因为使用自定义标量、自定义指令和验证规则存在问题。我在 GitHub 上开了一个问题:https://github.com/apollographql/apollo-server/issues/1942
最佳答案
您有效地寻找的是自定义验证逻辑。您可以在构建模式时通常包含的“默认”集之上添加任何您想要的验证规则。下面是一个粗略的示例,说明如何添加规则以在特定类型或标量用作参数时检查空值:
const { specifiedRules } = require('graphql/validation')
const { GraphQLError } = require('graphql/error')
const typesToValidate = ['Foo', 'Bar']
// This returns a "Visitor" whose properties get called for
// each node in the document that matches the property's name
function CustomInputFieldsNonNull(context) {
return {
Argument(node) {
const argDef = context.getArgument();
const checkType = typesToValidate.includes(argDef.astNode.type.name.value)
if (checkType && node.value.kind === 'NullValue') {
context.reportError(
new GraphQLError(
`Type ${argDef.astNode.type.name.value} cannot be null`,
node,
),
)
}
},
}
}
// We're going to override the validation rules, so we want to grab
// the existing set of rules and just add on to it
const validationRules = specifiedRules.concat(CustomInputFieldsNonNull)
const server = new ApolloServer({
typeDefs,
resolvers,
validationRules,
})
编辑:以上仅在您不使用变量时才有效,这在大多数情况下不会很有帮助。作为解决方法,我能够利用 FIELD_DEFINITION 指令来实现所需的行为。可能有多种方法可以解决这个问题,但这里有一个基本示例:
class NonNullInputDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const { resolve = defaultFieldResolver } = field
const { args: { paths } } = this
field.resolve = async function (...resolverArgs) {
const fieldArgs = resolverArgs[1]
for (const path of paths) {
if (_.get(fieldArgs, path) === null) {
throw new Error(`${path} cannot be null`)
}
}
return resolve.apply(this, resolverArgs)
}
}
}
然后在你的架构中:
directive @nonNullInput(paths: [String!]!) on FIELD_DEFINITION
input FooInput {
foo: String
bar: String
}
type Query {
foo (input: FooInput!): String @nonNullInput(paths: ["input.foo"])
}
假设每次在架构中使用 input
时“非空”输入字段都是相同的,您可以将每个 input
的名称映射到一个数组应验证的字段名称。所以你也可以这样做:
const nonNullFieldMap = {
FooInput: ['foo'],
}
class NonNullInputDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const { resolve = defaultFieldResolver } = field
const visitedTypeArgs = this.visitedType.args
field.resolve = async function (...resolverArgs) {
const fieldArgs = resolverArgs[1]
visitedTypeArgs.forEach(arg => {
const argType = arg.type.toString().replace("!", "")
const nonNullFields = nonNullFieldMap[argType]
nonNullFields.forEach(nonNullField => {
const path = `${arg.name}.${nonNullField}`
if (_.get(fieldArgs, path) === null) {
throw new Error(`${path} cannot be null`)
}
})
})
return resolve.apply(this, resolverArgs)
}
}
}
然后在您的架构中:
directive @nonNullInput on FIELD_DEFINITION
type Query {
foo (input: FooInput!): String @nonNullInput
}
关于node.js - GraphQL 中可选但不可为空的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53194116/
我正在尝试将抓取的 xml 输出写入 json。由于项目不可序列化,抓取失败。 从这个问题来看,它建议您需要构建一个管道,未提供的答案超出了问题 SO scrapy serializer 的范围。 所
有没有一种方法可以通过重载函数来区分参数是在编译时可评估还是仅在运行时可评估? 假设我有以下功能: std::string lookup(int x) { return table::va
我正在使用 MVVM 模式编写一个应用程序。我通过将 View 的 DataContext 属性设置为 ViewModel 的实例来向 View 提供数据。一般来说,我只是从那里使用 Binding
对于一个项目,我正在使用带有简单 python module 的传感器收集多个红外命令。 . 我收到如下字节字符串: commando1= b'7g4770CQfwCTVT9bQDAzVEBMagGR
我有一个计算方法,可以在用户使用 Cartridge 作为我的商店框架结账时计算税费。 税 = 税 * 小数(str(settings.SHOP_DEFAULT_TAX_RATE)) 计算工作正常。然
我正在用 pygame 制作一个绘图程序,我想在其中为用户提供一个选项来保存程序的确切状态,然后在稍后重新加载它。在这一点上,我保存了我的全局字典的副本,然后遍历, pickle 每个对象。 pyga
在 C++11 之前,我可以使用它来使类不可复制: private: MyClass(const MyClass&); MyClass& operator=(const MyClass&); 使用 C
大家好 :) 我在我的 VC++ 项目中使用 1.5.4-all (2014-10-22)(适用于 x86 平台的 Microsoft Visual C++ 编译器 18.00.21005.1)。 我
我有一个 python 文件:analysis.py: def svm_analyze_AHE(file_name): # obtain abp file testdata = pd.
这个问题已经有答案了: How to serialize SqlAlchemy result to JSON? (37 个回答) 已关闭 4 年前。 我正在编写小查询来从 mysql 获取数据数据库,
我是 Python 初学者,我在 JSON 方面遇到了一些问题。在我正在使用的教程中有两个函数: def read_json(filename): data = [] if os.pa
我目前正在开发一个针对 iPad 的基于 HTML5 Canvas/JavaScript 的小型绘图应用程序。它在 Safari 中运行。到目前为止,除了一件事之外,一切都进展顺利。 如果我旋转设备,
以下代码无法使用 Visual Studio 2013 编译: #include struct X { X() = default; X(const X&) = delete;
嗨,我制作了一个文本分类分类器,我在其中使用了它,它返回一个数组,我想返回 jsonresponse,但最后一行代码给我错误 'array(['cycling'], dtype =object) 不可
我使用 Flask 和 Flask-Login 进行用户身份验证。 Flask-Sqlalchemy 将这些模型存储在 sqlite 数据库中: ROLE_USER = 0 ROLE_ADMIN =
如果您尝试发送不可 JSON 序列化的对象(列表、字典、整数等以外的任何对象),您会收到以下错误消息: "errorMessage": "Object of type set is not JSON
我在尝试 move std::vector 时遇到崩溃其中 T显然是不可 move 的(没有定义 move 构造函数/赋值运算符,它包含内部指针) 但为什么 vector 的 move 函数要调用 T
我尝试在用户成功登录后将 token 返回给他们,但不断收到以下错误: 类型错误:“字节”类型的对象不可 JSON 序列化 我该如何解决这个问题?这是我到目前为止的代码: if user:
我是一名优秀的程序员,十分优秀!