Work with PROV-JSONLD¶
PROV-JSONLD is a W3C member submission
describing a JSON-LD representation of the PROV Data Model. It is selected with
format="jsonld". Like PROV-JSON, it needs no extra dependency — the serializer is
implemented against the standard library only and is always available.
Serialize to a file¶
import prov.model as pm
document = pm.ProvDocument()
document.set_default_namespace("http://example.org/")
e = document.entity("e1")
a = document.activity("a1")
document.wasGeneratedBy(e, a)
document.serialize("document.jsonld", format="jsonld")
Serialize to a string¶
jsonld_str = document.serialize(format="jsonld", indent=2)
print(jsonld_str)
{
"@context": [
{
"@vocab": "http://example.org/",
"@base": "http://example.org/"
},
"https://openprovenance.org/prov-jsonld/context.jsonld"
],
"@graph": [
{
"@type": "Entity",
"@id": "e1"
},
{
"@type": "Activity",
"@id": "a1"
},
{
"@type": "Generation",
"entity": "e1",
"activity": "a1"
}
]
}
A document’s registered namespace prefixes (and its default namespace, as both @vocab and
@base – JSON-LD’s @vocab alone does not govern @id values or @id-typed terms like
entity/activity, so @base is needed too) become the first entry of @context; every
unprefixed @type (Entity, Activity, Generation, …) is resolved against the
submission’s context, referenced as the second entry. Named bundles nest as {"@type": "Bundle", "@id", "@context", "@graph"} objects inside the top-level @graph.
Choose how the context is referenced¶
The context keyword controls how the submission’s context (the second entry of
@context) is emitted:
context="url"(the default) references it by URL, exactly as shown above. This is the smaller, more common output, but a consumer needs network access to resolvehttps://openprovenance.org/prov-jsonld/context.jsonldto fully process the document as JSON-LD.context="embed"inlines the vendored context object instead, so the document is fully self-contained:document.serialize(format="jsonld", context="embed")
Any other value raises ValueError. Prefer context="embed" when the output needs to be
processed offline or archived without a dependency on the submission’s context URL staying
reachable.
Deserialize from a file or stream¶
loaded = pm.ProvDocument.deserialize("document.jsonld", format="jsonld")
assert loaded == document
source also accepts an open stream:
with open("document.jsonld") as f:
loaded = pm.ProvDocument.deserialize(f, format="jsonld")
Deserialize from a string¶
loaded = pm.ProvDocument.deserialize(content=jsonld_str, format="jsonld")
Auto-detect the format with prov.read()¶
prov.read() tries every registered deserializer in turn — PROV-JSON, PROV-O/RDF,
PROV-N, PROV-XML, then PROV-JSONLD last — until one both succeeds and produces a non-empty
document:
import prov
loaded = prov.read("document.jsonld")
assert loaded == document
Passing format="jsonld" explicitly skips the trial-and-error and gives a proper traceback
if the content is not valid PROV-JSONLD.
Input scope¶
The deserializer only accepts the submission’s canonical §4 compacted shape — one JSON
object per PROV-DM statement under a top-level "@graph", exactly the shape this
serializer writes. It does not run general-purpose JSON-LD processing (no expansion,
flattening, or framing), so expanded or flattened JSON-LD that is otherwise valid
PROV-JSONLD is rejected. Malformed or unrecognised JSON-LD raises
prov.serializers.provjsonld.ProvJSONLDException:
from prov.serializers.provjsonld import ProvJSONLDException
try:
pm.ProvDocument.deserialize(content='{"entity": {"ex:e1": {}}}', format="jsonld")
except ProvJSONLDException as e:
print(f"{type(e).__name__}: {e}")
ProvJSONLDException: A PROV-JSONLD document requires both "@context" and "@graph"; found keys ['entity']
Malformed JSON itself (not valid JSON at all) raises the standard library’s decoder error,
not ProvJSONLDException:
try:
pm.ProvDocument.deserialize(content="not json", format="jsonld")
except Exception as e:
print(f"{type(e).__name__}: {e}")
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
The decoder additionally tolerates ProvToolbox’s
prov:-prefixed spellings of the type and special terms ("prov:Entity" alongside
"Entity", "prov:type" alongside "type"), so documents produced by that reference
implementation read in without modification.
Limitations¶
mentionOf (PROV-DM’s Mention relation) cannot be represented: the submission defines no
JSON-LD term for it. serialize() raises ProvJSONLDException for any document containing
a ProvMention record:
document = pm.ProvDocument()
document.add_namespace("ex", "http://example.org/")
document.mention("ex:e2", "ex:e1", "ex:b")
try:
document.serialize(format="jsonld")
except ProvJSONLDException as e:
print(f"{type(e).__name__}: {e}")
ProvJSONLDException: PROV-JSONLD cannot represent mentionOf (None): the submission defines no Mention term; see docs/reference/conformance.md
This is a permanent limitation of the PROV-JSONLD submission, not a gap in this library; see Conformance matrix for the full write-up alongside the equivalent PROV-O limitation.
Media type and file extension¶
The submission associates PROV-JSONLD with the application/ld+json media type; by
convention, files use the .jsonld extension, as in the examples above. prov does not
dispatch on either of these — the format is always selected via format="jsonld" or
auto-detected by content — but they are worth using for interoperability with other JSON-LD
tooling.