This notebook demonstrates the basic problem with using JSON-LD 1.0 and the curies used in the prefixcommons library. For the purposes of this demo, we will use the biocontext monarch context. This is a serious problem because a not-insignificant portion of the prefixcommons libraries use prefixes that end in something other than "/" or "#".
This issue exists because of a fix described in https://lists.w3.org/Archives/Public/public-rdf-comments/2018Jan/0002.html . Basically, the solution in JSON-LD 1.0 is, "if it doesn't look like a prefix, it isn't a prefix".
The @prefix
tag was added in the JSON-LD 1.1 specification to allow one to force a any string to be treated as a prefix. This, however, currently has to be done on a per-prefix basis:
{
"@context" : {
"CHEBI" : {
"@id": "http://purl.obolibrary.org/obo/CHEBI_",
"@prefix": true
}
}
}
The problem with this approach is that prefixcommons library users use both the raw json and the rdflib json-ld parser, meaning that, unless the prefixcommons parser is enhanced to recognize the expanded format, the above fix won't work.
An issue has been filed suggesting (now requesting) that @prefix
be allowed as a default on the entire context:
{
"@context" : {
"@prefix": true,
"CHEBI" : "http://purl.obolibrary.org/obo/CHEBI_"
...
}
}
!pip install -q prefixcommons
!pip install -q rdflib
!pip install -q rdflib-jsonld
!pip install -q jsonasobj
from contextlib import closing
from typing import Optional, Dict
import requests
from jsonasobj import loads
from prefixcommons import curie_util
from rdflib import Graph
def fetch_pc_context(name: str) -> Optional[str]:
"""
Retrive the prefixcommons JSON-LD entry for name
:param name: context name
:return: String representation of JSON-LD context
"""
url = f"https://raw.githubusercontent.com/prefixcommons/biocontext/master/registry/{name}.jsonld"
with closing(requests.get(url, stream=False)) as resp:
if resp.status_code == 200:
return resp.text
else:
print(f"Cannot fetch: {url}")
def prefix_for(prefixes: Dict[str, str], prefix: str) -> str:
"""
Format the prefix entry in prefixes
:param prefixes: map from prefix to URI
:param prefix: prefix to map
:return: result
"""
if prefix in prefixes:
return f'@prefix {prefix}: <{prefixes[prefix]}> .'
else:
return f'*prefix: {prefix} not mapped'
When we load the context as a plain JSON-LD object, both the BIOGRID and CHEBI contexts are are aliases
ctxt_str = fetch_pc_context('monarch_context')
ctxt = loads(ctxt_str)
print(f"Entry for BIOGRID is {ctxt['@context'].BIOGRID}")
print(f"Entry for CHEBI is {ctxt['@context'].CHEBI}")
Entry for BIOGRID is http://thebiogrid.org/ Entry for CHEBI is http://purl.obolibrary.org/obo/CHEBI_
The prefix commons utility doesn't use the JSON-LD library, so both of the prefixes are represented
curie_map = {k: v for k, v in curie_util.read_biocontext('monarch_context').items()}
print(prefix_for(curie_map, 'BIOGRID'))
print(prefix_for(curie_map, 'CHEBI'))
@prefix BIOGRID: <http://thebiogrid.org/> . @prefix CHEBI: <http://purl.obolibrary.org/obo/CHEBI_> .
When we use the JSON-LD library, however, URI's that don't end in "#" or "/" are not treated as prefixes (!)
g = Graph()
g.parse(data=ctxt_str, format="json-ld")
prefixes = {k:v for k, v in g.namespaces()}
print(prefix_for(prefixes, 'BIOGRID'))
print(prefix_for(prefixes, 'CHEBI'))
@prefix BIOGRID: <http://thebiogrid.org/> . *prefix: CHEBI not mapped