datamodel-code-generator
datamodel-code-generator copied to clipboard
`AnyUrl` does not accept URIs without host
Describe the bug
When generating Pydantic models from a jsonschema, the type uri is mapped to AnyUrl, which is incorrect as URL is a subset of URI. A URI string with no host field (like something://) is a valid URI but not a valid URL.
To Reproduce
- Generate Pydantic models from a schema containing a
uritype field - Try to set that field to a host-less URI like
something:// - An exception is thrown:
pydantic_core._pydantic_core.ValidationError: 1 validation error for TestModel
field_name
Input should be a valid URL, empty host [type=url_parsing, input_value='something://', input_type=str]
For further information visit https://errors.pydantic.dev/2.10/v/url_parsing
Example schema:
...
"field_name": {
"type": "string",
"format": "uri"
}
...
Used commandline:
$ python -m datamodel_code_generator --input-file-type jsonschema --input "$SCHEMA_DIR/" --output "$OUTPUT" --output-model-type pydantic_v2.BaseModel
Expected behavior
uri fields should allow any valid URI, not just URLs.
Version:
- Python version: 3.12.6
- datamodel-code-generator version: 0.26.3
Additional context
My use-case is handling data in the GBFS format, which is an open standard format for exchanging data about bike-sharing, car-sharing and other similar micromobility systems. This issue occurs with the rental_apps.android.discovery_uri field of the system_information endpoint, which comes with this explanation:
URI that can be used to discover if the rental Android app is installed on the device (for example, using PackageManager.queryIntentActivities()). This intent is used by viewing apps to prioritize rental apps for a particular user based on whether they already have a particular rental app installed.
Example value: com.example.android://
I've constructed this model to handle such URIs and confirmed it works:
from pydantic.networks import _BaseUrl, UrlConstraints
class Uri(_BaseUrl):
_constraints = UrlConstraints()
Ideally something like this would be implemented in Pydantic itself, but it could also be put into this library.