ID Properties
Basic IDs
Just like value objects, ID objects are supported via a custom class as well.
from pydantic_jsonld.compact import BaseModel, Id, Value
class DatasetModel(BaseModel):
title: Value[str]
measured_property: Value[str]
instrument: Id
license: Id
data = {
"@context": {"@vocab": "http://www.example.org/"},
"title": "Atmospheric CO2 Measurements 2025",
"measuredProperty": "CO2 concentration",
"instrument": {"@id": "http://www.example.org/instrument/mauna-loa-sensor"},
"license": {"@id": "http://www.example.org/licenses/by/4.0/"},
}
model = DatasetModel.model_validate(data)
assert model.title.value == "Atmospheric CO2 Measurements 2025"
assert model.measured_property.value == "CO2 concentration"
assert model.instrument.id == "http://www.example.org/instrument/mauna-loa-sensor"
assert model.license.id == "http://www.example.org/licenses/by/4.0/"
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped == data
from pydantic_jsonld.compact import BaseModel, Id, Value
class SoftwarePackageModel(BaseModel):
name: Value[str]
version: Value[str]
homepage: Id
dependency: Id
data = {
"@context": {"@vocab": "http://www.example.org/"},
"name": "jsonld-compact",
"version": "2.3.0",
"homepage": {"@id": "http://www.example.org/example/jsonld-compact"},
"dependency": {"@id": "http://www.example.org/project/pydantic"},
}
model = SoftwarePackageModel.model_validate(data)
assert model.name.value == "jsonld-compact"
assert model.version.value == "2.3.0"
assert model.homepage.id == "http://www.example.org/example/jsonld-compact"
assert model.dependency.id == "http://www.example.org/project/pydantic"
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped == data
from pydantic_jsonld.compact import BaseModel, Id, Value
class ExhibitModel(BaseModel):
title: Value[str]
creator: Id
location_found: Id
material: Value[str]
data = {
"@context": {"@vocab": "http://www.example.org/"},
"title": "Bronze Age Ritual Blade",
"creator": {"@id": "http://www.example.org/culture/unknown-bronze-age-smith"},
"locationFound": {"@id": "http://www.example.org/place/danube-valley"},
"material": "Bronze",
}
model = ExhibitModel.model_validate(data)
assert model.title.value == "Bronze Age Ritual Blade"
assert model.creator.id == "http://www.example.org/culture/unknown-bronze-age-smith"
assert model.location_found.id == "http://www.example.org/place/danube-valley"
assert model.material.value == "Bronze"
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped == data
Complex IDs
Additional information provided in ID objects is captured as well.
from pydantic_jsonld.compact import BaseModel, Id, Value
class DatasetModel(BaseModel):
title: Value[str]
measured_property: Value[str]
instrument: Id
license: Id
data = {
"@context": {"@vocab": "http://www.example.org/"},
"title": "Atmospheric CO2 Measurements 2025",
"measuredProperty": "CO2 concentration",
"instrument": {
"@id": "http://www.example.org/instrument/mauna-loa-sensor",
"@type": "http://www.example.org/Sensor",
},
"license": {
"@id": "http://www.example.org/licenses/by/4.0/",
"@type": "http://www.example.org/CreativeWorkLicense",
},
}
model = DatasetModel.model_validate(data)
assert model.title.value == "Atmospheric CO2 Measurements 2025"
assert model.measured_property.value == "CO2 concentration"
assert model.instrument.id == "http://www.example.org/instrument/mauna-loa-sensor"
assert model.instrument.type == "http://www.example.org/Sensor"
assert model.license.id == "http://www.example.org/licenses/by/4.0/"
assert model.license.type == "http://www.example.org/CreativeWorkLicense"
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped == data
from pydantic_jsonld.compact import BaseModel, Id, Value
class SoftwarePackageModel(BaseModel):
name: Value[str]
version: Value[str]
homepage: Id
dependency: Id
data = {
"@context": {"@vocab": "http://www.example.org/"},
"name": "jsonld-compact",
"version": "2.3.0",
"homepage": {
"@id": "http://www.example.org/example/jsonld-compact",
"@type": "http://www.example.org/WebPage",
},
"dependency": {
"@id": "http://www.example.org/project/pydantic",
"@type": "http://www.example.org/SoftwareDependency",
},
}
model = SoftwarePackageModel.model_validate(data)
assert model.name.value == "jsonld-compact"
assert model.version.value == "2.3.0"
assert model.homepage.id == "http://www.example.org/example/jsonld-compact"
assert model.homepage.type == "http://www.example.org/WebPage"
assert model.dependency.id == "http://www.example.org/project/pydantic"
assert model.dependency.type == "http://www.example.org/SoftwareDependency"
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped == data
from pydantic_jsonld.compact import BaseModel, Id, Value
class ExhibitModel(BaseModel):
title: Value[str]
creator: Id
location_found: Id
material: Value[str]
data = {
"@context": {"@vocab": "http://www.example.org/"},
"title": "Bronze Age Ritual Blade",
"creator": {
"@id": "http://www.example.org/culture/unknown-bronze-age-smith",
"@type": "http://www.example.org/CulturalGroup",
},
"locationFound": {
"@id": "http://www.example.org/place/danube-valley",
"@type": "http://www.example.org/ArchaeologicalSite",
},
"material": "Bronze",
}
model = ExhibitModel.model_validate(data)
assert model.title.value == "Bronze Age Ritual Blade"
assert model.creator.id == "http://www.example.org/culture/unknown-bronze-age-smith"
assert model.creator.type == "http://www.example.org/CulturalGroup"
assert model.location_found.id == "http://www.example.org/place/danube-valley"
assert model.location_found.type == "http://www.example.org/ArchaeologicalSite"
assert model.material.value == "Bronze"
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped == data
ID Keywords
The keywords captured are @type and @index.
Plain IDs
Conversely, if you know that some property will always have plain scalar IDs, you may also simplify the property's class declaration.
from pydantic_jsonld.compact import BaseModel, Id, Value
class DatasetModel(BaseModel):
title: Value[str]
measured_property: Value[str]
instrument: str
license: str
data = {
"@context": {
"@vocab": "http://www.example.org/",
"instrument": {"@type": "@id"},
"license": {"@type": "@id"},
},
"title": "Atmospheric CO2 Measurements 2025",
"measuredProperty": "CO2 concentration",
"instrument": "http://www.example.org/instrument/mauna-loa-sensor",
"license": "http://www.example.org/licenses/by/4.0/",
}
model = DatasetModel.model_validate(data)
assert model.title.value == "Atmospheric CO2 Measurements 2025"
assert model.measured_property.value == "CO2 concentration"
assert model.instrument == "http://www.example.org/instrument/mauna-loa-sensor"
assert model.license == "http://www.example.org/licenses/by/4.0/"
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped == data
from pydantic_jsonld.compact import BaseModel, Id, Value
class SoftwarePackageModel(BaseModel):
name: Value[str]
version: Value[str]
homepage: str
dependency: str
data = {
"@context": {
"@vocab": "http://www.example.org/",
"homepage": {"@type": "@id"},
"dependency": {"@type": "@id"},
},
"name": "jsonld-compact",
"version": "2.3.0",
"homepage": "http://www.example.org/example/jsonld-compact",
"dependency": "http://www.example.org/project/pydantic",
}
model = SoftwarePackageModel.model_validate(data)
assert model.name.value == "jsonld-compact"
assert model.version.value == "2.3.0"
assert model.homepage == "http://www.example.org/example/jsonld-compact"
assert model.dependency == "http://www.example.org/project/pydantic"
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped == data
from pydantic_jsonld.compact import BaseModel, Id, Value
class ExhibitModel(BaseModel):
title: Value[str]
creator: str
location_found: str
material: Value[str]
data = {
"@context": {
"@vocab": "http://www.example.org/",
"creator": {"@type": "@id"},
"locationFound": {"@type": "@id"},
},
"title": "Bronze Age Ritual Blade",
"creator": "http://www.example.org/culture/unknown-bronze-age-smith",
"locationFound": "http://www.example.org/place/danube-valley",
"material": "Bronze",
}
model = ExhibitModel.model_validate(data)
assert model.title.value == "Bronze Age Ritual Blade"
assert model.creator == "http://www.example.org/culture/unknown-bronze-age-smith"
assert model.location_found == "http://www.example.org/place/danube-valley"
assert model.material.value == "Bronze"
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped == data
Validation Failure
If a particular data entry happens to have an ID object which is not a plain scalar value, the validation will fail for that instance.
Limitations
As the context is not parsed or resolved in any way, there is no way to safely determine whether any given ID object can be collapsed to a plain scalar.
This implementation does not collapse in such instances by default. However, when constructing a model from data, the initial format is remembered.
The difference is illustrated in the following examples
from pydantic_jsonld.compact import BaseModel, Id
class ExampleModel(BaseModel):
id: Id
data = {
"@context": {
"@vocab": "http://www.example.org/",
"id": {"@type": "@id"},
},
"id": "http://www.example.org/1",
}
model = ExampleModel.model_validate(data)
dumped = model.model_dump(by_alias=True, exclude_none=True)
# Keeps input format (correct compact form)
assert dumped["id"] == "http://www.example.org/1"
from pydantic_jsonld.compact import BaseModel, Id
class ExampleModel(BaseModel):
id: Id
data = {
"@context": {
"@vocab": "http://www.example.org/",
"id": {"@type": "@id"},
},
"id": {
"@id": "http://www.example.org/1",
"@type": "http://www.example.org/UniqueIdentifier",
},
}
model = ExampleModel.model_validate(data)
model.id = Id(id="http://www.example.org/2")
dumped = model.model_dump(by_alias=True, exclude_none=True)
# Keeps input format (incorrect compact form)
# Should be just "http://www.example.org/2"
assert dumped["id"] == {"@id": "http://www.example.org/2"}
For such edge cases and also especially when manually creating instances instead of validating from data, you can manually change the behavior.
from pydantic_jsonld.compact import BaseModel, Id
class ExampleModel(BaseModel):
id: Id
data = {
"@context": {
"@vocab": "http://www.example.org/",
"id": {"@type": "@id"},
},
"id": {
"@id": "http://www.example.org/1",
"@type": "http://www.example.org/UniqueIdentifier",
},
}
model = ExampleModel.model_validate(data)
model.id = Id(id="http://www.example.org/2")
model.id.compact = True
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped["id"] == "http://www.example.org/2"
from pydantic_jsonld.compact import BaseModel, Id
class ExampleModel(BaseModel):
id: Id
data = {
"@context": {
"@vocab": "http://www.example.org/",
"id": {"@type": "@id"},
},
"id": {
"@id": "http://www.example.org/1",
"@type": "http://www.example.org/UniqueIdentifier",
},
}
model = ExampleModel.model_validate(data)
model.id = Id(id="http://www.example.org/2", compact=True)
dumped = model.model_dump(by_alias=True, exclude_none=True)
assert dumped["id"] == "http://www.example.org/2"