Open adlerfaulkner opened 1 year ago
Reference to relevant part of the JSON-LD spec https://www.w3.org/TR/json-ld11/#json-literals
At times, it is useful to include JSON within JSON-LD that is not interpreted as JSON-LD. Generally, a JSON-LD processor will ignore properties which don't map to IRIs, but this causes them to be excluded when performing various algorithmic transformations. But, when the data that is being described is, itself, JSON, it's important that it survives algorithmic transformations.
Ah, I am seeing from this test https://w3c.github.io/json-ld-api/tests/compact-manifest#tjs07 that you have to add "@container": "@set"
to the context.
That seems like a requirement that is not stated in the spec, and in fact contradicts the spec's notion that JSON literals should not be transformed by the processor in any way. Any one have insight on why this is?
@adlerfaulkner,
This might be a good issue to bring the spec as this is just a particular implementation of it. You can do so over here:
The spec and test coverage of this area is poor. I think your example should by default output the JSON array: "people": [{...}]
. If @set
is used, it should output an array with your JSON: "people": [[{...}]]
. If that's the case, then js07 is incorrect.
There are complications here too. If multiple JSON values are compacted, it would be fine if @set
is in the context. But if not, what should happen? It can't make an array, since that would be interpreted as raw JSON. I think compaction should throw an error. But the spec and tests don't cover this case. There is also the oddity of JSON + non-JSON values for the same term. If there is a single JSON value, then jsonld.js, probably by luck, will function and output the JSON in the compacted term, and non-JSON as values for the expanded term. That's arguably a way to do it, but I'm not sure it's explicit anywhere. And also how do you interpret data that has @set
in the context but the value is not an array? Throw an error or just fallback and assume a single JSON value?
I'm working up some tests for the WG to look at and clarify how this should work, and jsonld.js fixes will follow.
Yes, the intersection of "@container": "@set"
and "@type": "@json"
could probably be explored further. Looking at the expansion algorithm, the value of a term with @type
: @json
will always be extracted from any containing array, so the JSON value can't really take the form of an array (probably could if it were the value of @value
, though).
I'm sure there are some unexplored corner-cases here.
Thanks @gkellogg and @davidlehn. I look forward to seeing those tests and their reception in the WG.
It sounds to me like @set
in the context should always be evaluated before determining the type of the value (JSON or non-JSON). I think what you say about having @set
in the context for a non-Array value during compaction should either throw an error or just not match (& thus not compact) the field. This would be similar to how a field would not be compacted if the @type
field was not matching even though its id field matched between context and data.
@container: @set
isn't used in expansion; it is a signal for the compaction algorithm to put values inside an array. Note that the compaction algorithm can't generate an empty array, as there is no value to invoke in the algorithm.
Creating more special magic for @set
along with @type: @json
would be special use and complicate an already complicated process, so personally, I don't see that happening.
Feel free to raise an issue at https://github.com/w3c/json-ld-api, but I don't see that making the cut for the next version.
Issue: https://github.com/w3c/json-ld-api/issues/560 First pass at test cases: https://github.com/w3c/json-ld-api/pull/559
When compacting (or framing with an
@context
), any@value
of a node with"@type': "@json"
that is a JSON array of length 1 gets transformed into a non array value equalling the first item in the JSON array.For example:
Note above that the
people
field in the output was transformed from a JSON array to an object equal the the original array's first value.I would expect this library to preserve the original JSON array. The output should be: