Python-jsonschema的pydantic类验证

发布于 2025-01-31 12:46:04 字数 1867 浏览 2 评论 0原文

因此,我们使用Pydantic和Python-Jsonschema来验证用户输入。用于内部验证的Pydantic和Python-Jsonschema在门户网站上进行验证。而且我遇到了一个有趣的问题,我无法将其缠住。

示例代码:

from pydantic import BaseModel
import typing as tp
import jsonschema

class Pet(BaseModel):
    pet_type: tp.Optional[tp.Literal['cat', 'dog']]

params = {'pet_type': None}
myPet = Pet(**params)
print(myPet.pet_type)

try:
    jsonschema.validate(instance=params, schema=Pet.schema())
    print('Passed validaton on None')
except Exception as e:
    print('Failed validation on None')

因此,根据 pydantic文档tp.union。这意味着上面的代码应读为tp.union [tp.literal ['cat','dog'],无]。这意味着动物类型可以是“猫”,“狗”,也可以是“狗”,对吗?

好吧,架构似乎可以确认,由于pet.schema()输出为以下,而无需“必需”作为pet_type:

{
  'title': 'Pet',
  'type': 'object',
  'properties': {
    'pet_type': {
      'title': 'Pet Type',
      'enum': ['cat', 'dog'],
      'type': 'string'
    }
  }
}

但是,如果运行代码,

ValidationError: None is not one of ['cat', 'dog']

Failed validating 'enum' in schema['properties']['pet_type']:
    {'enum': ['cat', 'dog'], 'title': 'Pet Type', 'type': 'string'}

On instance['pet_type']:
    None

则 在jsonschema验证中失败了。成为“猫”,“狗”,或者没有,Jsonschema仍然失败。

Pydantic代码,Python-Jsonschema代码或我们对Pydantic的使用是一个问题吗?

编辑: 为了进一步缩小原因,我尝试手动创建一个模式并通过JSonschema验证它。手动通行证,pydantic没有:

schema_manual = {
    'title': 'Pet',
    'type': 'object',
    'properties': {
        'pet_type': {
            'title': 'Pet Type',
            'oneOf': [
                {'type': 'string', 'enum': ['cat', 'dog']}, 
                {'type': 'null'}
            ]
        }
    }
}

validate(instance=params, schema=schema_manual)
validate(instance=params, schema=Pet.schema())

So we're using pydantic and python-jsonschema to validate user input. Pydantic for internal validation, and python-jsonschema for validation on the portal. And I've come across an interesting issue, and I can't wrap my head around it.

Example code:

from pydantic import BaseModel
import typing as tp
import jsonschema

class Pet(BaseModel):
    pet_type: tp.Optional[tp.Literal['cat', 'dog']]

params = {'pet_type': None}
myPet = Pet(**params)
print(myPet.pet_type)

try:
    jsonschema.validate(instance=params, schema=Pet.schema())
    print('Passed validaton on None')
except Exception as e:
    print('Failed validation on None')

So, according to Pydantic documentation, tp.Optional is a shorthand for tp.Union. Which means that the code above should be read as tp.Union[tp.Literal['cat', 'dog'], None]. Meaning that animal type can be 'cat', 'dog' or None, right?

Well, schema seems to confirm that, with Pet.schema() output being the following, and no 'required' as pet_type:

{
  'title': 'Pet',
  'type': 'object',
  'properties': {
    'pet_type': {
      'title': 'Pet Type',
      'enum': ['cat', 'dog'],
      'type': 'string'
    }
  }
}

However, if the code is run it fails at jsonschema validation with message:

ValidationError: None is not one of ['cat', 'dog']

Failed validating 'enum' in schema['properties']['pet_type']:
    {'enum': ['cat', 'dog'], 'title': 'Pet Type', 'type': 'string'}

On instance['pet_type']:
    None

So even though pydantic specifies that attribute can be 'cat', 'dog' or None, jsonschema still fails.

Is that a problem with pydantic code, python-jsonschema code or our use of pydantic?

EDIT:
To try to further narrow down the cause, I've tried creating a schema manually and validating it through jsonschema. Manual passes, pydantic one doesn't:

schema_manual = {
    'title': 'Pet',
    'type': 'object',
    'properties': {
        'pet_type': {
            'title': 'Pet Type',
            'oneOf': [
                {'type': 'string', 'enum': ['cat', 'dog']}, 
                {'type': 'null'}
            ]
        }
    }
}

validate(instance=params, schema=schema_manual)
validate(instance=params, schema=Pet.schema())

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文