在python中验证yaml文档

时间:2010-07-16 06:55:49

标签: python yaml validation

XML的一个好处是能够针对XSD验证文档。 YAML没有此功能,那么如何验证我打开的YAML文档是否符合我的应用程序所期望的格式?

10 个答案:

答案 0 :(得分:26)

鉴于JSON和YAML是非常相似的野兽,您可以使用JSON-Schema来验证YAML的相当大的子集。这是一段代码段(您需要安装PyYAMLjsonschema):

from jsonschema import validate
import yaml

schema = """
type: object
properties:
  testing:
    type: array
    items:
      enum:
        - this
        - is
        - a
        - test
"""

good_instance = """
testing: ['this', 'is', 'a', 'test']
"""

validate(yaml.load(good_instance), yaml.load(schema)) # passes

# Now let's try a bad instance...

bad_instance = """
testing: ['this', 'is', 'a', 'bad', 'test']
"""

validate(yaml.load(bad_instance), yaml.load(schema))

# Fails with:
# ValidationError: 'bad' is not one of ['this', 'is', 'a', 'test']
#
# Failed validating 'enum' in schema['properties']['testing']['items']:
#     {'enum': ['this', 'is', 'a', 'test']}
#
# On instance['testing'][3]:
#     'bad'

这样做的一个问题是,如果您的架构跨越多个文件并使用"$ref"引用其他文件,那么其他文件将需要是JSON,我想。但是可能有办法解决这个问题。在我自己的项目中,我正在使用JSON文件指定模式,而实例是YAML。

答案 1 :(得分:9)

尝试Rx,它有一个Python实现。它适用于JSON和YAML。

来自Rx网站:

“在为您的Web服务添加API时,您必须选择如何对您在整个生产线上发送的数据进行编码.XML是一种常见的选择,但它很快就会变得神秘而繁琐。很多网络服务作者都希望避免考虑XML,而是选择提供与现代编程语言中的通用数据结构相对应的一些简单数据类型的格式。换句话说,JSON和YAML。

不幸的是,虽然这些格式可以轻松传递复杂的数据结构,但它们缺少验证系统。 XML具有XML Schema和RELAX NG,但这些标准很复杂,有时令人困惑。它们对JSON提供的数据结构并不是很容易移植,如果你想避免将XML作为数据编码,那么编写更多的XML来验证第一个XML可能就不那么吸引人了。

Rx旨在提供一个数据验证系统,与JSON风格的数据结构相匹配,并且与JSON本身一样易于使用。“

答案 2 :(得分:9)

是的 - 支持验证对于许多重要的用例至关重要。参见例如YAML and the importance of Schema Validation « Stuart Gunter

如前所述,有Rx,可用于各种语言,Kwalify用于Ruby和Java。

另见PyYAML讨论:YAMLSchemaDiscussion

相关工作是JSON Schema,甚至还有一些IETF标准化活动(draft-zyp-json-schema-03 - A JSON Media Type for Describing the Structure and Meaning of JSON Documents

答案 3 :(得分:5)

这些看起来不错。 yaml解析器可以处理语法错误,其中一个库可以验证数据结构。

答案 4 :(得分:4)

我发现Cerberus非常可靠,有很好的文档和直接使用。

这是一个基本的实现示例:

my_yaml.yaml

name: 'my_name'
date: 2017-10-01
metrics:
  percentage:
    value: 87
    trend: stable

schema.py中定义验证架构:

{
    'name': {
        'required': True,
        'type': 'string'
    },
    'date': {
        'required': True,
        'type': 'date'
    },
    'metrics': {
        'required': True,
        'type': 'dict',
        'schema': {
            'percentage': {
                'required': True,
                'type': 'dict',
                'schema': {
                    'value': {
                        'required': True,
                        'type': 'number',
                        'min': 0,
                        'max': 100
                    }
                    'trend': {
                        'type': 'string',
                        'nullable': True,
                        'regex': '^(?i)(down|equal|up)$'
                    }
                }
            }
        }
    }
}

使用PyYaml加载yaml文档:

def __load_doc():
        with open(__yaml_path, 'r') as stream:
            try:
                return yaml.load(stream)
            except yaml.YAMLError as exception:
                raise exception

评估yaml文件非常简单:

schema = eval(open('PATH_TO/schema.py', 'r').read())
        v = Validator(schema)
        doc = __load_doc()
        print v.validate(doc, schema)
        print v.errors

请记住,Cerberus是一种不可知的数据验证工具,这意味着它可以支持YAML以外的格式,例如JSON,XML等。

答案 5 :(得分:3)

我遇到了同样的情况。我需要验证YAML的元素。

首先我想到了#PyYAML标签'是最好,最简单的方法。但后来又决定选择PyKwalify'它实际上定义了YAML的模式。

PyYAML标签:

YAML文件具有标记支持,我们可以通过为数据类型添加前缀来强制执行此基本检查。 (例如)对于整数 - !! int" 123"

有关PyYAML的更多信息:http://pyyaml.org/wiki/PyYAMLDocumentation#Tags 这很好,但是如果你要将它暴露给最终用户,那么它可能会引起混淆。 我做了一些研究来定义YAML的模式。这个想法就像我们可以使用相应的模式验证YAML以进行基本数据类型检查。甚至我们的自定义验证,如IP地址,随机字符串也可以在此添加。所以我们可以单独使用我们的模式,使YAML简单易读。

我无法发布更多链接。请为YAM' L谷歌架构查看架构讨论。

PyKwalify:

有一个名为PyKwalify的软件包可用于此目的:https://pypi.python.org/pypi/pykwalify

此套装最符合我的要求。 我在本地设置中用一个小例子尝试了这个,并且正在工作。下面是示例模式文件。

#sample schema

type: map
mapping:
    Emp:
        type:    map
        mapping:
            name:
                type:      str
                required:  yes
            email:
                type:      str
            age:
                type:      int
            birth:
                type:     str

此架构的有效YAML文件

---
Emp:
    name:   "abc"
    email:  "xyz@gmail.com"
    age:    yy
    birth:  "xx/xx/xxxx"

谢谢

答案 6 :(得分:1)

您可以将YAML文档作为 dict 加载,并使用库 schema 进行检查:

from schema import Schema, And, Use, Optional, SchemaError
import yaml

schema = Schema(
        {
            'created': And(datetime.datetime),
            'author': And(str),
            'email': And(str),
            'description': And(str),
            Optional('tags'): And(str, lambda s: len(s) >= 0),
            'setup': And(list),
            'steps': And(list, lambda steps: all('=>' in s for s in steps), error='Steps should be array of string '
                                                                                  'and contain "=>" to separate'
                                                                                  'actions and expectations'),
            'teardown': And(list)
        }
    )

with open(filepath) as f:
   data = yaml.load(f)
   try:
       schema.validate(data)
   except SchemaError as e:
       print(e)

答案 7 :(得分:0)

我不知道python解决方案。但是有一个名为kwalify的YAML的ruby模式验证器。如果你没有遇到python库,你应该可以使用子进程访问它。

答案 8 :(得分:0)

您可以使用python的yaml lib显示已加载文件的message / char / line / file。

#!/usr/bin/env python

import yaml

with open("example.yaml", 'r') as stream:
    try:
        print(yaml.load(stream))
    except yaml.YAMLError as exc:
        print(exc)

可以通过exc.problem

访问错误消息

访问exc.problem_mark以获取<yaml.error.Mark>个对象。

此对象允许您访问属性

  • 名称
  • 线

因此,您可以创建自己的指针来解决问题:

pm = exc.problem_mark
print("Your file {} has an issue on line {} at position {}".format(pm.name, pm.line, pm.column))

答案 9 :(得分:0)

我包含了一些与json相关的现有python库旨在能够将它们与yaml一起使用

生成的python库主要包装...

  • jsonschema - 针对json个文件的json-schema个文件的验证程序,用于支持yaml文件对json-schema个文件的验证yaml个文件1}} - 格式。

  • jsonpath-ng - 用于python的JSONPath实现,包含在JSONPath文件上直接支持yaml选项。

...并且可以在github上找到:

https://github.com/yaccob/ytools

可以使用pip安装:

pip install ytools

验证示例(来自https://github.com/yaccob/ytools#validation):

import ytools
ytools.validate("test/sampleschema.yaml", ["test/sampledata.yaml"])

您还没有开箱即用,正在验证yaml格式的外部架构。

ytools并未提供之前不存在的任何内容 - 它只是使某些现有解决方案的应用更加灵活和方便。