w3c / w3c/json-ld-syntax

Terms defined using list containers only preserve the latest-declared list value?

Open
#492 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs discussion
Dominant language
HTML
Stars
139
Forks
23
PR merge metrics
No merged PRs in 30d

Description

Background

Context

In Activity Streams 2.0's normative context document, we define "items" and "orderedItems" separately, but with the same id. The difference is that "orderedItems" uses a list container, and "items" does not:

"items": {
  "@id": "as:items",
  "@type": "@id"
},
"orderedItems": {
  "@id": "as:items",
  "@type": "@id",
  "@container": "@list"
},
Simple example

Consider the input graph:

{
  "@id": "c",
  "https://www.w3.org/ns/activitystreams#items": [
    {"@list": [
      {"@id": "o1"}
    ]},
    {"@list": [
      {"@id": "o2"}
    ]}
  ]
}

You would expect both o1 and o2 to show up in the compacted result in some fashion, perhaps something like this: https://json-ld.org/playground/#startTab=tab-compacted&json-ld=%7B%22%40id%22%3A%22c%22%2C%22https%3A%2F%2Fwww.w3.org%2Fns%2Factivitystreams%23items%22%3A%5B%7B%22%40list%22%3A%5B%7B%22%40id%22%3A%22o1%22%7D%5D%7D%2C%7B%22%40list%22%3A%5B%7B%22%40id%22%3A%22o2%22%7D%5D%7D%5D%7D&context=%7B%22%40context%22%3A%7B%22items%22%3A%7B%22%40id%22%3A%22https%3A%2F%2Fwww.w3.org%2Fns%2Factivitystreams%23items%22%2C%22%40type%22%3A%22%40id%22%7D%7D%7D

{
  "@context": {
    "items": {
      "@id": "https://www.w3.org/ns/activitystreams#items",
      "@type": "@id"
    }
  },
  "@id": "c",
  "items": [
    {
      "@list": [
        "o1"
      ]
    },
    {
      "@list": [
        "o2"
      ]
    }
  ]
}

But in actuality, when both "items" and "orderedItems" are defined, only o2's list is preserved, via "orderedItems": https://json-ld.org/playground/#startTab=tab-compacted&json-ld=%7B%22%40id%22%3A%22c%22%2C%22https%3A%2F%2Fwww.w3.org%2Fns%2Factivitystreams%23items%22%3A%5B%7B%22%40list%22%3A%5B%7B%22%40id%22%3A%22o1%22%7D%5D%7D%2C%7B%22%40list%22%3A%5B%7B%22%40id%22%3A%22o2%22%7D%5D%7D%5D%7D&context=%7B%22%40context%22%3A%7B%22items%22%3A%7B%22%40id%22%3A%22https%3A%2F%2Fwww.w3.org%2Fns%2Factivitystreams%23items%22%2C%22%40type%22%3A%22%40id%22%7D%2C%22orderedItems%22%3A%7B%22%40id%22%3A%22https%3A%2F%2Fwww.w3.org%2Fns%2Factivitystreams%23items%22%2C%22%40type%22%3A%22%40id%22%2C%22%40container%22%3A%22%40list%22%7D%7D%7D

{
  "@context": {
    "items": {
      "@id": "https://www.w3.org/ns/activitystreams#items",
      "@type": "@id"
    },
    "orderedItems": {
      "@id": "https://www.w3.org/ns/activitystreams#items",
      "@type": "@id",
      "@container": "@list"
    }
  },
  "@id": "c",
  "orderedItems": [
    "o2"
  ]
}

You can see this happen with the normative activitystreams context document, too: https://json-ld.org/playground/#startTab=tab-compacted&json-ld=%7B%22%40id%22%3A%22c%22%2C%22https%3A%2F%2Fwww.w3.org%2Fns%2Factivitystreams%23items%22%3A%5B%7B%22%40list%22%3A%5B%7B%22%40id%22%3A%22o1%22%7D%5D%7D%2C%7B%22%40list%22%3A%5B%7B%22%40id%22%3A%22o2%22%7D%5D%7D%5D%7D&context=%7B%22%40context%22%3A%22https%3A%2F%2Fwww.w3.org%2Fns%2Factivitystreams%22%7D

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "c",
  "orderedItems": ["o2"]
}
Slightly more complex example

Consider the input graph:

{
  "@id": "c",
  "https://www.w3.org/ns/activitystreams#items": [
    {"@list": [
      {"@list": [{"@id": "o1"}]},
      {"@id": "o2"}
    ]},
    {"@id": "o3"},
    {"@list": [
      {"@list": [{"@id": "o4"}]},
      {"@id": "o5"}
    ]},
    {"@id": "o6"}
  ]
}

The JSON-LD playground produces this: https://json-ld.org/playground/#startTab=tab-compacted&json-ld=%7B%22%40id%22%3A%22c%22%2C%22https%3A%2F%2Fwww.w3.org%2Fns%2Factivitystreams%23items%22%3A%5B%7B%22%40list%22%3A%5B%7B%22%40list%22%3A%5B%7B%22%40id%22%3A%22o1%22%7D%5D%7D%2C%7B%22%40id%22%3A%22o2%22%7D%5D%7D%2C%7B%22%40id%22%3A%22o3%22%7D%2C%7B%22%40list%22%3A%5B%7B%22%40list%22%3A%5B%7B%22%40id%22%3A%22o4%22%7D%5D%7D%2C%7B%22%40id%22%3A%22o5%22%7D%5D%7D%2C%7B%22%40id%22%3A%22o6%22%7D%5D%7D&context=%7B%22%40context%22%3A%22https%3A%2F%2Fwww.w3.org%2Fns%2Factivitystreams%22%7D

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "c",
  "orderedItems": [
    [
      "o4"
    ],
    "o5"
  ],
  "items": [
    "o3",
    "o6"
  ]
}

Here, we note that o3 and o6 were split out into the "items" property, which defaults to an unordered set container. This is expected.

But we also note that the "orderedItems" property, which is defined as an ordered list container, should refer to both lists in the input graph. Curiously, the list containing the list-of-o1 and then o2 has disappeared from the compacted output entirely.

Questions

What is the correct behavior here?

I can't imagine the disappearance of o1 and o2 to be correct, but there is a difference between [{"@list": []}, {"@list": []}] and "@list": [{"@list": []}, {"@list": []}]. With there being 2 list values in an unordered set, I would guess that the "orderedItems" term is no longer fully appropriate? So maybe the correct answer should be something like applying only the "items" term definition:

{
  "@context": {
    "items": {
      "@id": "https://www.w3.org/ns/activitystreams#items",
      "@type": "@id"
    }
  },
  "@id": "c",
  "items": [
    {
      "@list": [
        "o1"
      ]
    },
    {
      "@list": [
        "o2"
      ]
    }
  ]
}

which applies the @type: @id of the "items" term definition and preserves the lists as @list nodes.

For the more complex example:

{
  "@context": {
    "items": {
      "@id": "https://www.w3.org/ns/activitystreams#items",
      "@type": "@id"
    }
  },
  "@id": "c",
  "items": [
    {
      "@list": [
        {
          "@list": [
            {
              "@id": "o1"
            }
          ]
        },
        "o2"
      ]
    },
    "o3",
    {
      "@list": [
        {
          "@list": [
            {
              "@id": "o4"
            }
          ]
        },
        "o5"
      ]
    },
    "o6"
  ]
}

More precisely, if both "items" and "orderedItems" are defined, then the definition of "orderedItems" will cause some information to be lost. More generally: A term definition using @container: @list will result in information loss with more than 1 list value, regardless if a term definition without @container: @list is present.

Is the bug in the compaction algorithm or in the implementation?

This was observed on the JSON-LD playground, which uses jsonld.js iirc. But it's possible the issue is actually an oversight of the compaction algorithm itself, so I'm filing this here for now. If the compaction algorithm actually accounts for this, then I can refile the issue against jsonld.js and/or the playground.

Etc

I found this possibly related issue:

  • #428

Although this current issue seems to occur even with "simpler" lists that don't contain other lists.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the examples in the JSON-LD playground using the normative Activity Streams context and compare the simple and nested-list outputs. Read related issue #428 and determine whether the information loss is permitted by the compaction algorithm or is an implementation issue; done means the correct behavior and affected component are established.

Written by the indexing model from the issue text.

Assessment

Tech stack
json
Domain
data, documentation
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.