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

Ability to declare a container as both @language and @set #407

Closed
danmichaelo opened this issue Jan 9, 2016 · 20 comments
Closed

Ability to declare a container as both @language and @set #407

danmichaelo opened this issue Jan 9, 2016 · 20 comments

Comments

@danmichaelo
Copy link

Related to #269 . I would like to use @language maps with @set, but haven't found a way to do so.

My data is following the SKOS model, where each concept can have one preferred label per language, and any number of alternative labels per language. To make the data easy to work with, I'm trying to achieve the following output:

{
  "@id": "http://data.ub.uio.no/realfagstermer/c012548",
  "prefLabel": {
    "nb": "Abbor",
    "en": "European perch"
  },
  "altLabel": {
    "nb": [
      "Åbor"
   ]
  }
}

The best context I've come up with is this (JSON-LD Playground):

{
  "@context": {
    "skos": "http://www.w3.org/2004/02/skos/core#",
    "prefLabel": {
      "@id": "skos:prefLabel",
      "@container": "@language"
    },
    "altLabel": {
      "@id": "skos:altLabel",
      "@container": "@language"
    }
  }
}

but this makes altLabel a set (or a js list) only if there's more than one item, an object otherwise. I would like to force altLabel to always be a set.

@lanthaler lanthaler added the 1.1 label Jan 10, 2016
@lanthaler
Copy link
Member

I don’t know how frequent having multiple string values per language are (I haven’t seen this often) but I tagged it as a request for the next version of JSON-LD. Thanks for the suggestion

@lanthaler lanthaler added this to the JSON-LD.next milestone Jan 10, 2016
@akuckartz
Copy link

The current behavior is the one I would expect. But non-RDF developers might like sets (JS arrays) with a single element. That could be a more general use case.

@danmichaelo
Copy link
Author

@akuckartz Yeah, as a JS developer I find that I easily end up with a lot of extra code to normalize the data to make it easier work with. For instance I currently have something like this to cast the altLabels to arrays:

function asArray(x) {
  return typeof(x) == 'undefined' ? [] : (typeof(x) == 'string' ? [x] : x);
}
function valuesAsArray(x) {
  x = x ? x : {};
  Object.keys(x).forEach(function(key) {
    x[key] = asArray(x[key]);
  });
  return x;
}
concept.altLabel = valuesAsArray(concept.altLabel);

@dlongley
Copy link
Member

@danmichaelo, btw, if you're using jsonld.js you can use:

var thisIsAnArrayOfValues = jsonld.getValues(node, 'property');

@danmichaelo
Copy link
Author

@dlongley Sweet, thanks!

@gkellogg gkellogg modified the milestone: JSON-LD.next Sep 22, 2016
@gkellogg gkellogg removed the 1.1 label Sep 22, 2016
@azaroth42
Copy link
Contributor

We have this use case as well, for serializing vocabularies in SKOS and in providing data level internationalization. Each term has multiple labels in multiple languages, and it would be nice to be able to use @set to ensure that the resulting structure is consistent, even if there is a single element in the list.

@gkellogg
Copy link
Member

@azaroth42 good to know. Do you have a proposal for addressing this in the spec?

@gkellogg gkellogg added this to the JSON-LD 1.1 milestone Apr 11, 2017
@gkellogg gkellogg removed the on-hold label Apr 11, 2017
@gkellogg
Copy link
Member

Here's a proposal for both this issue and #269:

PROPOSAL: updating the definition of @container in Context Definitions:

If the expanded term definition contains the @container keyword, its value must be either @list, @set, @language, @index, @id, @type or be null. Values other than @list and @set may also include @set separated by whitespace, to ensure that values are always represented using an array. If the value includes @language, when the term is used outside of the @context, the associated value must be a language map. If the value includes @index, when the term is used outside of the @context, the associated value must be an index map.

This allows a term definition such as the following:

{
  "@context": {
    "skos": "http://www.w3.org/2004/02/skos/core#",
    "prefLabel": {
      "@id": "skos:prefLabel",
      "@container": "@language @set"
    },
    "altLabel": {
      "@id": "skos:altLabel",
      "@container": "@language @set"
    }
  }
}

Other than @list and @set, the default compaction would favor a direct value use without an array form, as it does now. If @set is added, a single value will always be represented in an array.

If this is acceptable, please 👍 or 👎 this comment, or suggest an improvement.

@azaroth42
Copy link
Contributor

azaroth42 commented May 22, 2017

Can you describe the rationale for whitespace separation rather than a JSON array?

e.g. what was undesirable about:

"prefLabel": {
  "@id": "skos:prefLabel",
  "@container": ["@language", "@set"]
}

Also, is the order of @set important in the string (or array) or can it be the first keyword?

@gkellogg
Copy link
Member

It could go either way, whitespace separation keeps values of @container strings with simple split used to determine. Array means needing to check if the value is an array, or not, or coercing it to an array always, and then looking at the array contents.

term['@container'].to_s.split(/\s+/).include?('@set')

vs.

Array(term['@container']).include?('@set')

Checking for appropriate combinations should be done as another way of supporting backwards-compatibility.

If that's preferable, we could amend the proposal to use the array form.

@danmichaelo
Copy link
Author

👍 for the array form

@azaroth42
Copy link
Contributor

My fear about micro-DSLs even as simple as "whitespace separated terms" is that they invariably end up less and less micro. OTOH, I understand the backwards compatibility desire of keeping the data type only a string, and also to avoid annoying type checking.

I'm 👍 to the proposal and don't mind either a string or an array, with a vague preference for an array.

@niklasl
Copy link
Member

niklasl commented May 23, 2017

👍 for the proposal with a slight preference for array (i.e. with a preference for mixed type with "ready to use" values over a microsyntax).

@dlongley
Copy link
Member

👍 for the array version, very 👎 for the microsyntax (whitespace delimited).

@gkellogg
Copy link
Member

Array version it is. I'll implement and do a PR when I have time.

gkellogg added a commit that referenced this issue May 28, 2017
…y including `@set` along with another container type.

Fixes #269. Fixes #407.
gkellogg added a commit to ruby-rdf/json-ld that referenced this issue May 28, 2017
@niklasl
Copy link
Member

niklasl commented May 29, 2017

The example really shouldn't use skos:prefLabel though, since SKOS disallows using more than one per language for that property. Something like skos:altLabel or skos:hiddenLabel could do though.

@gkellogg
Copy link
Member

@niklasl Which example uses more than one skis:prefLabel? We use both altLabel and prefLabel, but I don't see a case where prefLabel has more than one value.

@niklasl
Copy link
Member

niklasl commented May 29, 2017

@gkellogg I only saw it in the proposal context above (#407 (comment)). Just in case anyone would build off of that.

@gkellogg
Copy link
Member

Okay, sure. Didn't make it into the PR.

@niklasl
Copy link
Member

niklasl commented Jun 1, 2017

Just in case it would be more comprehensible, we might consider splitting the support for "container-as-an-indexed-dict" and "container-as-an-array" into two keywords. That is, in JSON-LD 1.1, declaring a term to be indexed on @language, @id, @type or @index would be done (preferably...) using the @index keyword as a key.

Apart from splitting up the current meaning of containers for the possible benefit of intuitive understanding of indexed dicts, this proposal would then look like:

    "altLabel": {"@index": "@language", "@container": "@set"},

With this, @container would be only (recommended to be) used for @set and @list. Support for the other keywords in @container would be kept for backwards compatibility.

I cannot say whether this is better or not. It might be more intuitive for someone who isn't accustomed to JSON-LD 1.0. For the rest of us, this certainly does throw things around a bit (and I admit I haven't at all considered the consequences in terms of the spec text yet). It did occur to me quite a while back originally though, so I'd like to through it out here for consideration, if for nothing else than to avoid second thoughts further down the line.

(Admittedly, using @list in conjunction with an index would probably be very strange in most conceivable cases. I'm not sure that speaks against this in itself though.)

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

7 participants