Work with PROV-JSONLD

PROV-JSONLD is a W3C member submission that represents the PROV Data Model in JSON-LD. Select it with format="jsonld". It needs no extra.

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"
    }
  ]
}

The first entry of @context holds the document’s namespace prefixes. The default namespace appears as both @vocab and @base. @vocab expands unprefixed property names, and @base expands unprefixed @id values such as e1, which would otherwise resolve against the document’s own location. The second entry references the submission’s context, which resolves the unprefixed types such as Entity and Generation. A named bundle nests inside the top-level @graph as an object with @type: "Bundle", its own @context and its own @graph.

Choose how the context is referenced

The context keyword controls the second entry of @context:

  • context="url", the default, references the submission’s context by URL, as above. The output is smaller, but a consumer needs network access to process it as JSON-LD.

  • context="embed" inlines the context object, so the document is self-contained:

    document.serialize(format="jsonld", context="embed")
    

Any other value raises ValueError. Use context="embed" for output that will be archived or processed offline.

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 PROV-JSONLD last, after the four other formats, so valid PROV-JSONLD still auto-detects. See Auto-detect the format with prov.read() in the PROV-JSON guide for how detection works and when to pass format= instead.

import prov

loaded = prov.read("document.jsonld")
assert loaded == document

Input scope

The deserializer accepts the submission’s compacted shape only. That is one JSON object per PROV-DM statement under a top-level "@graph", which is the shape this serializer writes. It does not run a JSON-LD processor, so expanded or flattened JSON-LD is rejected even when it is otherwise valid PROV-JSONLD. It does accept ProvToolbox’s prov:-prefixed spellings of the type and special terms, such as "prov:Entity" and "prov:type".

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']

Input that is not valid JSON at all raises the standard library’s decoder error instead:

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)

Limitations

The submission defines no term for mentionOf, PROV-DM’s Mention relation, so PROV-JSONLD cannot represent 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: the submission defines no Mention term; see docs/reference/conformance.md

This is a limitation of the submission, not of the library. Conformance records it alongside the equivalent PROV-O limitation.

Media type and file extension

The submission associates PROV-JSONLD with the application/ld+json media type, and files conventionally use the .jsonld extension. prov dispatches on neither. The format is selected with format="jsonld" or auto-detected from content. Use them anyway for interoperability with other JSON-LD tooling.