piprate / json-gold

A JSON-LD processor for Go
Apache License 2.0
259 stars 30 forks source link

Inconsistent behavior with absolute IRI prefix in context #57

Closed ewintr closed 2 years ago

ewintr commented 2 years ago

I am a bit confused by the following behavior. This will expand the lei prefix as expected:

  proc := ld.NewJsonLdProcessor()
  options := ld.NewJsonLdOptions("")

  doc := map[string]interface{}{
    "@context": []interface{}{
      map[string]interface{}{
        "lei": "urn:lei:",
      },
    },
    "@id": "http://example.com/speakers#Alice",
      "http://www.w3.org/md-odrl-profile/lei": map[string]interface{}{
        "@id": "lei:12345",
      },
   }

  flattenedDoc, err := proc.Flatten(doc, nil, options)
  if err != nil {
    log.Println("Error when flattening JSON-LD document:", err)
    return
  }

  ld.PrintDocument("JSON-LD flattened doc", flattenedDoc)

Result:

JSON-LD flattened doc
[
  {
    "@id": "http://example.com/speakers#Alice",
    "http://www.w3.org/md-odrl-profile/lei": [
      {
        "@id": "urn:lei:12345"
      }
    ]
  }
]

But this will throw an error "Error when flattening JSON-LD document: IRI confused with prefix: Absolute IRI lei:12345 confused with prefix lei":

  proc := ld.NewJsonLdProcessor()
  options := ld.NewJsonLdOptions("")

  ctx := map[string]interface{}{
    "lei": "urn:lei:",
  }
  doc := map[string]interface{}{
    "@id": "http://example.com/speakers#Alice",
      "http://www.w3.org/md-odrl-profile/lei": map[string]interface{}{
        "@id": "lei:12345",
      },
    }

  flattenedDoc, err := proc.Flatten(doc, ctx, options)
  if err != nil {
    log.Println("Error when flattening JSON-LD document:", err)
      return
  }

  ld.PrintDocument("JSON-LD flattened doc", flattenedDoc)

See playground1 and playground2

I can see that there is code in the Context type to explicitly forbid this type of prefix, but should it not be allowed? Trying the same example on the json-ld.org playground also works fine.

kazarena commented 2 years ago

@ewintr,

The two examples you provided have slightly different semantics.

  1. The first example contains a document with a prefix defined in the context. Because you don't provide the target context for flattening, the output will not be compacted.
  2. The second example passes the same document without a context. So, from the algorithm's perspective, lei: is not a prefix anymore, but a valid part of an absolute identifier. The subsequent compaction using the provided context gets confused and throws an error. By the way, I tried the same example on JSON-LD playground, and it produces the same error.

In order to get the flattening working, you should either 1) keep the context in the document, so that the prefix is visible to the algorithm, and then pass the context for compaction, as in your second example; or 2) pass the ID in the full form as urn:lei:12345 instead of lei:12345.

ewintr commented 2 years ago

Oh, this is very helpful. I now understand better where I went wrong. Thank you for explaining!