【问题标题】:Create dynamic Pydantic model with typed optional values使用键入的可选值创建动态 Pydantic 模型
【发布时间】:2025-12-03 11:35:01
【问题描述】:

我想从我的数据创建一个动态模型,从中创建 JSON,然后将其加载到另一个位置。

我找不到以某种方式定义字段的方法,它应该是可选的,但是当该字段存在数据时 - 它将被验证。

这是必填字段: fields[col_name] = (data_type, None)

# resolve types for data
data_type = resolve_type(data)
required = is_required(data)
if required:
  fields[col_name] = (data_type, ...)
else:
  fields[col_name] = (data_type, None) <--- unclear

...

pydantic.create_model(name, **fields)

上述配置生成 JSON 模型,该模型使字段可选和键入,但随后我使用无法传递 None 值 - '$.inputs.0.Field', 'message': "None is not of type 'string'" 的输入数据进行验证

所以我的问题 - 如何声明一个可以验证输入的字段,但前提是它不是无。 并且以这种方式,我可以创建 JSON 模式并将其加载到另一个位置。

【问题讨论】:

  • 我也遇到了同样的问题(使用预定义的模型)。目前不支持可选字段,因为对于作者来说,您要么拥有所有数据,要么没有。这个问题可以帮助github.com/samuelcolvin/pydantic/issues/990
  • 是的,基于该问题实施了解决方法。
  • 抱歉,当我只想更新某些字段时,我往往会面临使用 fastAPI 的类似问题,我必须重新提交整个数据对象并验证某些旧内容是否匹配...

标签: python pydantic


【解决方案1】:

根据https://github.com/samuelcolvin/pydantic/issues/990 中的建议实施解决方法

optional_fields = list()
if required:
  fields[col_name] = (data_type, ...)
else:
  fields[col_name] = (data_type, None)
  optional_fields.append(col_name)

model = pydantic.create_model(name, **fields)

def schema_extra(schema, model):
    for column in optional_fields:
        original_type = schema["properties"][column]["type"]
        schema["properties"][column].update({"type": ["null", original_type]})

model.__config__.schema_extra = schema_extra

schema_json = model.schema_json()

【讨论】:

    【解决方案2】:
    Foo = create_model("Foo", foo = (int, None))
    
    Foo(foo=None)
    # Foo(foo=None)
    
    Foo()
    # Foo(foo=None)
    
    Foo(foo=3)
    # Foo(foo=3)
    

    这是你想要的结果吗?

    【讨论】: