我正在寻找一种字典验证的解决方案,其中一个约束是is in
约束,其中被认为有效的值来自被验证的字典本身。
例如,想象一下下面的伪模式
{
"notions" : [ string ],
"category" : [ is in notions ]
}
为了清楚起见,我还口头表达了这个伪模式的约束。这些是我想要验证的约束,be d
the dictionary to validate:
set(d.keys()) == {"notions", "categories"}
isinstance(d["notions"], list)
isinstance(notion, str) for notion in d["notions"]
isinstance(d["category"], list)
element is in d["notion"] for element in d["category"]
不要问,这个特定的数据结构是否有任何意义。事实并非如此。我只是想为我的问题创建一个最小的例子。我的实际字典模式要复杂得多,并且将有多个对字典中的值的引用。这就是为什么我希望避免手动定义和验证约束,而更喜欢基于模式的解决方案。
我已经研究了一些模式验证库,但是我没有发现任何地方都包含这个特性。有没有一个基于一些库的解决方案,可能会有一些小的调整?我宁愿不要第二次发明轮子。
发布于 2019-03-16 02:35:24
通常,模式验证器尽量避免将数据拉入验证器中。例如,JSON-schema standard是debating adding $data
access in schemas,但是(还没有)实现这个想法(即使他们有several use cases for it)。
一般的反对意见是,使验证模式依赖于它正在验证的数据会使验证很难保持与上下文无关(这使实现更容易,并使并行验证更容易),并且使模式的静态分析变得更加困难(因为模式在运行时随数据而变化)。
也就是说,Colander project可以做您想做的事情,因为它允许您在Python代码中简单地定义验证器。
例如:
import colander
class Foo(colander.MappingSchema):
@colander.instantiate()
class notions(colander.SequenceSchema):
notion = colander.SchemaNode(colander.String())
@colander.instantiate()
class category(colander.SequenceSchema):
cat = colander.SchemaNode(colander.String())
def validator(self, node, cstruct):
"""Validate that all category values are listed in notions"""
notions = set(cstruct['notions'])
if not notions.issuperset(cstruct['category']):
raise colander.Invalid(
node['category'],
"All categories must be listed in notions"
)
请注意,验证器是在定义notions
和category
的级别上定义的,因为验证器只能访问正在验证的数据的“本地”部分(所有子节点验证都已经发生)。如果您只为category
定义了验证器,那么您就不能访问notions
列表,并且您可以相信已经验证了notions
列表。验证器引发Invalid
异常,第一个参数是category
模式节点,它直接将责任推给该列表中的值。
漏斗模式在反序列化时进行验证;您可以看到Schema.deserialize()
方法的输入是未经验证的数据(漏斗序列化),输出是经过验证和清理的应用程序就绪数据(appdata)。这是因为漏斗还会在缺省的情况下设置缺省值,可以生成元组、集合、HTML值等等,还支持数据准备(清理datetime
等)。当您使用模式处理它时。
通过一些演示输入,上面的模式验证并在成功时返回经过验证的结构:
>>> schema = Foo()
>>> schema.deserialize({'notions': [], 'category': []})
{'notions': [], 'category': []}
>>> schema.deserialize({'notions': ['foo', 'bar'], 'category': []})
{'notions': ['foo', 'bar'], 'category': []}
>>> schema.deserialize({'notions': ['foo', 'bar'], 'category': ['foo']})
{'notions': ['foo', 'bar'], 'category': ['foo']}
>>> schema.deserialize({'notions': ['foo', 'bar'], 'category': ['foo', 'spam']})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../site-packages/colander/__init__.py", line 2381, in deserialize
self.validator(self, appstruct)
File "<string>", line 17, in validator
colander.Invalid: {'category': 'All categories must be listed in notions'}
发布于 2019-03-15 06:46:06
你的字典那么复杂,那你就大错特错了。考虑创建类并将该类的对象存储在字典中。这些类还可以保存其他类的其他对象。这样就避免了字典的嵌套。在类中创建函数以验证其数据。
https://stackoverflow.com/questions/55173021
复制相似问题