在Python中验证YAML文档

95 投票
11 回答
114340 浏览
提问于 2025-04-16 01:23

XML的一个好处是可以通过XSD来验证文档的正确性。可是,YAML没有这个功能。那么,我该怎么确认我打开的YAML文档是我的应用程序所期望的格式呢?

11 个回答

29

我觉得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文档:

import yaml
def load_doc():
    with open('./my_yaml.yaml', 'r') as stream:
        try:
            return yaml.load(stream)
        except yaml.YAMLError as exception:
            raise exception

## Now, validating the yaml file is straightforward:
from cerberus import Validator
schema = eval(open('./schema.py', 'r').read())
    v = Validator(schema)
    doc = load_doc()
    print(v.validate(doc, schema))
    print(v.errors)

请记住,Cerberus是一个通用的数据验证工具,这意味着它不仅支持YAML格式,还可以支持其他格式,比如JSON、XML等等。

63

因为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'

不过有一个问题,如果你的模式(schema)跨越多个文件,并且你用"$ref"来引用其他文件,那么那些其他文件可能需要是JSON格式。我想是这样的。不过可能有其他解决办法。在我自己的项目中,我尝试用JSON文件来定义模式,而实例则使用YAML格式。

14

试试Rx吧,它有Python的实现,支持处理JSON和YAML格式的数据。

在Rx网站上说:

“当你给你的网络服务添加一个API时,你需要选择一种方式来编码你要发送的数据。XML是一个常见的选择,但它很快就会变得复杂和麻烦。很多网络服务的开发者希望避免使用XML,而是选择一些简单的数据格式,这些格式能对应现代编程语言中常见的数据结构。换句话说,就是JSON和YAML。”

不过,虽然这些格式让传递复杂数据结构变得简单,但它们没有验证数据的系统。XML有XML模式和RELAX NG这样的工具,但这些标准复杂且有时让人困惑。它们不太适合JSON这种数据结构,如果你想避免使用XML来编码数据,那么为了验证第一个XML而写更多的XML,可能就更让人头疼了。

Rx的目的是提供一个与JSON风格的数据结构相匹配的数据验证系统,并且使用起来和JSON一样简单。

撰写回答