Re: [FHIR JSON-LD] How best to handle or avoid blank nodes?

One quick note: order matters within FHIR JSON arrays, so if you need to
support round-trips, you'd also want to add {"@container":"@list"} to your
context for every property that allows multiple cardinality.

On Thu, Feb 26, 2015 at 2:41 PM, Jim McCusker <mccusj@rpi.edu> wrote:

> Blank node IDs are only significant in RDF if they are objects of more
> than one statement. The two graphs you show above are semantically
> equivalent, so you should be fine omitting the @id. I would check to see if
> there are any edge cases where blank nodes might be referred to twice, but
> based on the original serialization in FRIR, that seems unlikely
> (especially since JSON is a tree).
>
> Jim
>
> On Thu Feb 26 2015 at 3:35:20 PM David Booth <david@dbooth.org> wrote:
>
>> On 02/25/2015 10:11 AM, Manu Sporny wrote:
>> > So, count us in - send the questions to the mailing list and it looks
>> > like you have multiple community members that would be willing to help
>> out.
>>
>> Thanks Manu (and Markus and Jim and any others)!   Okay, my first
>> question regards blank nodes.
>>
>> Here is an except of a FHIR JSON data:
>>
>> {
>>    "dob": "1972-11-30",
>>    "_dob": {
>>      "id": "314159",
>>      "extension": [{
>>         "url" : "http://example.org/fhir/extensions#text
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example.org_fhir_extensions-23text&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=v2-wOqi3M9X7-KyOF79RsqMm6dAJTXaxN3zBuJ8_YBo&e=>
>> ",
>>         "valueString" : "Easter 1970"
>>      }]
>> }
>>
>> To turn this into JSON-LD, I've created an @context:
>>
>> {
>>     "@context":
>>     {
>>        "@vocab": "http://example/fhir/vocab#
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=FqkUWPFwgp5vHwj6ndnm9tXnf0kAV_c_R2braWjY5VI&e=>
>> ",
>>        "fhir": "http://example/fhir#
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir-23&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=44EoZLooeCSOW3bMtRWsiClgUASN712lqm52Rw-wu8Q&e=>
>> ",
>>        "xsd": "http://www.w3.org/2001/XMLSchema#
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.w3.org_2001_XMLSchema-23&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=obVE-Xv77VHSs7JnAymzMxL2zy0-UzuTwxEV7-jEPGw&e=>
>> ",
>>        "dob":
>>        {
>>           "@id": "fhir:dob",
>>           "@type": "xsd:date"
>>        },
>>        "_dob":
>>        {
>>           "@id": "fhir:_dob",
>>           "@type": "@id"
>>        }
>>     }
>> }
>>
>> and I've linked it from the FHIR JSON document (thus involving a single,
>> constant, one-line change to the existing format).  Here is the
>> resulting JSON-LD, with three # comments added for reference later:
>>
>> {                                # _:b0
>>    "@context": "http://dbooth.org/2015/fhir/json-ld/dob-context.jsonld
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__dbooth.org_2015_fhir_json-2Dld_dob-2Dcontext.jsonld&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=E81eCUULmJadDJO2uHeEZiPIiNpxYd0Hr7xjtDaXLog&e=>
>> ",
>>    "dob": "1972-11-30",
>>    "_dob": {                      # _:b1
>>      "id": "314159",
>>      "extension": [{              # _:b2
>>         "url" : "http://example.org/fhir/extensions#text
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example.org_fhir_extensions-23text&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=v2-wOqi3M9X7-KyOF79RsqMm6dAJTXaxN3zBuJ8_YBo&e=>
>> ",
>>         "valueString" : "Easter 1970"
>>      }]
>> }
>>
>> As you can see, none of the JSON objects above has been given an @id, so
>> when this is interpreted as RDF, blank nodes (_:b0, _:b1, _:b2) are
>> generated to represent those unidentified objects.  Here is the RDF
>> interpretation in Turtle:
>>
>>    @prefix fhir:  <http://example/fhir#
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir-23&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=44EoZLooeCSOW3bMtRWsiClgUASN712lqm52Rw-wu8Q&e=>>
>> .
>>    @prefix xsd:  <http://www.w3.org/2001/XMLSchema#
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.w3.org_2001_XMLSchema-23&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=obVE-Xv77VHSs7JnAymzMxL2zy0-UzuTwxEV7-jEPGw&e=>>
>> .
>>
>>    _:b0 fhir:_dob  _:b1 ;
>>         fhir:dob   "1972-11-30"^^xsd:date .
>>
>>    _:b1 <http://example/fhir/vocab#extension
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23extension&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=iIY9cW0yRcF3shc1ydJ4xDEfzUghVtwawiskRULZX0k&e=>>
>> _:b2 ;
>>         <http://example/fhir/vocab#id
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23id&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=njZfZM2P8qG1p-cxeDuEi6AuQoDEMEJhXGCSXwvj8os&e=>>
>> "314159" .
>>
>>    _:b2 <http://example/fhir/vocab#url
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23url&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=GPeA354Va1jkpeQFE752CLXZBiUot0q4acRdZj_cxH4&e=>
>> >
>>             "http://example.org/fhir/extensions#text
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example.org_fhir_extensions-23text&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=v2-wOqi3M9X7-KyOF79RsqMm6dAJTXaxN3zBuJ8_YBo&e=>"
>> ;
>>         <http://example/fhir/vocab#valueString
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23valueString&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=0mV9key2_nwDiyT9LSr_hclTg69sdl8udFV_PPzN5M8&e=>
>> >
>>             "Easter 1970" .
>>
>> One of the key requirements is for FHIR data to be round-trippable
>> between the different data representations, such as XML and JSON.  This
>> means that if we interpret some given FHIR JSON-LD data as RDF, we need
>> to be able to serialize from RDF back to the *same* JSON-LD.  Here is
>> the result after serializing the above Turtle back into JSON-LD (using
>> jena riot), with line numbers added for reference:
>>
>>   1. {
>>   2.   "@context": {
>>   3.     "fhir": "http://example/fhir#
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir-23&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=44EoZLooeCSOW3bMtRWsiClgUASN712lqm52Rw-wu8Q&e=>
>> ",
>>   4.     "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.w3.org_1999_02_22-2Drdf-2Dsyntax-2Dns-23&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=1iTn8oAnsMWdsZra3QiQbxnFCg3BX9MhKc1AakAAiMQ&e=>
>> ",
>>   5.     "rdfs": "http://www.w3.org/2000/01/rdf-schema#
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.w3.org_2000_01_rdf-2Dschema-23&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=QB9OyblS_wpupoBsjjr9WamQxGXa6cMcF6ymV1IzNlc&e=>
>> ",
>>   6.     "xsd": "http://www.w3.org/2001/XMLSchema#
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.w3.org_2001_XMLSchema-23&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=obVE-Xv77VHSs7JnAymzMxL2zy0-UzuTwxEV7-jEPGw&e=>
>> "
>>   7.   },
>>   8.   "@graph": [
>>   9.     {
>> 10.       "@id": "_:fc7725329340449efa72b6f7f5d7182eeb3",
>> 11.       "http://example/fhir/vocab#url
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23url&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=GPeA354Va1jkpeQFE752CLXZBiUot0q4acRdZj_cxH4&e=>
>> ":
>> "http://example.org/fhir/extensions#text
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example.org_fhir_extensions-23text&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=v2-wOqi3M9X7-KyOF79RsqMm6dAJTXaxN3zBuJ8_YBo&e=>
>> ",
>> 12.       "http://example/fhir/vocab#valueString
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23valueString&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=0mV9key2_nwDiyT9LSr_hclTg69sdl8udFV_PPzN5M8&e=>":
>> "Easter 1970"
>> 13.     },
>> 14.     {
>> 15.       "@id": "_:fc7725329340449efa72b6f7f5d7182eeb2",
>> 16.       "http://example/fhir/vocab#extension
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23extension&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=iIY9cW0yRcF3shc1ydJ4xDEfzUghVtwawiskRULZX0k&e=>":
>> {
>> 17.         "@id": "_:fc7725329340449efa72b6f7f5d7182eeb3"
>> 18.       },
>> 19.       "http://example/fhir/vocab#id
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23id&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=njZfZM2P8qG1p-cxeDuEi6AuQoDEMEJhXGCSXwvj8os&e=>
>> ": "314159"
>>
>> 20.     },
>> 21.     {
>> 22.       "@id": "_:fc7725329340449efa72b6f7f5d7182eeb1",
>> 23.       "fhir:_dob": {
>> 24.         "@id": "_:fc7725329340449efa72b6f7f5d7182eeb2"
>> 25.       },
>> 26.       "fhir:dob": {
>> 27.         "@type": "xsd:date",
>> 28.         "@value": "1972-11-30"
>> 29.       }
>> 30.     }
>> 31.   ]
>> 32. }
>>
>> As you can see, there are several differences from the original JSON-LD,
>> which is not a surprise.  I already know that a generic RDF JSON-LD
>> serializer will not suffice for this purpose -- a special purpose
>> FHIR-aware JSON-LD serializer will be needed -- but that's okay, because
>> FHIR already requires a special-purpose serializer for its existing JSON
>> format anyway.   Some of the differences could be readily handled by a
>> special-purpose FHIR JSON-LD serializer (such as the outer @graph
>> wrapper and the embedded @context), but not all.
>>
>> In this message I want to focus specifically on the blank nodes, so for
>> the moment I'll ignore other differences.  Blank node labels are
>> arbitrary in RDF, so they might be serialized differently by different
>> serializers or in different runs of the same serializer, so I had been
>> thinking that, to enable predictable round tripping, it may be best to
>> generate predictable URIs instead of using blank nodes.  However, a
>> downside of this is that AFAIK it would require the FHIR JSON-LD
>> instance data -- not merely the @context -- to contain an explicit @id
>> property on every FHIR JSON-LD object.  Is this correct?  If so, FHIR
>> JSON users are likely to reject that option as too onerous, because most
>> of them don't care about RDF.  If not, how would URIs be specified in
>> the @context for JSON-LD objects that have no explicit @ids?
>>
>> However, I am now thinking that it might be better to allow those
>> unidentified JSON-LD objects to become blank nodes in the RDF
>> interpretation, and instead have the FHIR-specific JSON-LD serializer
>> suppress them (if they are blank nodes).   So instead of serializing a
>> bit of RDF as:
>>
>>    {
>>      "@id": "_:fc7725329340449efa72b6f7f5d7182eeb3",
>>      "http://example/fhir/vocab#url
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23url&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=GPeA354Va1jkpeQFE752CLXZBiUot0q4acRdZj_cxH4&e=>
>> ":
>> "http://example.org/fhir/extensions#text
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example.org_fhir_extensions-23text&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=v2-wOqi3M9X7-KyOF79RsqMm6dAJTXaxN3zBuJ8_YBo&e=>
>> ",
>>      "http://example/fhir/vocab#valueString
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23valueString&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=0mV9key2_nwDiyT9LSr_hclTg69sdl8udFV_PPzN5M8&e=>":
>> "Easter 1970"
>>    },
>>
>> it would instead omit the @id property and serialize it as:
>>
>>    {
>>      "http://example/fhir/vocab#url
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23url&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=GPeA354Va1jkpeQFE752CLXZBiUot0q4acRdZj_cxH4&e=>
>> ":
>> "http://example.org/fhir/extensions#text
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example.org_fhir_extensions-23text&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=v2-wOqi3M9X7-KyOF79RsqMm6dAJTXaxN3zBuJ8_YBo&e=>
>> ",
>>      "http://example/fhir/vocab#valueString
>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__example_fhir_vocab-23valueString&d=BQMFaQ&c=qS4goWBT7poplM69zy_3xhKwEW14JZMSdioCoppxeFU&r=c7b1QeR755-dBx2b0xnlepDTylromoEzcLl-6ixmBL3TpXSxSvtAvT553fzSgLpm&m=cwBQRtzGpJh6TOof7KR8AR7dd72k3x6hssmzw4HweFk&s=0mV9key2_nwDiyT9LSr_hclTg69sdl8udFV_PPzN5M8&e=>":
>> "Easter 1970"
>>    },
>>
>> Does this seem like a good idea?   Any hidden problems?  Are there other
>> approaches that you think would be better?
>>
>> Thanks,
>> David
>>
>

Received on Thursday, 26 February 2015 23:19:42 UTC