Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question/ unexpected behavior: Why does compaction sometimes expand and not remove a prefix? #495

Closed
cboettig opened this issue May 19, 2017 · 7 comments

Comments

@cboettig
Copy link

Consider the following example:

{
  "@context": {
    "schema": "http://schema.org/",
    "ex": "http://example.org/",
    "name": "schema:name",
    "foo": {"@id": "ex:foo", "@type": "schema:Text"},
    "bar": {"@id": "ex:bar", "@type": "schema:Person"},
  },
  "@type": "schema:Thing",
  "name": "Jane Doe",
  "foo": "Professor",
  "bar": {
    "@type": "schema:Person",
    "name": "John Doe"
  }
}

Compaction under the identical context results in bar being expanded to ex:bar, but foo remains foo. Why? To me this is unexpected: the context seems to unambiguously define bar as ex:bar. I think this behavior has something to do with bar taking a node value rather than a data value, but I fail to see why that matters. What does the user gain by having it called ex:bar that wasn't clear when it was just bar?

This behavior is frustrating from the standpoint of a developer consuming JSON-LD with this kind of context structure, because I feel unable to predict whether the JSON files will use bar or ex:bar (and naturally I want to just use bar, which is why it's explicitly mapped bar to "@id": "ex:bar" in the first place).

Here's my example on Playground.

Thanks kindly for any clarification into this seemingly unexpected behavior that is no doubt more a problem of my understanding than algorithmic error!

@gkellogg
Copy link
Member

@cboettig the @type in the context definition for bar is actually out of range. @type here is intended to describe either a literal datatype, or be one of @id or @vocab, which determines how values are treated. For literal values, they will compact using the term if the datatype defined for the term is exactly the same as the datatype of the literal value (value object).

In this case, the value is an object, not a literal. One of the object properties is "@type": "schema:Person", this is not a datatype, but an object type. Because the value is not a literal with datatype schema:Person (which would not be valid schema.org, in any case), it cannot be used for compaction.

This is described in Term Selection, but the language is fairly opaque, and the introduction could use a better english-language overview of what is going on.

I'll keep this open as a reminder to add such language.

@cboettig
Copy link
Author

@gkellogg thanks so much, that explains volumes.

Yup, I think there were a few times in the documentation where I've puzzled as to whether the type being discussed was in reference only to data type, only to node type, or to both.

@garpinc
Copy link

garpinc commented May 24, 2021

@gkellogg I am not understanding above nor did I understand what was described in Term Selection.

What if you want the above to actually work and you want both prefixes to be stripped (with foo remaining foo and bar remaining bar) ? Then what do you have to do to the context to make that happen?

In my case I have:
[{@id=http://test1, @type=[http://cambridgesemantics.com/ontologies/2018/06/MetadataDictionary#MetadataDictionary], http://cambridgesemantics.com/ontologies/2018/06/MetadataDictionary#metaDataConcepts=[{@id=http://testc1}], http://purl.org/dc/elements/1.1/title=[{@value=test1}]}, {@id=http://testc1, @type=[http://cambridgesemantics.com/ontologies/2018/06/MetadataDictionary#ClassConcept]}]

as first arg to JsonLdProcessor.frame(output, JsonUtils.fromString(frame), opts)
with:

opts.setUseNativeTypes(true);
opts.setCompactArrays(true);
opts.setOmitGraph(getWriterConfig().get(OMIT_GRAPH));

and frame:

{
  "@context" : [ "http://cambridgesemantics.com/ontologies/2018/06/MetadataDictionary/ClassConcept", "http://cambridgesemantics.com/ontologies/2018/06/MetadataDictionary/MetadataDictionary" ],
  "@type" : "http://cambridgesemantics.com/ontologies/2018/06/MetadataDictionary#MetadataDictionary"
}

in the MetadataDictionary context I have:

    "metaDataConcepts": {
      "@id": "metaframe:metaDataConcepts",
      "@type": "metaframe:ClassConcept"
    },
    "title": {
      "@id": "dc:title",
      "@type": "xsd:string"
      
    },

Which results in:

{
  "@context" : [ "http://cambridgesemantics.com/ontologies/2018/06/MetadataDictionary/ClassConcept", "http://cambridgesemantics.com/ontologies/2018/06/MetadataDictionary/MetadataDictionary" ],
  "uri" : "http://test1",
  "type" : "metaframe:MetadataDictionary",
  "metaframe:metaDataConcepts" : {
    "uri" : "http://testc1",
    "type" : "metaframe:ClassConcept"
  },
  "dc:title" : "test1"
}

but I want both those prefixes stripped.. How can I make that happen? If I remove the @type from the properties in context above then they do get stripped like I desire but I don't think I should be removing the type like that...

In short I figure I'm doing something wrong so please advise..

@pchampin
Copy link
Contributor

pchampin commented May 25, 2021

@garpinc It seems that you are misunderstanding the role of @type in a term declaration in the context.
Consider the following term declaration:

   "foo":  {
        "@id": "http://example.org/foo",
        "@type": "http://example.orf/bar"
   }

means:

  • expand a JSON attribute foo into the RDF predicate http://example.org/foo (this is what @id does)
  • if the value of foo is a string, then expand it into an RDF literal with datatype http://example.org/bar (this is what @type does)

About the second point above, notice that

  • if the value of foo is not a string (e.g. a number or an object), then the @type from the context is ignored;
  • in your example above, the @type of metaDataConcepts is ignored (since the value of metaDataConcepts is an object) and probably should not be there (as I understand, metaframe:ClassConcept is a class, not a datatype).

So removing it from the context is probably the good solution.

@garpinc
Copy link

garpinc commented May 26, 2021

This explanation makes sense. I assume @gkellogg that you agree with this explanation?

I was thinking that @type gives the author of content some indication what to put in the property and some validation facility?

Since this is not the case how does an author know the type by looking at context... And how does a validator know what types are valid?

@gkellogg
Copy link
Member

@pchampin is correct, of course.

the context is not used for validation, but expansion/compaction. It’s purpose is to provide a “context” for interpreting JSON. An OWL ontology, or ShEx/SHACL shape could be used for validation at the level of RDF, so JSON Schema at the level of JSON.

the Structured Data Linter uses some of these techniques and other heuristics for validating JSON-LD.

@garpinc
Copy link

garpinc commented May 26, 2021

Ok.. I think that's pretty clear now... Perhaps some additional verbiage stating what you both said should be in the documentation because clearly what's there now wasn't clear to me.. This was a much better explanation..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants