json-ld / json-ld.org

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

Scoped contexts with multiple instantiation conflict resolution should be documented #616

Closed azaroth42 closed 6 years ago

azaroth42 commented 6 years ago

Scoped contexts allow us to associate different predicates with terms based on the class of the resource. In RDF, resources can instantiate multiple classes simultaneously. Those classes might have conflicting definitions for the same term in a scoped context.

The value of @type is unordered, as it's just the rdf:type predicate. This means that serialization will have no predictable order for the classes. The order of the classes in the array, as merged from alpha-sorting any aliases for @type, determines which of the contexts takes precedence, per step 7 of both compaction and expansion algorithms.

Example:

{
  "@context": {
    "@version": 1.1,
    "eg": "https://example.com/ns/",
    "Type1": {"@id": "eg:Type1", "@context": {"label": "eg:label1"}},
    "Type2": {"@id": "eg:Type2", "@context": {"label": "eg:label2"}}
  },
  "@id": "https://example.com/object/1",
  "@type": ["Type1", "Type2"],
  "label": "1 or 2? Place bets now!"
}

Proposal:

I don't have any better solution :( The only ordered data is the @type array at the JSON level, so the current behavior of taking the last type is probably as good as can be managed, but the issue seems worth documenting in the main spec, rather than just in the algorithm.

\ht @workergnome

(edited for clarity)

gkellogg commented 6 years ago

This is true only when round-tripping through triples, otherwise the order is maintained by the algorithms.

One solution to this is documentation. Or, We could potentially order the types, by their compacted values when applying scoped contexts, which would be deterministic

dlongley commented 6 years ago

Or, We could potentially order the types, by their compacted values when applying scoped contexts, which would be deterministic

While deterministic, every time we've done this in the past it has always seemed to me to be like a lackluster effort to mirror author intent for "most cases". Perhaps we should consider introducing something like @precedence to allow authors to be explicit -- removing surprises and frustration entirely.

For example:

{
  "@context": {
    "@version": 1.1,
    "eg": "https://example.com/ns/",
    "Type1": {"@id": "eg:Type1", "@context": {"label": "eg:label1"}},
    "Type2": {"@id": "eg:Type2", "@context": {"label": "eg:label2"}},
    "@precedence": ["Type2", "Type1"]
  },
  "@id": "https://example.com/object/1",
  "@type": ["Type1", "Type2"],
  "label": "1 or 2? Place bets now!"
}

This would also allow for precedence to be given for terms that are not types; I'm not sure what the precedence is right now if you've got a property term that says one thing and a type term that says another:

{
  "@context": {
    "@version": 1.1,
    "eg": "https://example.com/ns/",
    "label": "eg:label3",
    "Type1": {"@id": "eg:Type1", "@context": {"label": "eg:label1"}},
    "Type2": {"@id": "eg:Type2", "@context": {"label": "eg:label2"}}
  },
  "@id": "https://example.com/object/1",
  "@type": ["Type1", "Type2"],
  "label": "1 or 2... OR 3??? Place bets now!"
}

I imagine one of the types would win in this case because of the level of specificity, but perhaps the author would not be expecting this. They could be explicit:

"@precedence": ["label", "Type2", "Type1"]
gkellogg commented 6 years ago

While deterministic, every time we've done this in the past it has always seemed to me to be like a lackluster effort to mirror author intent for "most cases". Perhaps we should consider introducing something like @precedence to allow authors to be explicit -- removing surprises and frustration entirely.

Uhh... how much complexity are we adding for what is likely an extremely marginal case (any data to show the real world implications?)

I'm not sure what the precedence is right now if you've got a property term that says one thing and a type term that says another

Scoped contexts in property terms are evaluated first, before descending into the object value. Types are processed in presented order at the beginning of looping over key-value pairs. If order we must, ordering by compacted type at least makes it predictable.

Having incompatible scoped contexts on different types which might be combined seems like a bad practice, to me. Use Cases?

iherman commented 6 years ago

I fully agree with @gkellogg:

Uhh... how much complexity are we adding for what is likely an extremely marginal case (any data to show the real world implications?)

JSON-LD is already very complex as is. There should be a clear warning in the document about this corner case, possibly define a warning for the processor, but we should stop at that.