3

I want to create a dynamic model from my data, create JSON from it, and load it in another location.

I can't find a way to define a field in a way, that should it is optional, but when data exists for that field - it would be validated.

This is for required field: 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)

The above configuration generates JSON model that makes fields optional and typed, but then I validate by using the input data I can't pass None values - '$.inputs.0.Field', 'message': "None is not of type 'string'"

So my question - how to declare a field that would validate input, but only when it's not None. And in such a manner, that I could create JSON schema and load it in another location.

3
  • 1
    I had the same issue as well (with predefined models). At the moment there is no support for fields that are optional, as it seems that for the author either you have all the data or none. This issue could help github.com/samuelcolvin/pydantic/issues/990 Commented Sep 8, 2020 at 9:25
  • Yeah, implemented workaround based on that issue. Commented Sep 8, 2020 at 13:14
  • Sorry, I tend to face similar problems with fastAPI when I want only certain fields to be updated, I have to resubmit the whole data object and verify that some old things match... Commented Sep 8, 2020 at 13:20

2 Answers 2

2

Implemented workaround based on suggestions in 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()
Sign up to request clarification or add additional context in comments.

Comments

0
Foo = create_model("Foo", foo = (int, None))

Foo(foo=None)
# Foo(foo=None)

Foo()
# Foo(foo=None)

Foo(foo=3)
# Foo(foo=3)

Is this your desired result?

2 Comments

This is not dynamic since you know that you are receiving foo. What if I don't know what key is coming in a json?
See Martynas Jurkus's answer, you can use a dict define the code, and use **kwargs as the arguments of create_model

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.