Search code examples
jsonschemapydanticpydantic-v2

Pydantic v2 to JSON Schema translation: How to suppress autogeneration of "title" annotation in v2?


I am using Pydantic 2.6.4 to generate JSON schemas. If I write an attribute in a Pydantic model that has no value for "title" in its FieldInfo, Pydantic will always autogenerate one from the name of the attribute when translating the model to a JSON Schema. How do I prevent this?

Consider the following Pydantic model:

class Model(BaseModel):
    a: int

The result of print(json.dumps(Model.model_json_schema()) will be:

{
  "properties": {
    "a": {
      "title": "A",
      "type": "integer"
    }
  },
  "title": "Model",
  "type": "object"
} 

Note there is no Field(title="A") specified for the attribute a. Pydantic is autogenerating this. How do I get Pydantic to output:

{
  "properties": {
    "a": {
      "type": "integer"
    }
  },
  "title": "Model",
  "type": "object"
} 

Pydantic v1 had a rather complicated solution. You had to overwrite schema_extra in the Config subclass as follows:

class Model(BaseModel):
    a: int

    class Config:
        @staticmethod
        def schema_extra(schema: dict[str, Any], model: type['Model']) -> None:
            for prop in schema.get('properties', {}).values():
                prop.pop('title', None)

However the documentation for Pydantic v2 says that Config is now deprecated. What is the solution for Pydantic v2?

Thank you!


Solution

  • After digging a bit deeper into the pydantic code I found a nice little way to prevent this. There is a method called field_title_should_be_set(...) in GenerateJsonSchema which can be subclassed and provided to model_json_schema(...).

    I'm not sure if the way I've overwritten the method is sufficient for each edge case but at least for this little test class it works as intended.

    from pydantic import BaseModel
    from pydantic._internal._core_utils import is_core_schema, CoreSchemaOrField
    from pydantic.json_schema import GenerateJsonSchema
    
    
    class Test(BaseModel):
        a: int
    
    class GenerateJsonSchemaWithoutDefaultTitles(GenerateJsonSchema):
        def field_title_should_be_set(self, schema: CoreSchemaOrField) -> bool:
            return_value = super().field_title_should_be_set(schema)
            if return_value and is_core_schema(schema):
                return False
            return return_value
    
    json_schema = Test.model_json_schema(schema_generator=GenerateJsonSchemaWithoutDefaultTitles)
    assert "title" not in json_schema["properties"]["a"]