json-ld / json-ld.org

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

API step §5.1.2.9.4.6 #662

Closed doriantaylor closed 6 years ago

doriantaylor commented 6 years ago

Per https://lists.w3.org/Archives/Public/public-linked-json/2018Jun/0014.html:

I am implementing the expansion algorithm and found that §5.1.2.9 may erroneously create structures like { "@value": "...", "@type": ["..."] }. I suspect it has to do with §5.1.2.9.4.4, or more accurately, the fact of doing a single pass over a dictionary containing keys which may expand to both @type and @value (and further, if they are to be sorted lexically, @value comes after @type).

I have remedied this in my own implementation by adding a check after §5.1.2.9.15, that simply takes the @type out of any array if there is also @value present.

While we're in here, I'll also call attention to §5.1.2.9.4.7 which says to make the value for @language into an array, which the test suite ostensibly disagrees with.

gkellogg commented 6 years ago

I am implementing the expansion algorithm and found that §5.1.2.9 may erroneously create structures like { "@value": "...", "@type": ["..."] }.

If the input contains both @value and an array of @type, it will indeed expand this as you say, but the algorithm is used for @type in all circumstances. Step 10 checks for this, and issues an invalid value object exception if this is so.

§5.1.2.9.4.7 which says to make the value for @language into an array

Note that this is only done if the frame expansion flag is true, as it a frame may include an array of languages (or an empty object), which is used in matching.

doriantaylor commented 6 years ago

by my reading §5.1.2.9.4.4 will unconditionally assign @type to an array which means §5.1.2.10 will unconditionally throw an error whenever @value is present, no?

(also noted on the issue @language and the frame flag)

doriantaylor commented 6 years ago

alternatively one could not coerce @type into an array unless the @value was absent, say, after §5.1.2.9.15. that would preserve the error condition if the input itself was incorrect.

gkellogg commented 6 years ago

§5.1.2.9.4.4 reads:

If expanded property is @type and value is neither a string nor an array of strings, an invalid type value error has been detected and processing is aborted. Otherwise, set expanded value to the result of using the IRI Expansion algorithm, passing active context, true for vocab, and true for document relative to expand the value or each of its items. When the frame expansion flag is set, value may also be an empty dictionary.

To me, this does not say anything about transforming value to an array, only preserving it as an array if that was the input. In crafting such algorithmic text, decisions need to be made about brevity and conciseness vs lengthly exposition and IMO, the text is clear. However, if you think it can be improved, please suggest an alternate wording.

The text operates on @type without consideration to the presence of @value, which I don't believe is necessary, as there are safeguards elsewhere in the algorithm.

doriantaylor commented 6 years ago

I see now that plumping @type up to an array if it isn't one already (and with @value not present) takes place in §5.1.2.11.

A common strategy for dealing with input that may or may not be a sequence of items is to just unconditionally coerce single items into an array and then map over them, especially if you know it will be coerced into an array downstream. I admit however I didn't appreciate the delicateness of the operation. The problem went away when I added a conditional.

Nevertheless, to avoid correspondences like these, I am inclined to footnote step §5.1.2.9.4.4 with something like "at this time the status of whether or not this value is an array must be preserved" or simply "do not coerce the value into an array at this step; leave it as you found it", since other implementers are bound to try the map strategy.

I must say overall this represents the only failure to transcribe (at least so far that I can tell) in the nearly 600 lines of code I wrote to implement the expansion algorithm. Everything else executed on the very first try.