json-ld / json-ld.org

JSON for Linked Data's documentation and playground site
https://json-ld.org/
Other
856 stars 152 forks source link

IRIs in types of type-scoped contexts are not expanded #712

Open Panaetius opened 4 years ago

Panaetius commented 4 years ago

Consider this jsonld document that uses a type-scoped context: https://tinyurl.com/qm8mux2 which should be equivalent to https://tinyurl.com/vfjfczx (without type-scoping).

I the latter, the @type of foaf:Document is correctly expanded, but in the former, the prefix of the type does not get expanded.

The only way around this is to specify the foaf prefix in the parent context, so it's propagated down, but that defeats the purpose of having type-scoped contexts. They are useful as a way to differentiate in properties that can have multiple types as children (so each context only applies to its type of child), but having to propagate up definitions to the parent context opens this up to ambiguities again.

We can work around this for now on our end by just using the expanded form instead of the prefix notation, but it'd be nice if this could be supported out of the box, as it'd help a lot with composeability.

Thanks a lot :slightly_smiling_face:

gkellogg commented 4 years ago

The scoped-context version defines a "Document" term with the "foaf" prefix, but that prefix isn't introduced until within the scoped context, so it is not in scope when "foaf:Document" is used as the value of @id in the term definition for "Document".

Panaetius commented 4 years ago

Thank you for the explanation.

Maybe I can elaborate a bit on how we are using this feature. We have classes in Python in a hierarchy that create a nested top level contexts when we serialize them to json-ld (by extending the attrs library).

This looks something like

@jsonld.s(
    type=[
        'wfdesc:Process',
        'prov:Activity',
    ],
    context={
        'wfdesc': 'http://purl.org/wf4ever/wfdesc#',
        'prov': 'http://www.w3.org/ns/prov#',
    },
)
class Parent:
    children = jsonld.ib(types=[Child1, Child2], path='prov:generated')

@jsonld.s(
    type=[
        'schema:Dataset',
    ],
    context={
        'schema': 'https://schema.org/Dataset',
    },
)
class Child1:
    [...properties...]

@jsonld.s(
    type=[
        'prov:Entity',
    ],
    context={
        'prov': 'http://www.w3.org/ns/prov#',
    },
)
class Child2:
    [...properties...]

And when creating the context, if a parent maps to more than 1 child, we type-scope and embed the children's context in the parent's context (We need a single top-level context due to the nature of the application).

Due to how the type-scoped contexts are handled, we can't just directly include the context of a child in the parent, but we'd have to expand its type first before embedding. Or include the prefix definition in the parent, though that wouldn't be that nice, since then the parents context would be polluted with context information of the children that it doesn't need. It could also lead to naming conflicts of the same prefix is used for different ontologies in the children (Though I'd consider that bad practice)

Expanding it in the child is a bit ugly as well, at least I consider @id to be part of the child, and having it expanded but at the same time having a prefix defined for it and not expanded looks a bit like a mix of expanded and compacted forms.