The documentation of JSON-LD types clearly states that you can define multiple types to a node.
https://www.w3.org/TR/json-ld11/#specifying-the-type
If you open the example #14 from the above url in the JSON-LD playground, you will see that it is a valid syntax.
{
"#id": "http://me.markus-lanthaler.com/",
"#type": [
"http://schema.org/Person",
"http://xmlns.com/foaf/0.1/Person"
]
}
However, if you try to move this definition into #context, and apply it to a specific property, you will get an error from the parser. Check it here.
{
"#context": {
"some_property": {
"#id": "http://me.markus-lanthaler.com/",
"#type": [
"http://schema.org/Person",
"http://xmlns.com/foaf/0.1/Person"
]
}
},
"some_property": "value"
}
The error displayed is:
jsonld.SyntaxError: Invalid JSON-LD syntax; an #context #type value must be a string.
I read the documentation carefully and it says that you can define multiple types for node types, but not for value objects.
The documentation clearly says that when #value and #type are used in the same dictionary, the #type keyword is expressing a value type. Otherwise, the #type keyword is expressing a node type.
But here is another example showing that this might not be true.
Does anybody have an idea how to define multiple node types in #context?
You cannot, because you cannot define node types in a context at all.
Starting normatively. In https://www.w3.org/TR/json-ld11/#context-definitions we read:
If the expanded term definition contains the #type keyword, its value MUST be an absolute IRI, a compact IRI, a term, null, or one of the keywords #id, #json, #none, or #vocab.
No arrays allowed here. Because #type in an expanded term definition in a context is used to specify the type of values of the defined property. As mentioned eg. in https://www.w3.org/TR/json-ld11/#typed-values:
Typed values may be expressed in JSON-LD in three ways:
By utilizing the #type keyword when defining a term within an #context section.
Finally let's see what your example expands to if we correct it to have a string value for #type.
{
"#context": {
"some_property": {
"#id": "http://me.markus-lanthaler.com/",
"#type": "http://schema.org/Person"
}
},
"some_property": "value"
}
expands to
[
{
"http://me.markus-lanthaler.com/": [
{
"#type": "http://schema.org/Person",
"#value": "value"
}
]
}
]
As you can see there you indeed have #value and #type together.
Related
I'm trying to work out the best way to handle localisation in JSON-LD. The spec has information on String Internationalization that allows you to specify different translations for string values:
{
"#context":
{
...
"occupation": { "#id": "ex:occupation", "#container": "#language" }
},
"name": "Yagyū Muneyoshi",
"occupation":
{
"ja": "忍者",
"en": "Ninja",
"cs": "Nindža"
}
...
}
This covers translation but not internationalization where the content changes depending on locale.
E.g.
{
"#context":
{
"#id": "http://example.org/carousel#mycarousel",
"#language": "ja"
...
},
"slides": ["http://example.org/japan.jpg"]
}
{
"#context":
{
"#id": "http://example.org/carousel#mycarousel",
"#language": "es"
...
},
"slides": ["http://example.org/spain.jpg"]
}
Does anyone know if the above is invalid in the JSON-LD spec, i.e. having different field values depending on the #language while there #ids are the same? If not is there an alternate approach that could work?
Yes, the above is invalid. #language is only used to annotate strings with their language. What you are looking for is higher-level information. As such, you need to use some vocabulary. Schema.org for instance has http://schema.org/inLanguage for this. There exist various others as well. Which one you want to use, depends on the specific use case.
As a simple exercise I wanted to take some test-data from a little app I had which produced a user record in JSON and turn it into JSON-LD, testing on JSON-LD.org's playground gives some help, but I don't know if I'm doing it right.
The original is:
[
{
"Id": 1
"Username": "Dave",
"Colour":"green“
}
]
So I have a person, who has a username, an ID and an associated colour.
What I've got so far is:
{
"#context": {
"name": "http://schema.org/name",
"Colour": {
"#id": "http://dbpedia.org/ontology/Colour",
"#type": "http://schema.org/Text",
"#language": "en"
}
},
"#type": "http://schema.org/Person",
"#Id": "http://example.com/player/1",
"sameAs" : "https://www.facebook.com/DaveAlger",
"Id": 1,
"name": "David Alger",
"Username": "Dave",
"Colour": "green"
}
So I'm declaring it's a #type of person, and given a URI #id.
I'm also using the "sameAs" idea, which I saw on a blog-post once, but am unclear if it is just supported right off.
Then I've tried to create a #context. Here that I've added a name and given that a reference. I've tried to create something for "colour" too. I'm not sure if pointing to a DBpedia reference about "colour" and specifying a #type and #language is good, or not.
I suppose the final thing is "username", but that feels so deeply internal to a site that it doesn't make sense to "Link" it at all.
I'm aware this data is perhaps not even worth linking, this is very much a learning exercise for me.
I don’t think that http://dbpedia.org/ontology/Colour should be used like that. It’s a class, not a property. The property that has http://dbpedia.org/ontology/Colour as range is http://dbpedia.org/ontology/colour. (That said, I’m not sure if your really intend that the person should have a colour, instead of something related to this person.)
If you want to provide the language of the colour strings, you should not specify the datatype, #language is sufficient (if a value is typed, it can’t have a language anymore; by using #language, it’s implied that the value is a string).
You are using #Id for specifying the node’s URI, but it must be #id.
The properties sameAs, Id and Username are not defined in your #context.
If you intend to use Schema.org’s sameAs property, you could define it similar to what you did with name, but you should specify that the value is a URI:
"sameAs": {
"#id": "http://schema.org/sameAs",
"#type": "#id"
},
For Username, you could use FOAF’s nick property, or maybe Schema.org’s alternateName property.
No idea which property you could use for Id (depends on your case if this is useful for others at all, or if this is only relevant for your internal system).
In the question JSON-LD framing single object arrays was asked on how to make arrays from single objects while framing JSON-LD for all arrays (by adding an compactArrays option).
Is there any way to do it selectively? Starting from always having "#graph", and after that for some "major" nodes. Maybe some parameter can be given in the frame to indicate exception of the general option?
In my case arrays are actually sets.
Yep, you can do it per-property by setting the #collection attribute of the property to #set:
{
"#context": {
"arrayProperty": {
"#id": "http://example.com/something",
"#container": "#set"
}
},
...
"arrayProperty": []
}
I copy here a part of an example from the json-ld standard:
{
"#context": {
"foaf": "http://xmlns.com/foaf/0.1/",
"picture": { "#id": "foaf:depiction", "#type": "#id" }
},
"picture": "http://twitter.com/account/profile_image/markuslanthaler"
}
I don't get it, why we should use the #id in the #context. It should be:
{
"#context": {
"foaf": "http://xmlns.com/foaf/0.1/",
"picture": {
"#type": [ "#id", "foaf:depiction" ]
}
},
"picture": "http://twitter.com/account/profile_image/markuslanthaler"
}
Do you have any explanation?
A few years later
I guess the upper means the following in a more reusable form:
{
"http://xmlns.com/foaf/0.1/depiction": "http://twitter.com/account/profile_image/markuslanthaler"
}
It is a lot easier to understand if we check the flattened form first and try to compact it gradually. So the #id is the IRI of the property and the #type is the type of the value, which is here #id, which can be confusing, but it just means that we are expecting an IRI as value.
#id tells the JSON-LD processor how to expand the term. It can be omitted if you use #vocab, or the term is in the form of a compact IRI.
#type tells the processor how to handle plain-string values of that term used within the body if a JSON-LD document. It can be something like an XSD data type, #id or #vocab. The last two are very similar, except one is evaluated against the document base and the other as a vocabulary term.
If the value of a term definition in the context is a string, rather than an object, it's a short-hand for specifying an object with just #id. Don't think of the context as an RDFS/OWL vocabulary, but as a kind of prefix mechanism.
I am new to JSON-LD and LOD so please excuse my use of terminology. I am working on creating a data model in JSON-LD to describe aggregated digital collections based on the European Data Model (http://pro.europeana.eu/edm-documentation).
I would like to create an #context area that describes the relationship:
ore:Aggregation --- edm:aggregatedCHO --> edm:ProvidedCHO
(where 'edm:aggregatedCHO' is the predicate/edge), but I would like to label edm:ProvidedCHO as 'sourceResource' in my model.
Currently my #context looks something like this:
{
"#context": {
"edm" : "http://www.europeana.eu/schemas/edm/",
"sourceResource" : {
"#id" : "edm:ProvidedCHO",
"#type" : "edm:aggregatedCHO"
}
}
}
My intention was to define the predicate ('edge') using #type, and the node contents using #id, but after reviewing the W3C Recommendation, this seems incorrect, and that 'edm:ProvidedCHO' should actually be the #type, because it describes the content type of the node (http://www.w3.org/TR/json-ld/#typed-values).
My question, generally, is where/how do you include the predicate of a triple in a JSON-LD #context statement?
In this case specifically, how do I represent a node called 'sourceResource' that contains edm:ProvidedCHO objects that are each an edm:aggregatedCHO?
Note that setting #type in the context says that the term is expected to be a literal with that datatype; you probably want to use this #type in the body, which will create a type edge, if you will.
Note that the #context does not define relationships, but terms, and how the values of the terms should be interpreted (along with a couple of other things). I think what you want is to have an #context that simply defines terms you want to use in the body of the JSON, where you can define your nodes and they're relationships.
This might be something like the following:
{
"#context": {
"edm" : "http://www.europeana.eu/schemas/edm/",
"ore": "http://example/",
"edm:aggregatedCHO": {"#type": "#id"}
},
"#id": "ore:Aggregation",
"edm:aggregatedCHO": "edm:ProvidedCHO"
}
It's always good to test your JSON-LD on the JSON-LD playground, or some similar service or tool.