This document provides guidance from the NIEM Technical Architecture Committee (NTAC) for using the National Information Exchange Model (NIEM) with JavaScript Object Notation (JSON). NIEM provides a well-established standard for defining information exchanges. JSON is specified by RFC4627.
This guidance is non-normative. It discusses possible NIEM conformance rules for JSON data, but it does not establish any specification for such conformance.
This document is a working draft; revisions and additions are expected. Readers are invited to provide feedback on this document by entering an issue at https://github.com/NIEM/NIEM.github.io/issues or sending email to niem-comments@lists.gatech.edu.
This document provides guidance from the NIEM Technical Architecture Committee (NTAC) for using the National Information Exchange Model (NIEM) with JavaScript Object Notation (JSON). NIEM provides a well-established standard for defining information exchanges. JSON is specified by RFC4627.
This document is provided as guidance, not as a normative specification. It discusses possible NIEM conformance rules for JSON data, but it does not establish any specification for such conformance. This document is the first step in establishing a repeatable and interoperable methodology for using JSON to represent NIEM-conformant information exchanges. The guidelines presented by this document should be in alignment with later normative specifications that define NIEM-conformant JSON.
The primary target of this guidance is the developer who has a NIEM IEPD that defines one or more XML messages, and who wishes to exchange JSON representations of those messages, instead of XML. For these users, this document supplies patterns for converting an NIEM XML document (i.e., an IEP, an information exchange package) into a semantically-equivalent JSON serialization.
This document also provides guidance for the developer who wishes to use NIEM definitions in a JSON object design. Guidance for developers who wish to map existing JSON objects to NIEM XML may be provided at a later date.
This document is one step in the NTAC technical road map for JSON, Using JSON with NIEM. It describes NIEM’s methodology for creating consistent, interoperable JSON messages that are based on NIEM-conformant XML schemas. Core aspects of this guidance are:
The NIEM Naming and Design Rules (NDR) is the main document that explains the meaning of NIEM–conformant XML schemas and XML instance documents. The framework that the NIEM NDR relies on for meaning is the Resource Description Framework (RDF), which defines a data model that is the basis for Semantic Web technologies. NIEM defines the meaning of conformant XML schemas and XML instance documents in terms of RDF. This document leverages the NDR’s RDF to map NIEM XML schemas and XML instance documents to JSON-LD.
Although NIEM is, at its core, defined in terms of RDF, most users of NIEM do not have to understand much about RDF; NIEM is primarily discussed in terms of XML and XML schema: rules about elements, attributes, simple and complex types, etc. Similarly, users of this guidance document, and of NIEM’s JSON-LD representation, will not need to understand much about RDF. The few RDF concepts this document explicitly requires are explained without requiring deep understanding of the underlying RDF concepts.
The NIEM NDR Section 5, “The NIEM conceptual model” describes the conceptual model of NIEM, and provides a mapping between NIEM-conformant XML schemas and XML instance documents, and RDF. This section is the basis for much of what appears in this document. For example:
These, and other sections of the NDR are the basis of the translation from NIEM XML to JSON-LD. A goal of this document is to explain the translations from NIEM to JSON-LD sufficiently, so that the reader does not need to understand the NDR’s mappings to RDF, nor the JSON-LD’s RDF basis.
This document describes the translation of NIEM-conformant XML instance documents (informed by certain features of schemas, such as component types) into JSON, using JSON-LD as the target JSON representation. JSON-LD (JavaScript Object Notation for Linking Data) is a language-independent data format for representing Linked Data, expressed as JSON. JSON-LD provides a lightweight mechanism that allows data to be linked across websites. The syntax is easy for humans to read and easy for machines to parse and generate.
One reason for choosing JSON-LD is its context mechanism, which allows IRIs in JSON-LD to look like XML qualified names (QNames). As described above, the NDR defines how to translate element QNames to IRIs. These IRIs can be represented in a short form using a JSON-LD context.
Take, for example, the following JSON data:
{
"http://release.niem.gov/niem/niem-core/3.0/#quantityUnitText" : "dozen"
}
The key in this JSON object is the IRI defined by NIEM for the
nc:quantityUnitText
attribute. Using the JSON-LD context mechanism,
that IRI can be compacted. as follows:
{
"@context": {
"nc": "http://release.niem.gov/niem/niem-core/3.0/#"
},
"nc:quantityUnitText": "dozen"
}
The benefits of a JSON-LD representation are apparent. The context object preserves the information in the XML namespace declarations. The JSON object key is a familiar NIEM QName. That QName can be converted into the full IRI by an expansion algorithm defined for JSON-LD by JSON-LD 1.0 Processing Algorithms and API, Section 2.1, “Expansion”.
A second reason for choosing JSON-LD is that JSON-LD is a concrete RDF syntax, like RDF/XML or Turtle. This means that NIEM JSON-LD data may be processed using RDF techniques, such as SPARQL queries. This also means that there are now two methods of generating RDF from NIEM-conforming XML documents and schemas: the first defined in NIEM NDR Section 5, the second described by this guidance. The NTAC’s intention is that the two methods produce consistent RDF; realizing this intention may require future changes to the NDR, this guidance, or both.
Based on the above, all three of these methods are legitimate ways to access NIEM JSON-LD data:
The guidance in the next major section is intended to describe a JSON-LD serialization of NIEM-conforming XML that is easy to generate, and convenient to process, for all three of these consumer use cases. Certain advanced concerns for that serialization may be found in section 4. This document does not attempt to teach best practices for JSON or JSON-LD; for that, the reader may turn to http://json-ld.org/spec/latest/json-ld-api-best-practices, or other similar resources.
A NIEM-conformant schema defines a simple object model. Here is an example of data that is defined by a NIEM schema:
This data can be represented in either of two forms: XML or JSON. Here are an XML and a JSON representation for this data, side-by-side:
<?xml version="1.0" encoding="UTF-8"?> {
<cyfs:PersonOtherKinAssociation "@context" : {
xmlns:cyfs="http://release.niem.gov/niem/domains/cyfs/3.2/" "cyfs": "http://release.niem.gov/niem/domains/cyfs/3.2/#",
xmlns:j="http://release.niem.gov/niem/domains/jxdm/5.2/" "j": "http://release.niem.gov/niem/domains/jxdm/5.2/#",
xmlns:nc="http://release.niem.gov/niem/niem-core/3.0/"> "nc": "http://release.niem.gov/niem/niem-core/3.0/#"
},
"cyfs:PersonOtherKinAssociation": {
<cyfs:SourcePerson> "cyfs:SourcePerson": {
<nc:PersonAgeMeasure> "nc:PersonAgeMeasure": {
<nc:MeasureIntegerValue>14</nc:MeasureIntegerValue> "nc:MeasureIntegerValue": 14,
<nc:TimeUnitCode>ANN</nc:TimeUnitCode> "nc:TimeUnitCode": "ANN"
</nc:PersonAgeMeasure> },
<j:PersonHairColorCode>BRO</j:PersonHairColorCode> "j:PersonHairColorCode": "BRO",
<nc:PersonName> "nc:PersonName": {
<nc:PersonGivenName>Mortimer</nc:PersonGivenName> "nc:PersonGivenName": "Mortimer",
<nc:PersonSurName>Smith</nc:PersonSurName> "nc:PersonSurName": "Smith",
<nc:PersonNameSuffixText>Sr</nc:PersonNameSuffixText> "nc:PersonNameSuffixText": "Sr",
<nc:PersonPreferredName>Morty</nc:PersonPreferredName> "nc:PersonPreferredName": "Morty"
</nc:PersonName> }
</cyfs:SourcePerson> },
<cyfs:TargetPerson> "cyfs:TargetPerson": {
<j:PersonHairColorCode>GRY</j:PersonHairColorCode> "j:PersonHairColorCode": "GRY",
<nc:PersonName> "nc:PersonName": {
<nc:PersonGivenName>Rick</nc:PersonGivenName> "nc:PersonGivenName": "Rick",
<nc:PersonSurName>Sanchez</nc:PersonSurName> "nc:PersonSurName": "Sanchez"
</nc:PersonName> }
</cyfs:TargetPerson> },
<cyfs:PersonOtherKinAssociationCategoryCode "cyfs:PersonOtherKinAssociationCategoryCode":
>Maternal Grandfather</cyfs:PersonOtherKinAssociationCategoryCode> "Maternal Grandfather"
</cyfs:PersonOtherKinAssociation> }
}
You can exchange NIEM data either as XML or as JSON. Either way, the data that is expected in a message, and the meaning of that data, is defined by NIEM schemas.
The NIEM JSON representation uses JSON-LD, which means that order of NIEM JSON data is flexible, that the names of keys is determined by JSON-LD contexts, that the JSON representation is also an RDF representation, and that there are additional tools available for working with NIEM JSON.
One method of facilitating NIEM JSON exchanges is for someone who understands
NIEM schemas to construct a template JSON instance, which is a NIEM JSON
instance for a NIEM schema, but with data values replaced with null
. This
method is described by the next section.
Another method of facilitating NIEM JSON exchanges is to translate between NIEM XML and NIEM JSON. This is described in a section below. That section also describes how NIEM JSON represents data that is more complex. Although NIEM XML is used in that section describe how NIEM JSON works in various situations, you do not have to work with NIEM XML or translate between JSON and XML to work with NIEM JSON.
One way to make it simpler for the JSON developer to create JSON-LD documents for a NIEM exchange is to provide a fully completed JSON-LD document structure with all “null” values. The IEP designer provides an iep-sample-template.jsonld document in the iep-samples directory that describes the context and structure of the document for the exchange. The developer populates the fields for which they have values and submits the document. All elements with null values are ignored during processing at the receiving end.
The following JSON example is a JSON IEP template for the simple object model from Section 1.5, above.
{
"@context": {
"exch": "http://example.com/SimpleExchange/1.0/#",
"j": "http://release.niem.gov/niem/domains/jxdm/5.1/#",
"nc": "http://release.niem.gov/niem/niem-core/3.0/#",
"cyfs": "http://release.niem.gov/niem/domains/cyfs/3.2/"
},
"cyfs:PersonOtherKinAssociation": {
"cyfs:SourcePerson": {
"nc:PersonAgeMeasure": {
"nc:MeasureIntegerValue": null,
"nc:TimeUnitCode": null
},
"j:PersonHairColorCode": null,
"nc:PersonName": {
"nc:PersonGivenName": null,
"nc:PersonSurName": null,
"nc:PersonNameSuffixText": null,
"nc:PersonPreferredName": null
}
},
"cyfs:TargetPerson": {
"j:PersonHairColorCode": null,
"nc:PersonName": {
"nc:PersonGivenName": null,
"nc:PersonSurName": null
}
},
"cyfs:PersonOtherKinAssociationCategoryCode": null
}
}
This section describes the translation of an example IEP (information exchange package, an XML instance document), defined by an IEPD (information exchange package description), into the corresponding JSON-LD data. Each section within highlights the transformation of a NIEM or XML concept into corresponding JSON-LD. The full source XML appears in an appendix below. The resulting JSON-LD also appears in an appendix below.
This section makes simplifying assumptions, which may not apply to every NIEM IEP. If your IEP is more complicated, then you may have to extend the guidelines to cover your data.
Throughout these examples, at each stage, content is omitted or held back for later sections. When content is left out, an ellipsis (“…”) appears in place of the omitted text.
The IEP as a whole is represented by a JSON object, evident in an
instance by an outside set of curly braces. The sub-objects for the
root element and @context
go within that object:
{
"@context" : {
...
},
...
}
Rules for what goes in this object follow below.
NIEM uses XML namespaces to distinguish components with similar names, to identify the authorities responsible for managing a set of XML schema components, and to organize data definitions among NIEM Core, domains, IEPD extensions, etc. Every NIEM IEP has namespace declarations for its content. To uniquely specify a NIEM element, attribute, or schema component, its local name must be combined with the namespace associated with its namespace prefix.
The context mechanism in JSON-LD can serve a purpose similar to XML namespaces. JSON-LD uses International Resource Identifiers (IRIs) as keys within JSON objects, and to uniquely identify objects. A JSON-LD context can define parts of IRIs, which can be used in short-form terms which expand into full IRIs. So, XML namespaces in the IEP are mapped to JSON-LD context entries, to support short-form terms.
ASSUMPTIONS: All of the IEP’s namespace declarations are at or above the IEP’s root element (if there is an envelope around the IEP’s root element). There is no content using the default (no namespace prefix) namespace.
These are the namespace declarations in the sample IEP:
<exch:CrashDriverInfo
xmlns:exch="http://example.com/CrashDriver/1.0/"
xmlns:j="http://release.niem.gov/niem/domains/jxdm/5.1/"
xmlns:nc="http://release.niem.gov/niem/niem-core/3.0/"
xmlns:geo="http://release.niem.gov/niem/adapters/geospatial/3.0/"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:structures="http://release.niem.gov/niem/structures/3.0/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<nc:Person structures:id="P01">
...
</exch:CrashDriverInfo>
Each declared namespace prefix is converted into an @context
entry:
The rules for constructing IRIs from QNames are provided by NDR section 5.6.1, “Resource IRIs for XML Schema components and information items”. This leads to the definition of IRI roots as follows:
For the QName nc:Person
this yields the IRI http://release.niem.gov/niem/niem-core/3.0/#Person
.
In addtion, we apply the following guidelines:
xsi
namespace, http://www.w3.org/2001/XMLSchema-instance
, which
is reserved for XML Schema-specific concepts, and is not carried over into
JSON-LD.rdf
to
http://www.w3.org/1999/02/22-rdf-syntax-ns#
. This is used for rdf:value
and rdf:XMLLiteral
.This yields the following @context
entry:
{
"@context" : {
"exch" : "http://example.com/CrashDriver/1.0/#",
"j" : "http://release.niem.gov/niem/domains/jxdm/5.1/#",
"nc" : "http://release.niem.gov/niem/niem-core/3.0/#",
"geo" : "http://release.niem.gov/niem/adapters/geospatial/3.0/",
"gml" : "http://www.opengis.net/gml/3.2#",
"structures" : "http://release.niem.gov/niem/structures/3.0/#",
"rdf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
},
"exch:CrashDriverInfo" : {
...
}
}
Each element within the IEP is converted to a key in a JSON-LD node object.
The root element (or document element) of a NIEM IEP is also converted to a node object. It is given the JSON key corresponding to the QName (XML qualified name) of the element. This may be expanded into an IRI by a JSON-LD processor, but this guidance recommends using the QName, supported by a context entry for the IRI root. Within the full example, this yields:
{
"@context": {
"exch": "http://example.com/CrashDriver/1.0/#",
...
},
"exch:CrashDriverInfo": {
...
}
}
Seems to me we need only one of sections 2.1 and 2.3. I’d keep 2.3. —@iamdrscott
Since the top level element is a
NIEM object type, we convert most
elements within to a key for the top-level element’s JSON-LD object. In the
sample instance, exch:CrashDriverInfo
has the following child elements:
nc:Person
j:Crash
j:PersonChargeAssociation
j:Charge
j:JusticeMetadata
These are each converted into keys within the exch:CrashDriverInfo
object
described above:
...
"exch:CrashDriverInfo": {
"nc:Person": {
...
},
"j:CrashDriver": {
...
},
"j:PersonChargeAssociation": {
...
},
"j:Charge": {
...
}
"j:JusticeMetadata": {
...
}
}
This is the most common case; this is how object types and association type are translated to JSON-LD.
Note that there is only one pair for each child element name, no matter how many times that element appears in the content. It is now time to discuss…
In the full example XML IEP, The element
nc:PersonMiddleName
is repeated within nc:PersonName
:
<nc:PersonName nc:personNameCommentText="copied">
<nc:PersonGivenName nc:sequenceID="1">Peter</nc:PersonGivenName>
<nc:PersonMiddleName nc:sequenceID="2">Death</nc:PersonMiddleName>
<nc:PersonMiddleName nc:sequenceID="3">Bredon</nc:PersonMiddleName>
<nc:PersonSurName>Wimsey</nc:PersonSurName>
</nc:PersonName>
Since nc:PersonMiddleName
is repeated, it is represented using the key
nc:PersonMiddleName
, with a value that is an array of objects:
"nc:PersonName": {
"nc:PersonGivenName": <!-- content of element nc:PersonGivenName -->,
"nc:PersonMiddleName": [
<!-- content of first element nc:PersonGivenName -->,
<!-- content of second element nc:PersonGivenName -->
],
"nc:PersonSurName": <!-- content of element nc:PersonSurName -->,
"nc:personNameCommentText": "copied"
}
We see that occurrences of element nc:PersonMiddleName
are bundled
together as an array, and that array is the value for key
nc:PersonMiddleName
. A repeated element is converted into a JSON
object with an array value. (This is done for elements with simple
content as well as the complex elements shown.) The array contains one
JSON object for the content of each element instance. Note that order
of data within an array should not be considered significant, as
described below.
Consumers of NIEM JSON-LD data must be aware that the value of a repeatable element may be an array (if the element is in fact repeated), or an object (if it is not), and code accordingly.
Observe that with this guidance, the same JSON is produced for these
two Parent
elements:
|<Parent> | <Parent> |
| <Repeated/> | <Repeated/> |
| <Repeated/> | <Child/> |
| <Child/> | <Repeated/> |
|</Parent> | </Parent> |
Therefore it is up to the developer to ensure that these two elements have the same meaning in the IEP. If the meaning depends on the difference in element ordering, then the guidance in this document does not apply, and the developer is on his own. However, in that case, the IEPD design is bad, conflicting with the NIEM Conceptual Model.
The content of an element with complex content is converted to a JSON object with one pair for the name of each attribute and one pair for the name of each child element in that content. For example, in the sample IEP we have
<nc:PersonName nc:personNameCommentText="copied">
<nc:PersonGivenName nc:sequenceID="1">Peter</nc:PersonGivenName>
<nc:PersonMiddleName nc:sequenceID="2">Death</nc:PersonMiddleName>
<nc:PersonMiddleName nc:sequenceID="3">Bredon</nc:PersonMiddleName>
<nc:PersonSurName>Wimsey</nc:PersonSurName>
</nc:PersonName>
which is converted to the following JSON
"nc:PersonName": {
"nc:personNameCommentText": "copied",
"nc:PersonGivenName": {
...
},
"nc:PersonMiddleName": [
...
],
"nc:PersonSurName": {
...
}
}
Observe that for a NIEM-conforming IEP, there can’t be a collision between attribute and child element names, because of the camel-case rule. For an IEP that is not NIEM conforming, it is possible to have an attribute and a child element with the same name. This document has no guidance for such non-conforming IEPs; developers are on their own.
The nc:PersonGivenName
element has simple content and
attributes. Its JSON representation is
"nc:PersonGivenName" : {
"nc:sequenceID" : 1,
"rdf:value" : "Peter"
}
The element’s simple content can’t be represented by
{"nc:PersonGivenName" : "Peter" }
, because then there is no place to
put the attributes. Instead, the representation must be an object,
with ordinary keys for the attributes and a special key for the simple
content. That special key could have a magic syntax, such as "."
,
but this would only work for plain JSON consumers; to process the data
as JSON-LD or RDF, the key must be a term mapped to an IRI.
According to the RDF
Primer (2004),
rdf:value
is customarily used in this situation where a property has
one main value and one or more additional values providing context
that qualifies the main value. Therefore, this
guidance chooses rdf:value
for the special key. This choice also makes
the JSON-LD representation consistent with NDR content of an
element, which specifies that
non-empty simple values are mapped in this way.
Obviously this will break if an element in the IEP has rdf:value
as
an attribute. Fortunately, there is no good reason to do that in a NIEM IEP.
The nc:Date
element has simple content and no attributes. Its JSON-LD
representation is
"nc:Date" :"1893-05-04"
With no attributes, there is no need for the rdf:value
key, and so it
is not used. Consumers of NIEM JSON-LD data must be aware that the
value of a simple element may be an object (if the element has
attributes), or a value (if it does not), and code accordingly.
When the IEPD schema defines a numeric type for a simple element, the
value of the JSON pair is a number. Likewise, when the schema defines
a boolean type, the value of the JSON pair is true
or false
. For
example, the representations of nc:MeasureDecimalValue
and
exch:PersonFictionalCharacterIndicator
are:
"nc:MeasureDecimalValue" : 9.7
"exch:PersonFictionalCharacterIndicator" : true
There are three situations in an XML instance where an element may have empty content:
minOccurs="0"
.xsi:nil="true"
.Cases 1 and 2 are represented the same way in JSON-LD: There is no value associated with the element. Take this XML example (case 1):
<nc:Person/>
…or the equivalent (case 1):
<nc:Person></nc:Person>
Both of these omit any content. To be a valid XML instance, the schema for this
must either define nc:PersonType
(the type defined by NIEM for element
nc:Person
) with no child elements, or with child elements that have
minOccurs="0"
. A similar instance may use xsi:nil
(case 2):
<nc:Person xsi:nil="true"/>
This XML instance may be valid with mandatory element children, as long as
nillable="true"
is set for the element. The JSON for all of these is the same:
"nc:Person" : { }
This expresses that nc:Person
is a node object, but does not assert any other
properties.
An element carrying an empty string (case 2) is represented differently. In NIEM, element
nc:PersonGivenName
is defined to have simple content based on xs:string
. So,
if that element is empty, it represents the empty string. The XML instance (case 2):
<nc:PersonGivenName></nc:PersonGivenName>
…and the equivalent XML (case 2):
<nc:PersonGivenName/>
…are both carrying the empty string as children of
nc:PersonGivenName
. This may be represented with the JSON:
"nc:PersonGivenName" : ""
NIEM defines the attribute structures:id
to carry ID
values. structures:id
is the only ID-typed attribute allowed in
NIEM-conformant content (except for externally-defined content). An
ID attribute in XML defines a unique document-relative unique
identifier: An ID value may appear in at most one element within a
single XML document; the same ID value may appear in any number of
different documents.
The NIEM-defined structures:id
attribute is represented by the JSON-LD
reserved key @id
. The value for @id
is the value of structures:id
. For
example, the XML:
<nc:Person structures:id="P01">
<nc:PersonBirthDate>
<nc:Date>1893-05-04</nc:Date>
</nc:PersonBirthDate>
<nc:PersonName nc:personNameCommentText="copied">
...
</nc:PersonName>
<exch:PersonFictionalCharacterIndicator>true</exch:PersonFictionalCharacterIndicator>
</nc:Person>
…is represented by the JSON-LD:
"nc:Person" : {
"@id" : "P01",
"nc:PersonBirthDate": {
"nc:Date": "1893-05-04"
},
"nc:PersonName": {
"nc:personNameCommentText" : "copied",
...
},
"exch:PersonFictionalCharacterIndicator": true
}
The JSON-LD processor will process @id
values against a base IRI. This might
be automatically generated by a system (for example, the JSON-LD Playground uses
a base IRI of http://json-ld.org/playground/
). The base IRI may also be set by @base
within an @context
, as described by JSON-LD 1.0, Section 6.1, “Base IRI”.
The value of a structures:ref
attribute and any other IDREF
attribute is converted into a reference using the @id of the
corresponding JSON-LD node. For example, the representation for
<nc:RoleOfPerson structures:ref="P01" xsi:nil="true"/>
is
"nc:RoleOfPerson" : {
"@id" : "P01"
}
The representation of a reference element has no content from the
element value, either complex or simple; that is, the only content is
the "@id":"idref"
pair and zero or more attributes. In NIEM JSON-LD
data created according to this guidance, this will be true of every
object representing a reference element. In addition, there must be
exactly one object containing the "@id":"value"
pair that does have
child elements or simple element content. That will be the object
representing the element with the structures:id
attribute, as
described above. These constraints are not part of
JSON-LD; it is created by this guidance.
Observe that the xsi:nil
attribute, which is useful only for schema
validation, does not appear in the JSON-LD representation.
Because this guidance does not seek to replicate in JSON the underlying XML Schema powering NIEM, substitution groups are simply represented by replicating the XML instance structure, where the substitution has already taken place. Abstract elements do not appear at all. For example,
<nc:Person>
<!-- Date substituted for DateRepresentation -->
<nc:PersonBirthDate>
<nc:Date>1893-05-04</nc:Date>
</nc:PersonBirthDate>
</nc:Person>
becomes
"nc:Person" : {
"nc:PersonBirthDate" : {
"nc:Date" : "1893-05-04"
}
}
NIEM has two kinds of augmentation elements. The most common is a
container element that is derived from AugmentationType
and has a
name ending in Augmentation
; for example, LicenseAugmentation
in
the sample IEP. These augmentation container elements are important
for schema validation, but have no role in the conceptual model, and
so they do not appear in the JSON representation. So, for example, the
representation of j:DriverLicense
is
"j:DriverLicense" : {
"j:DriverLicenseCardIdentification" : {
"nc:IdentificationID" : "A1234567"
},
"nc:ItemLengthMeasure" : {
"nc:MeasureDecimalValue" : 9.7,
"nc:LengthUnitCode" : "CMT"
}
}
The other kind of augmentation element is an element declared in the
substitution group of an AugmentationPoint
. For example, the IEPD
schema includes the following element declaration:
<xs:element name="PersonFictionalCharacterIndicator" type="niem-xs:boolean"
substitutionGroup="nc:PersonAugmentationPoint">
<xs:annotation><xs:documentation>
True if this person is a fictional character in a literary work.
</xs:documentation></xs:annotation>
</xs:element>
Augmentation elements of this kind are treated the same as any other child element.
We are still working on figuring out how to represent metadata in JSON-LD. The NDR says to hang metadata on RDF statements, but it is not clear what would be the best way to do that. One option is if the XML contains metadata, then create an RDF statement and hang the metadata off of that. Metadata on objects can be handled with rdf:value, but metadata on associations is harder. —@webb, —@leilatite
One way to do that is through reification. The JSON-LD would look something like example from stack overflow:
{
"@context": {
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"subject": { "@id": "rdf:subject", "@type": "@id" },
"predicate": { "@id": "rdf:predicate", "@type": "@id" },
"object": { "@id": "rdf:object", "@type": "@id" },
"j": "http://release.niem.gov/niem/domains/jxdm/5.1/#",
"structures": "http://release.niem.gov/niem/structures/3.0/#"
},
"@type": "rdf:Statement",
"subject": "j:Charge",
"predicate": "structures:metadata",
"object": { "@id": "j:JusticeMetadata" },
"j:CriminalInformationIndicator": true
}
IEPD developers sometimes want to reuse schema components defined in
an existing standard via a schema that does not conform to the NDR.
The adapter elements defined in NDR section 10.2.3, “External
adapter types and external
components” are the NIEM
mechanism for including these external components in the IEPD. For
instance, in the following section of the sample IEP, the
geo:LocationGeospatialPoint
element is a NIEM-conforming
adapter. The external content of that adapter element (gml:Point
) is defined by the Open
Geospatial Consortium (OGC) in the Geographic Markup Language (GML).
<geo:LocationGeospatialPoint>
<gml:Point gml:id="PT01" srsName="urn:ogc:def:crs:EPSG::4326">
<gml:pos>51.835 -0.417</gml:pos>
</gml:Point>
</geo:LocationGeospatialPoint>
Because the external content of an adapter element does not follow the NDR, the guidance in this document may not apply. Developers must decide how to convert external content to JSON on a case-by-case basis, and must also decide which of the three consumer use cases (plain JSON, JSON-LD, RDF) they will support. For the adapter element in the sample IEP, the developer might apply any of the following solutions:
The developer could simply apply the guidance in this document as if the external content were NIEM conforming. In this case, the adapter element is converted to
"geo:LocationGeospatialPoint": {
"gml:Point": {
"@id": "PT01",
"srsName": "urn:ogc:def:crs:EPSG::4326",
"gml:pos": "51.835 -0.417"
}
}
That will work when processed as plain JSON. When processed as
JSON-LD, the resulting IRIs in the expanded form are
reasonable. However, because the srsName
attribute does not have a
namespace in GML, it will be dropped by the JSON-LD processor. That will
probably cause difficulties for the JSON-LD and RDF consumer use
cases.
The difficulty with the srsName
attribute could be resolved with a
custom mapping, one which extends the guidance in this document by
supplying a special @context
pair for the content of the adapter
element. The resulting JSON-LD would be
"geo:LocationGeospatialPoint": {
"@context": {
"srsName": "http://www.opengis.net/gml/3.2#srsName"
},
"gml:Point": {
"@id": "PT01",
"srsName": "urn:ogc:def:crs:EPSG::4326",
"gml:pos": "51.835 -0.417"
}
}
This approach produces a plausible IRI for the srsName
attribute in
the expanded JSON-LD, and so should work for the JSON-LD and RDF
consumer use cases. This is the approach followed for the full
example
GeoJSON is a geospatial data interchange format based on JSON. The Internet Engineering Task Force (IETF), in conjunction with the original specification authors, has formed the Geographic JSON WG to standardize the format. Although GeoJSON is not a specification of the OGC, it is still a plausible choice for encoding GML content in JSON. With this solution, the adapter element is converted to
"geo:LocationGeospatialPoint": {
"@context": {
"geometry": "https://datatracker.ietf.org/doc/draft-ietf-geojson/#geometry",
"type": "https://datatracker.ietf.org/doc/draft-ietf-geojson/#type",
"coordinates": "https://datatracker.ietf.org/doc/draft-ietf-geojson/#coordinates"
},
"geometry": {
"type": "Point",
"coordinates": [51.835, -0.417]
}
}
That will work when processed as plain JSON, ignoring the @context
pair. Defining the context as shown will produce plausible IRIs in the
expanded JSON-LD and converted RDF. A better base IRI would be
desirable, of course.
"geo:LocationGeospatialPoint": {
"@type": "rdf:XMLLiteral",
"@value":
"<gml:Point gml:id=\"PT01\"
srsName=\"urn:ogc:def:crs:EPSG::4326\">
<gml:pos>51.835 -0.417</gml:pos>
</gml:Point>"
}
TODO: Discuss an easy button transfrom from NIEM XML to JSON-LD, treating input like a canned query with very little optionality, transforming to JSON-LD using XSLT3’s JSON capability. —@webb
A software developer may wish to work with JSON-LD data instances with vanilla JSON tools, which aren’t JSON-LD aware. Although developers are encouraged to use JSON-LD tools, using vanilla JSON tools is straightforward, although there are caveats. These include:
Vanilla JSON processes that use JSON-LD are encouraged to carefully control the organization and JSON-LD context of the data. This may be done by using the expansion, compaction, and framing algorithms provided as part of the JSON-LD specification products.
In JSON and JSON-LD, the order of keys within an object are not considered significant. This means that the two following pieces of JSON-LD are equivalent:
{
"ns:key1": "value",
"ns:key2": "value"
}
is equivalent to:
{
"ns:key2": "value",
"ns:key1": "value"
}
The order of keys within a JSON-LD instance may be determined by the writer of the JSON-LD, or may be handled automatically by a JSON-LD library.
In JSON-LD, a single object is equivalent to an array that contains a single object. So, the two following pieces of JSON-LD are equivalent:
{
"ns:key": "value"
}
is equivalent to:
{
"ns:key" : [
"value"
]
}
A system that is generating JSON-LD could optionally generate the second form instead of the first.
The @type
keyword is used to associate a type with a node.
The concept of a node type and a value type are different. A node type specifies the type of
thing that is being described, like a Person, Location, or Event. A value type specifies the
data type of a particular value, such as an integer, a floating point number, or a date.
Using @type
keywords is optional. In general, the NIEM IEPD uses XML Schema to define node types
or to constrain value types so it would not be necessary for the JSON-LD to repeat all of that.
If you need to specify type information for handling the iep data correctly, you can add it where needed. This example specifies that the node type of Person in the iep is a NIEM PersonType and the value type of their PersonBirthDate is an xsd date type.
{
"@context": {
"nc": "http://release.niem.gov/niem/niem-core/3.0/#",
"xs": "http://www.w3.org/2001/XMLSchema#",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
},
"nc:Person": {
"@id": "P01",
"@type" : "nc:PersonType",
"nc:PersonBirthDate": {
"nc:Date": {
"rdf:value": {
"@value" : "1893-05-04",
"@type" : "xs:date"
}
}
}
}
}
Here is an example of a typed literal, identifying the type of the simple
content of nc:MeasureDecimalValue
as being type xs:decimal
:
{
"@context" : {
"nc": "http://release.niem.gov/niem/niem-core/3.0/#",
"xs": "http://www.w3.org/2001/XMLSchema#"
},
"nc:MeasureDecimalValue": {
"rdf:value": {
"@value": "9.7",
"@type" : "xs:decimal"
}
}
}
If you don’t specify the value type as xs:decimal, it is interpreted by JSON as being of type http://www.w3.org/2001/XMLSchema#double and the value becomes “9.699999999999999E0”.
See JSON-LD Section 6.4 Typed Values for more information on how to express typed values.
If you have existing JSON data that you want to expose as JSON-LD, you can
do that by supplying a separate JSON-LD context for it. This provides an
upgrade path for developers who need to be able to continue to support regular JSON.
You do this by adding a HTTP Link Header as specified by RFC5988
using the http://www.w3.org/ns/json-ld#context
link relation.
A separate context file could be served at URL http://example.com/contexts/iepd-context.jsonld
:
{
"@context": {
"nc": "http://release.niem.gov/niem/niem-core/3.0/#",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
...
"givenName" : "nc:PersonGivenName",
"additionalName" : "nc:PersonMiddleName",
"familyName" : "nc:PersonSurName",
"text" : "rdf:value"
}
}
A link header can be added to the plain JSON response that includes:
Link: <http://example.com/contexts/iepd-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"
The JSON-LD processor prepends the context to the JSON data and interprets the original plain JSON as JSON-LD. These definitions can then be used by a JSON data instance, without the instance explicitly referring to the context. Since the context defined the short terms as aliases to full NIEM terms, expanding this JSON data will convert it to use the full NIEM terms.
{
"givenName": { "text" : "Peter" },
"additionalName": [ { "text": "Death"},
{ "text" : "Bredon" } ],
"familyName": { "text" : "Wimsey" }
}
A benefit of separating the context from the JSON is that if you’re storing the JSON data in a database you can add new terms to the JSON-LD context without having to replace the inline context in all the data that has already been stored.
See JSON-LD Specification Section 6.8, “Interpreting JSON as JSON-LD” for more information and examples of how to implement this.
Describe approaches or tools for transforming.
Provide helper functions to check for repeatable elements.
The walkthrough of how to transform an XML instance document IEP into a JSON-LD data instance is demonstrated using the full example documents within this section. These examples were constructed to show many aspects and features of NIEM XML instance documents.
The following XML document is the XML form for the full example from Section 2, above.
<?xml version="1.0" encoding="UTF-8"?>
<exch:CrashDriverInfo
xmlns:exch="http://example.com/CrashDriver/1.0/"
xmlns:j="http://release.niem.gov/niem/domains/jxdm/5.1/"
xmlns:nc="http://release.niem.gov/niem/niem-core/3.0/"
xmlns:geo="http://release.niem.gov/niem/adapters/geospatial/3.0/"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:structures="http://release.niem.gov/niem/structures/3.0/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<nc:Person structures:id="P01">
<nc:PersonBirthDate>
<nc:Date>1893-05-04</nc:Date>
</nc:PersonBirthDate>
<nc:PersonName nc:personNameCommentText="copied">
<nc:PersonGivenName nc:sequenceID="1">Peter</nc:PersonGivenName>
<nc:PersonMiddleName nc:sequenceID="2">Death</nc:PersonMiddleName>
<nc:PersonMiddleName nc:sequenceID="3">Bredon</nc:PersonMiddleName>
<nc:PersonSurName>Wimsey</nc:PersonSurName>
</nc:PersonName>
<exch:PersonFictionalCharacterIndicator>true</exch:PersonFictionalCharacterIndicator>
</nc:Person>
<j:Crash>
<nc:IncidentLocation>
<geo:LocationGeospatialPoint>
<gml:Point gml:id="PT01" srsName="urn:ogc:def:crs:EPSG::4326">
<gml:pos>51.835 -0.417</gml:pos>
</gml:Point>
</geo:LocationGeospatialPoint>
</nc:IncidentLocation>
<j:CrashVehicle>
<j:CrashDriver>
<nc:RoleOfPerson structures:ref="P01" xsi:nil="true"/>
<j:DriverLicense>
<j:DriverLicenseCardIdentification>
<nc:IdentificationID>A1234567</nc:IdentificationID>
</j:DriverLicenseCardIdentification>
<exch:LicenseAugmentation>
<nc:ItemLengthMeasure>
<nc:MeasureDecimalValue>9.7</nc:MeasureDecimalValue>
<nc:LengthUnitCode>CMT</nc:LengthUnitCode>
</nc:ItemLengthMeasure>
</exch:LicenseAugmentation>
</j:DriverLicense>
</j:CrashDriver>
</j:CrashVehicle>
</j:Crash>
<j:PersonChargeAssociation>
<nc:Person structures:ref="P01" xsi:nil="true"/>
<j:Charge structures:ref="CH01" xsi:nil="true"/>
<j:JuvenileAsAdultIndicator>true</j:JuvenileAsAdultIndicator>
</j:PersonChargeAssociation>
<j:Charge structures:id="CH01" structures:metadata="MD01">
<j:ChargeDescriptionText>Wild Driving</j:ChargeDescriptionText>
<j:ChargeFelonyIndicator>false</j:ChargeFelonyIndicator>
</j:Charge>
<j:JusticeMetadata structures:id="MD01">
<j:CriminalInformationIndicator>true</j:CriminalInformationIndicator>
</j:JusticeMetadata>
</exch:CrashDriverInfo>
The following JSON data is a compact JSON-LD form of the full example from Section 2, above.
{
"@context": {
"exch": "http://example.com/CrashDriver/1.0/#",
"j": "http://release.niem.gov/niem/domains/jxdm/5.1/#",
"nc": "http://release.niem.gov/niem/niem-core/3.0/#",
"geo": "http://release.niem.gov/niem/adapters/geospatial/3.0/#",
"gml": "http://www.opengis.net/gml/3.2#",
"structures": "http://release.niem.gov/niem/structures/3.0/#",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
},
"exch:CrashDriverInfo": {
"nc:Person": {
"@id": "P01",
"nc:PersonBirthDate": {
"nc:Date": "1893-05-04"
},
"nc:PersonName": {
"nc:personNameCommentText": "copied",
"nc:PersonGivenName": {
"nc:sequenceID": 1,
"rdf:value": "Peter"
},
"nc:PersonMiddleName": [
{
"nc:sequenceID": 2,
"rdf:value": "Death"
},
{
"nc:sequenceID": 3,
"rdf:value": "Bredon"
}
],
"nc:PersonSurName": "Wimsey"
},
"exch:PersonFictionalCharacterIndicator": true
},
"j:Crash": {
"nc:IncidentLocation": {
"geo:LocationGeospatialPoint": {
"@context": {
"srsName": "http://www.opengis.net/gml/3.2#srsName"
},
"gml:Point": {
"@id": "PT01",
"srsName": "urn:ogc:def:crs:EPSG::4326",
"gml:pos": "51.835 -0.417"
}
}
},
"j:CrashVehicle": {
"j:CrashDriver": {
"nc:RoleOfPerson": {
"@id": "P01"
},
"j:DriverLicense": {
"j:DriverLicenseCardIdentification": {
"nc:IdentificationID": "A1234567"
},
"nc:ItemLengthMeasure": {
"nc:MeasureDecimalValue": 9.7
},
"nc:LengthUnitCode": "CMT"
}
}
}
},
"j:PersonChargeAssociation": {
"nc:Person": {
"@id": "P01"
},
"j:Charge": {
"@id": "CH01"
},
"j:JuvenileAsAdultIndicator": true
},
"j:Charge": {
"@id": "CH01",
"j:JusticeMetadata": {
"@id": "MD01",
"j:CriminalInformationIndicator": true
},
"j:ChargeDescriptionText": "Wild Driving",
"j:ChargeFelonyIndicator": false
}
}
}
The NIEM conceptual model is based on the RDF data model described in RDF-Concepts. NIEM defines a mapping from the XML components in IEPs and IEPD schemas to equivalent RDF triples. As of this writing, there is no automated translator for that mapping.
Another reason for choosing JSON-LD is that it is a concrete RDF syntax as described in RDF-Concepts. There is a mapping between JSON-LD objects and equivalent RDF tuples. This mapping is implemented in open-source translators. This means that the JSON-LD serialization of an IEP can be automatically translated to Turtle or RDF/XML and processed in that form.
This establishes two paths from a NIEM IEP to RDF
The NTAC intent is that the RDF created by both paths will be consistent. This may entail future revisions to the NDR.