Gregg Kellogg (v1.0 and v1.1) · w3.org

Abstract

This specification defines a set of algorithms for programmatic transformations of JSON-LD documents. Restructuring data according to the defined transformations often dramatically simplifies its usage. Furthermore, this document proposes an Application Programming Interface (API) for developers implementing the specified algorithms.

This specification describes a superset of the features defined in JSON-LD 1.0 Processing Algorithms And API [JSON-LD10-API] and, except where noted, the algorithms described in this specification are fully compatible with documents created using JSON-LD 1.0 [JSON-LD10].

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.

This document has been developed by the JSON-LD Working Group and was derived from the JSON-LD Community Group's Final Report.

There is a live JSON-LD playground that is capable of demonstrating the features described in this document.

This specification is intended to supersede the JSON-LD 1.0 Processing Algorithms And API [JSON-LD10-API] specification.

This document was published by the JSON-LD Working Group as a Recommendation.

GitHub Issues are preferred for discussion of this specification. Alternatively, you can send comments to our mailing list. Please send them to public-json-ld-wg@w3.org (archives).

Please see the Working Group's implementation report.

This document has been reviewed by W3C Members, by software developers, and by other W3C groups and interested parties, and is endorsed by the Director as a W3C Recommendation. It is a stable document and may be used as reference material or cited from another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its widespread deployment. This enhances the functionality and interoperability of the Web.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 1 March 2019 W3C Process Document.

Set of Documents

This document is one of three JSON-LD 1.1 Recommendations produced by the JSON-LD Working Group:

Table of Contents

  1. 1. Introduction
    1. 1.1 How to Read this Document
    2. 1.2 Contributing
    3. 1.3 Typographical conventions
    4. 1.4 Terminology
      1. 1.5 Example Conventions
    5. 2. Features
      1. 2.1 Expansion
      2. 2.2 Compaction
      3. 2.3 Flattening
      4. 2.4 RDF Serialization/Deserialization
    6. 3. Conformance
    7. 4. Context Processing Algorithms
      1. 4.1 Context Processing Algorithm
        1. 4.2 Create Term Definition
          1. 4.3 Inverse Context Creation
            1. 4.4 Term Selection
            2. 5. Expansion Algorithms
              1. 5.1 Expansion Algorithm
                1. 5.2 IRI Expansion
                  1. 5.3 Value Expansion
                  2. 6. Compaction Algorithms
                    1. 6.1 Compaction Algorithm
                      1. 6.2 IRI Compaction
                        1. 6.3 Value Compaction
                        2. 7. Flattening Algorithms
                          1. 7.1 Flattening Algorithm
                            1. 7.2 Node Map Generation
                              1. 7.3 Merge Node Maps
                              2. 7.4 Generate Blank Node Identifier
                              3. 8. RDF Serialization/Deserialization Algorithms
                                1. 8.1 Deserialize JSON-LD to RDF Algorithm
                                  1. 8.2 Object to RDF Conversion
                                    1. 8.3 List to RDF Conversion
                                      1. 8.4 Serialize RDF as JSON-LD Algorithm
                                        1. 8.5 RDF to Object Conversion
                                          1. 8.6 Data Round Tripping
                                        2. 9. The Application Programming Interface
                                          1. 9.1 The JsonLdProcessor Interface
                                          2. 9.2 RDF Dataset Interfaces
                                          3. 9.3 The JsonLdOptions Type
                                          4. 9.4 Remote Document and Context Retrieval
                                            1. 9.5 HTML Content Algorithms
                                              1. 9.6 Error Handling
                                              2. 10. Security Considerations
                                              3. 11. Privacy Considerations
                                              4. 12. Internationalization Considerations
                                              5. A. IDL Index
                                              6. B. Open Issues
                                              7. C. Changes since 1.0 Recommendation of 16 January 2014
                                              8. D. Changes since JSON-LD Community Group Final Report
                                              9. E. Changes since Candidate Release of 12 December 2019
                                              10. F. Changes since Candidate Release of 05 March 2020
                                              11. G. Changes since Proposed Recommendation Release of 7 May 2020
                                              12. H. Acknowledgements
                                              13. I. References
                                                1. I.1 Normative references
                                                2. I.2 Informative references

                                              1. Introduction

                                              This section is non-normative.

                                              This document is a detailed specification of the JSON-LD processing algorithms. The document is primarily intended for the following audiences:

                                              • Software developers who want to implement the algorithms to transform JSON-LD documents.
                                              • Web authors and developers who want a very detailed view of how a JSON-LD Processor operates.
                                              • Developers who want an overview of the proposed JSON-LD API.

                                              To understand the basics in this specification you must first be familiar with JSON, which is detailed in [RFC8259]. You must also understand the JSON-LD syntax defined in the JSON-LD 1.1 Syntax specification [JSON-LD11], which is the base syntax used by all of the algorithms in this document. To understand the API and how it is intended to operate in a programming environment, it is useful to have working knowledge of the JavaScript programming language [ECMASCRIPT] and WebIDL [WEBIDL]. To understand how JSON-LD maps to RDF, it is helpful to be familiar with the basic RDF concepts [RDF11-CONCEPTS].

                                              1.1 How to Read this Document

                                              This section is non-normative.

                                              This document is a detailed specification for a serialization of Linked Data in JSON. The document is primarily intended for the following audiences:

                                              • Software developers who want to implement processors and APIs for JSON-LD

                                              A companion document, the JSON-LD 1.1 specification [JSON-LD11], specifies the grammar of JSON-LD documents.

                                              To understand the basics in this specification you must first be familiar with JSON, which is detailed in [RFC8259].

                                              This document can highlight changes since the JSON-LD 1.0 version. Select to changes.

                                              1.2 Contributing

                                              This section is non-normative.

                                              There are a number of ways that one may participate in the development of this specification:

                                              • Technical discussion typically occurs on the public mailing list: public-json-ld-wg@w3.org
                                              • The working group uses #json-ld IRC channel is available for real-time discussion on irc.w3.org.
                                              • The #json-ld IRC channel is also available for real-time discussion on irc.freenode.net.

                                              1.3 Typographical conventions

                                              This section is non-normative.

                                              The following typographic conventions are used in this specification:

                                              markup
                                              Markup (elements, attributes, properties), machine processable values (string, characters, media types), property name, or a file name is in red-orange monospace font.
                                              variable
                                              A variable in pseudo-code or in an algorithm description is in italics.
                                              definition
                                              A definition of a term, to be used elsewhere in this or other specifications, is in bold and italics.
                                              definition reference
                                              A reference to a definition in this document is underlined and is also an active link to the definition itself.
                                              markup definition reference
                                              A references to a definition in this document, when the reference itself is also a markup, is underlined, red-orange monospace font, and is also an active link to the definition itself.
                                              external definition reference
                                              A reference to a definition in another document is underlined, in italics, and is also an active link to the definition itself.
                                              markup external definition reference
                                              A reference to a definition in another document, when the reference itself is also a markup, is underlined, in italics red-orange monospace font, and is also an active link to the definition itself.
                                              hyperlink
                                              A hyperlink is underlined and in blue.
                                              [reference]
                                              A document reference (normative or informative) is enclosed in square brackets and links to the references section.
                                              Changes from Recommendation
                                              Sections or phrases changed from the previous Recommendation may be highlighted using a control in §  1.1 How to Read this Document.

                                              Note

                                              Notes are in light green boxes with a green left border and with a "Note" header in green. Notes are always informative.

                                              Example 1

                                              Examples are in light khaki boxes, with khaki left border,
                                              and with a numbered "Example" header in khaki.
                                              Examples are always informative. The content of the example is in monospace font and may be syntax colored.
                                              Examples may have tabbed navigation buttons
                                              to show the results of transforming an example into other representations.

                                              1.4 Terminology

                                              This document uses the following terms as defined in external specifications and defines terms specific to JSON-LD.

                                              Terms imported from Other Specifications

                                              Terms imported from ECMAScript Language Specification [ECMASCRIPT], The JavaScript Object Notation (JSON) Data Interchange Format [RFC8259], Infra Standard [INFRA], and Web IDL [WEBIDL]

                                              array
                                              In the JSON serialization, an array structure is represented as square brackets surrounding zero or more values. Values are separated by commas. In the internal representation, a list (also called an array) is an ordered collection of zero or more values. While JSON-LD uses the same array representation as JSON, the collection is unordered by default. While order is preserved in regular JSON arrays, it is not in regular JSON-LD arrays unless specifically defined (see the Sets and Lists section of JSON-LD 1.1.
                                              boolean
                                              The values true and false that are used to express one of two possible states.
                                              JSON object
                                              In the JSON serialization, an object structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members). A name is a string. A single colon comes after each name, separating the name from the value. A single comma separates a value from a following name. In JSON-LD the names in an object must be unique.

                                              In the internal representation a JSON object is described as a map (see [INFRA]), composed of entries with key/value pairs.

                                              In the Application Programming Interface, a map is described using a [WEBIDL] record.

                                              null
                                              The use of the null value within JSON-LD is used to ignore or reset values. A map entry in the @context where the value, or the @id of the value, is null, explicitly decouples a term's association with an IRI. A map entry in the body of a JSON-LD document whose value is null has the same meaning as if the map entry was not defined. If @value, @list, or @set is set to null in expanded form, then the entire JSON object is ignored.
                                              number
                                              In the JSON serialization, a number is similar to that used in most programming languages, except that the octal and hexadecimal formats are not used and that leading zeros are not allowed. In the internal representation, a number is equivalent to either a long or double , depending on if the number has a non-zero fractional part (see [WEBIDL]).
                                              scalar
                                              A scalar is either a string, number, true, or false.
                                              string
                                              A string is a sequence of zero or more Unicode (UTF-8) characters, wrapped in double quotes, using backslash escapes (if necessary). A character is represented as a single character string.

                                              Terms imported from Internationalized Resource Identifiers (IRIs) [RFC3987]

                                              IRI
                                              The absolute form of an IRI containing a scheme along with a path and optional query and fragment segments.
                                              IRI reference
                                              Denotes the common usage of an Internationalized Resource Identifier. An IRI reference may be absolute or relative. However, the "IRI" that results from such a reference only includes absolute IRIs; any relative IRI references are resolved to their absolute form.
                                              relative IRI reference
                                              A relative IRI reference is an IRI reference that is relative to some other IRI, typically the base IRI of the document. Note that properties, values of @type, and values of terms defined to be vocabulary relative are resolved relative to the vocabulary mapping, not the base IRI.

                                              Terms imported from RDF 1.1 Concepts and Abstract Syntax [RDF11-CONCEPTS], RDF Schema 1.1 [RDF-SCHEMA], and Linked Data Design Issues [LINKED-DATA]

                                              base IRI
                                              The base IRI is an IRI established in the context, or is based on the JSON-LD document location. The base IRI is used to turn relative IRI references into IRIs.
                                              blank node
                                              A node in a graph that is neither an IRI, nor a literal. A blank node does not contain a de-referenceable identifier because it is either ephemeral in nature or does not contain information that needs to be linked to from outside of the linked data graph. In JSON-LD, a blank node is assigned an identifier starting with the prefix _:.
                                              blank node identifier
                                              A blank node identifier is a string that can be used as an identifier for a blank node within the scope of a JSON-LD document. Blank node identifiers begin with _:.
                                              dataset
                                              A dataset representing a collection of RDF graphs including exactly one default graph and zero or more named graphs.
                                              datatype IRI
                                              A datatype IRI is an IRI identifying a datatype that determines how the lexical form maps to a literal value.
                                              default graph
                                              The default graph of a dataset is an RDF graph having no name, which may be empty.
                                              graph name
                                              The IRI or blank node identifying a named graph.
                                              language-tagged string
                                              A language-tagged string consists of a string and a non-empty language tag as defined by [BCP47]. The language tag must be well-formed according to section 2.2.9 Classes of Conformance of [BCP47]. Processors may normalize language tags to lowercase.
                                              Linked Data
                                              A set of documents, each containing a representation of a linked data graph or dataset.
                                              list
                                              A list is an ordered sequence of IRIs, blank nodes, and literals.
                                              literal
                                              An object expressed as a value such as a string or number. Implicitly or explicitly includes a datatype IRI and, if the datatype is rdf:langString, an optional language tag.
                                              named graph
                                              A named graph is a linked data graph that is identified by an IRI or blank node.
                                              node
                                              A node in an RDF graph, either the subject and object of at least one triple. Note that a node can play both roles (subject and object) in a graph, even in the same triple.
                                              object
                                              An object is a node in a linked data graph with at least one incoming edge.
                                              property
                                              The name of a directed-arc in a linked data graph. Every property is directional and is labeled with an IRI or a blank node identifier. Whenever possible, a property should be labeled with an IRI.

                                              Note

                                              The use of blank node identifiers to label properties is obsolete, and may be removed in a future version of JSON-LD.

                                              Also, see predicate in [RDF11-CONCEPTS].
                                              RDF graph
                                              A labeled directed graph, i.e., a set of nodes connected by directed-arcs. Also called linked data graph.
                                              resource
                                              A resource denoted by an IRI, a blank node or literal representing something in the world (the "universe of discourse").
                                              subject
                                              A subject is a node in a linked data graph with at least one outgoing edge, related to an object node through a property.
                                              triple
                                              A component of an RDF graph including a subject, predicate, and object, which represents a node-arc-node segment of an RDF graph.

                                              JSON-LD Specific Term Definitions

                                              active context
                                              A context that is used to resolve terms while the processing algorithm is running.
                                              base direction
                                              The base direction is the direction used when a string does not have a direction associated with it directly. It can be set in the context using the @direction key whose value must be one of the strings "ltr", "rtl", or null. See the Context Definitions section of JSON-LD 1.1 for a normative description.
                                              compact IRI
                                              A compact IRI has the form of prefix:suffix and is used as a way of expressing an IRI without needing to define separate term definitions for each IRI contained within a common vocabulary identified by prefix.
                                              context
                                              A set of rules for interpreting a JSON-LD document as described in the The Context section of JSON-LD 1.1, and normatively specified in the Context Definitions section of JSON-LD 1.1.
                                              default language
                                              The default language is the language used when a string does not have a language associated with it directly. It can be set in the context using the @language key whose value must be a string representing a [BCP47] language code or null. See the Context Definitions section of JSON-LD 1.1 for a normative description.
                                              default object
                                              A default object is a map that has a @default key.
                                              expanded term definition
                                              An expanded term definition is a term definition where the value is a map containing one or more keyword keys to define the associated IRI, if this is a reverse property, the type associated with string values, and a container mapping. See the Expanded Term Definition section of JSON-LD 1.1 for a normative description.
                                              frame
                                              A JSON-LD document, which describes the form for transforming another JSON-LD document using matching and embedding rules. A frame document allows additional keywords and certain map entries to describe the matching and transforming process.
                                              graph object
                                              A graph object represents a named graph as the value of a map entry within a node object. When expanded, a graph object must have an @graph entry, and may also have @id, and @index entries. A simple graph object is a graph object which does not have an @id entry. Note that node objects may have a @graph entry, but are not considered graph objects if they include any other entries. A top-level object consisting of @graph is also not a graph object. Note that a node object may also represent a named graph it it includes other properties. See the Graph Objects section of JSON-LD 1.1 for a normative description.
                                              id map
                                              An id map is a map value of a term defined with @container set to @id. The values of the id map must be node objects, and its keys are interpreted as IRIs representing the @id of the associated node object. If a value in the id map contains a key expanding to @id, its value must be equivalent to the referencing key in the id map. See the Id Maps section of JSON-LD 1.1 for a normative description.
                                              included block
                                              An included block is an entry in a node object where the key is either @included or an alias of @included and the value is one or more node objects. See the Included Blocks section of JSON-LD 1.1 for a normative description.
                                              index map
                                              An index map is a map value of a term defined with @container set to @index, whose values must be any of the following types: string, number, true, false, null, node object, value object, list object, set object, or an array of zero or more of the above possibilities. See the Index Maps section in JSON-LD 1.1 for a formal description.
                                              JSON literal
                                              A JSON literal is a literal where the associated datatype IRI is rdf:JSON. In the value object representation, the value of @type is @json. JSON literals represent values which are valid JSON [RFC8259]. See the The rdf:JSON Datatype section in JSON-LD 1.1 for a normative description.
                                              JSON-LD document
                                              A JSON-LD document is a serialization of an RDF dataset. See the JSON-LD Grammar section in JSON-LD 1.1 for a formal description.
                                              JSON-LD internal representation
                                              The JSON-LD internal representation is the result of transforming a JSON syntactic structure into the core data structures suitable for direct processing: arrays, maps, strings, numbers, booleans, and null.
                                              JSON-LD Processor
                                              A JSON-LD Processor is a system which can perform the algorithms defined in JSON-LD 1.1 Processing Algorithms and API. See the Conformance section in JSON-LD 1.1 API for a formal description.
                                              JSON-LD value
                                              A JSON-LD value is a string, a number, true or false, a typed value, or a language-tagged string. It represents an RDF literal.
                                              keyword
                                              A string that is specific to JSON-LD, described in the Syntax Tokens and Keywords section of JSON-LD 1.1, and normatively specified in the Keywords section of JSON-LD 1.1,
                                              language map
                                              An language map is a map value of a term defined with @container set to @language, whose keys must be strings representing [BCP47] language codes and the values must be any of the following types: null, string, or an array of zero or more of the above possibilities. See the Language Maps section of JSON-LD 1.1 for a normative description.
                                              list object
                                              A list object is a map that has a @list key. It may also have an @index key, but no other entries. See the Lists and Sets section of JSON-LD 1.1 for a normative description.
                                              local context
                                              A context that is specified with a map, specified via the @context keyword.
                                              node object
                                              A node object represents zero or more properties of a node in the graph serialized by the JSON-LD document. A map is a node object if it exists outside of the JSON-LD context and:
                                              • it does not contain the @value, @list, or @set keywords, or
                                              • it is not the top-most map in the JSON-LD document consisting of no other entries than @graph and @context.
                                              The entries of a node object whose keys are not keywords are also called properties of the node object. See the Node Objects section of JSON-LD 1.1 for a normative description.
                                              prefix
                                              A prefix is the first component of a compact IRI which comes from a term that maps to a string that, when prepended to the suffix of the compact IRI, results in an IRI.
                                              processing mode
                                              The processing mode defines how a JSON-LD document is processed. By default, all documents are assumed to be conformant with this specification. By defining a different version using the @version entry in a context, publishers can ensure that processors conformant with JSON-LD 1.0 [JSON-LD10] will not accidentally process JSON-LD 1.1 documents, possibly creating a different output. The API provides an option for setting the processing mode to json-ld-1.0, which will prevent JSON-LD 1.1 features from being activated, or error if @version entry in a context is explicitly set to 1.1. This specification extends JSON-LD 1.0 via the json-ld-1.1 processing mode.
                                              scoped context
                                              A scoped context is part of an expanded term definition using the @context entry. It has the same form as an embedded context. When the term is used as a type, it defines a type-scoped context , when used as a property it defines a property-scoped context .
                                              set object
                                              A set object is a map that has an @set entry. It may also have an @index key, but no other entries. See the Lists and Sets section of JSON-LD 1.1 for a normative description.
                                              term
                                              A term is a short word defined in a context that may be expanded to an IRI. See the Terms section of JSON-LD 1.1 for a normative description.
                                              term definition
                                              A term definition is an entry in a context, where the key defines a term which may be used within a map as a key, type, or elsewhere that a string is interpreted as a vocabulary item. Its value is either a string ( simple term definition ), expanding to an IRI, or a map (expanded term definition).
                                              type map
                                              A type map is a map value of a term defined with @container set to @type, whose keys are interpreted as IRIs representing the @type of the associated node object; the value must be a node object, or array of node objects. If the value contains a term expanding to @type, its values are merged with the map value when expanding. See the Type Maps section of JSON-LD 1.1 for a normative description.
                                              typed value
                                              A typed value consists of a value, which is a string, and a type, which is an IRI.
                                              value object
                                              A value object is a map that has an @value entry. See the Value Objects section of JSON-LD 1.1 for a normative description.
                                              vocabulary mapping
                                              The vocabulary mapping is set in the context using the @vocab key whose value must be an IRI, a compact IRI, a term, or null. See the Context Definitions section of JSON-LD 1.1 for a normative description.

                                              1.4.1 Algorithm Terms

                                              The Following terms are used within specific algorithms.

                                              active graph
                                              The name of the currently active graph that the processor should use when processing.
                                              active property
                                              The currently active property or keyword that the processor should use when processing. The active property is represented in the original lexical form, which is used for finding coercion mappings in the active context.
                                              add value
                                              Used as a macro within various algorithms as a way to add a value to an entry in a map (object) using a specified key. The invocation may include an as array flag defaulting to false.
                                              1. If as array is true and the value of key in object does not exist or is not an array, set it to a new array containing any original value.
                                              2. If value is an array, then for each element v in value, use add value recursively to add v to key in entry.
                                              3. Otherwise:
                                                1. If key is not an entry in object, add value as the value of key in object.
                                                2. Otherwise
                                                  1. If the value of the key entry in object is not an array, set it to a new array containing the original value.
                                                  2. Append value to the value of the key entry in object.
                                              IRI compacting
                                              Used as a macro within various algorithms as to reduce the language used to describe the process of compacting a string var representing an IRI or keyword using an active context either specified directly, or coming from the scope of the algorithm step using this term. An optional value is used, if explicitly provided. Unless specified, the vocab flag defaults to true, and the reverse flag defaults to false.
                                              1. Return the result of using the IRI Compaction algorithm, passing active context, var, value (if supplied), vocab, and result.
                                              IRI expanding
                                              Used as a macro within various algorithms as to reduce the language used to describe the process of expanding a string value representing an IRI or keyword using an active context either specified directly, or coming from the scope of the algorithm step using this term. Optional defined and local context arguments are used, if explicitly provided. Unless specified, the document relative flag defaults to false, and the vocab flag defaults to true.
                                              1. Return the result of using the IRI Expansion algorithm, passing active context, value, local context (if supplied), defined (if supplied), document relative, and vocab.
                                              JSON-LD input
                                              The JSON-LD data structure that is provided as input to the algorithm.

                                              1.4.2 Syntax Tokens and Keywords

                                              In addition to the keywords defined in the JSON-LD 1.1 Syntax specification [JSON-LD11], this specification adds an additional keyword to support JSON-LD 1.1 Framing [JSON-LD11-FRAMING]:

                                              @preserve
                                              Used in an expanded document created as the result of the Framing algorithm to represent values that might otherwise be removed as part of the Expansion algorithm.

                                              1.5 Example Conventions

                                              This section is non-normative.

                                              Note that in the examples used in this document, output is of necessity shown in serialized form as JSON. While the algorithms describe operations on the JSON-LD internal representation, when they as displayed as examples, the JSON serialization is used. In particular, the internal representation use of maps are represented using JSON objects.

                                              Example 2

                                              : Sample JSON-LD document

                                              {
                                                "@context": {
                                                  "name": "http://xmlns.com/foaf/0.1/name",
                                                  "knows": "http://xmlns.com/foaf/0.1/knows"
                                                },
                                                "@id": "http://me.markus-lanthaler.com/",
                                                "name": "Markus Lanthaler",
                                                "knows": [
                                                  {
                                                    "name": "Dave Longley"
                                                  }
                                                ]
                                              }

                                              In the internal representation, the example above would be of a map containing @context, @id, name, and knows entries, with either maps, strings, or arrays of maps or strings values. In the JSON serialization, JSON objects are used for maps, while arrays and strings are serialized using a convention common to many programming languages.

                                              2. Features

                                              This section is non-normative.

                                              The JSON-LD 1.1 Syntax specification [JSON-LD11] defines a syntax to express Linked Data in JSON. Because there is more than one way to express Linked Data using this syntax, it is often useful to be able to transform JSON-LD documents so that they may be more easily consumed by specific applications.

                                              To allow these algorithms to be adapted for syntaxes other than JSON, the algorithms operate on the JSON-LD internal representation, which uses the generic concepts of arrays, maps, strings, numbers, booleans, and null to describe the data represented by a JSON document. Algorithms act on this internal representation with API entry points responsible for transforming between the concrete and internal representations.

                                              JSON-LD uses contexts to allow Linked Data to be expressed in a way that is specifically tailored to a particular person or application. By providing a context, JSON data can be expressed in a way that is a natural fit for a particular person or application whilst also indicating how the data should be understood at a global scale. In order for people or applications to share data that was created using a context that is different from their own, a JSON-LD processor must be able to transform a document from one context to another. Instead of requiring JSON-LD processors to write specific code for every imaginable context switching scenario, it is much easier to specify a single algorithm that can remove any context. Similarly, another algorithm can be specified to subsequently apply any context. These two algorithms represent the most basic transformations of JSON-LD documents. They are referred to as expansion and compaction, respectively.

                                              JSON-LD 1.1 introduces new features that are compatible with JSON-LD 1.0 [JSON-LD10], but if processed by a JSON-LD 1.0 processor may produce different results. Processors default to json-ld-1.1, unless the processingMode API option is explicitly set to json-ld-1.0. Publishers are encouraged to use the @version map entry within a context set to 1.1 to ensure that JSON-LD 1.0 processors will not misinterpret JSON-LD 1.1 features.

                                              There are four major types of transformation that are discussed in this document: expansion, compaction, flattening, and RDF serialization/deserialization.

                                              2.1 Expansion

                                              This section is non-normative.

                                              The algorithm that removes context is called expansion . Before performing any other transformations on a JSON-LD document, it is easiest to remove any context from it and to make data structures more regular.

                                              To get an idea of how context and data structuring affects the same data, here is an example of JSON-LD that uses only terms and is fairly compact:

                                              The next input example uses one IRI to express a property and a map to encapsulate a value, but leaves the rest of the information untouched.

                                              Note that both inputs are valid JSON-LD and both represent the same information. The difference is in their context information and in the data structures used. A JSON-LD processor can remove context and ensure that the data is more regular by employing expansion.

                                              Expansion has two important goals: removing any contextual information from the document, and ensuring all values are represented in a regular form. These goals are accomplished by expanding all entry keys to IRIs and by expressing all values in arrays in expanded form. Expanded form is the most verbose and regular way of expressing of values in JSON-LD; all contextual information from the document is instead stored locally with each value. Running the Expansion algorithm (expand()) operation) against the above examples results in the following output:

                                              Example 5

                                              : Expanded JSON-LD document using an IRI

                                              [
                                                {
                                                  "@id": "http://me.markus-lanthaler.com/",
                                                  "http://xmlns.com/foaf/0.1/name": [
                                                    { "@value": "Markus Lanthaler" }
                                                  ],
                                                  "http://xmlns.com/foaf/0.1/homepage": [
                                                    { "@id": "http://www.markus-lanthaler.com/" }
                                                  ]
                                                }
                                              ]

                                              The example above is the JSON-LD serialization of the output of the expansion algorithm, where the algorithm's use of maps are replaced with JSON objects.

                                              Note that in the output above all context definitions have been removed, all terms and compact IRIs have been expanded to absolute IRIs, and all JSON-LD values are expressed in arrays in expanded form. While the output is more verbose and difficult for a human to read, it establishes a baseline that makes JSON-LD processing easier because of its very regular structure.

                                              2.2 Compaction

                                              This section is non-normative.

                                              While expansion removes context from a given input, compaction 's primary function is to perform the opposite operation: to express a given input according to a particular context. Compaction applies a context that specifically tailors the way information is expressed for a particular person or application. This simplifies applications that consume JSON or JSON-LD by expressing the data in application-specific terms, and it makes the data easier to read by humans.

                                              Compaction uses a developer-supplied context to shorten IRIs to terms or compact IRIs and JSON-LD values expressed in expanded form to simple values such as strings or numbers.

                                              For example, assume the following expanded JSON-LD input document:

                                              Example 6

                                              : Expanded sample document

                                              [
                                                {
                                                  "@id": "http://me.markus-lanthaler.com/",
                                                  "http://xmlns.com/foaf/0.1/name": [
                                                    { "@value": "Markus Lanthaler" }
                                                  ],
                                                  "http://xmlns.com/foaf/0.1/homepage": [
                                                    { "@id": "http://www.markus-lanthaler.com/" }
                                                  ]
                                                }
                                              ]

                                              Additionally, assume the following developer-supplied JSON-LD context:

                                              Example 7

                                              : JSON-LD context

                                              {
                                                "@context": {
                                                  "name": "http://xmlns.com/foaf/0.1/name",
                                                  "homepage": {
                                                    "@id": "http://xmlns.com/foaf/0.1/homepage",
                                                    "@type": "@id"
                                                  }
                                                }
                                              }

                                              Running the Compaction Algorithm (compact()) operation) given the context supplied above against the JSON-LD input document provided above would result in the following output:

                                              The example above is the JSON-LD serialization of the output of the compaction algorithm, where the algorithm's use of maps are replaced with JSON objects.

                                              Note that all IRIs have been compacted to terms as specified in the context, which has been injected into the output. While compacted output is useful to humans, it is also used to generate structures that are easy to program against. Compaction enables developers to map any expanded document into an application-specific compacted document. While the context provided above mapped http://xmlns.com/foaf/0.1/name to name, it could also have been mapped to any other term provided by the developer.

                                              2.3 Flattening

                                              This section is non-normative.

                                              While expansion ensures that a document is in a uniform structure, flattening goes a step further to ensure that the shape of the data is deterministic. In expanded documents, the properties of a single node may be spread across a number of different node objects. By flattening a document, all properties of a node are collected in a single node object and all blank nodes are labeled with a blank node identifier. This may drastically simplify the code required to process JSON-LD data in certain applications.

                                              For example, assume the following JSON-LD input document:

                                              Example 9

                                              : JSON-LD document in compact form

                                              {
                                                "@context": {
                                                  "name": "http://xmlns.com/foaf/0.1/name",
                                                  "knows": "http://xmlns.com/foaf/0.1/knows"
                                                },
                                                "@id": "http://me.markus-lanthaler.com/",
                                                "name": "Markus Lanthaler",
                                                "knows": [
                                                  {"name": "Dave Longley"}
                                                ]
                                              }

                                              Running the Flattening Algorithm (flatten()) operation) with a context set to null to prevent compaction returns the following document:

                                              The example above is the JSON-LD serialization of the output of the flattening algorithm, where the algorithm's use of maps are replaced with JSON objects.

                                              Note how in the output above all properties of a node are collected in a single node object and how the blank node representing "Dave Longley" has been assigned the blank node identifier _:b0.

                                              To make it easier for humans to read or for certain applications to process it, a flattened document can be compacted by passing a context. Using the same context as the input document, the flattened and compacted document looks as follows:

                                              Please note that the result of flattening and compacting a document is always a map, (represented as a JSON object when serialized), which contains an @graph entry that represents the default graph.

                                              2.4 RDF Serialization/Deserialization

                                              This section is non-normative.

                                              JSON-LD can be used to serialize RDF data as described in [RDF11-CONCEPTS]. This ensures that data can be round-tripped to and from any RDF syntax without any loss in fidelity.

                                              For example, assume the following RDF input serialized in Turtle [TURTLE]:

                                              Example 12

                                              : Sample Turtle document

                                              @prefix foaf: <http://xmlns.com/foaf/0.1/> .
                                              <http://me.markus-lanthaler.com/>
                                                foaf:name "Markus Lanthaler" ;
                                                foaf:homepage <http://www.markus-lanthaler.com/> .

                                              Using the Serialize RDF as JSON-LD Algorithm a developer could transform this document into expanded JSON-LD:

                                              Example 13

                                              : Sample Turtle document converted to JSON-LD

                                              [
                                                {
                                                  "@id": "http://me.markus-lanthaler.com/",
                                                  "http://xmlns.com/foaf/0.1/name": [
                                                    { "@value": "Markus Lanthaler" }
                                                  ],
                                                  "http://xmlns.com/foaf/0.1/homepage": [
                                                    { "@id": "http://www.markus-lanthaler.com/" }
                                                  ]
                                                }
                                              ]

                                              The example above is the JSON-LD serialization of the output of the Serialize RDF as JSON-LD Algorithm, where the algorithm's use of maps are replaced with JSON objects.

                                              Note that the output above could easily be compacted using the technique outlined in the previous section. It is also possible to deserialize the JSON-LD document back to RDF using the Deserialize JSON-LD to RDF Algorithm.

                                              3. Conformance

                                              As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

                                              The key words MAY, MUST, MUST NOT, and SHOULD in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

                                              There are two classes of products that can claim conformance to this specification: JSON-LD Processors, and RDF Serializers/Deserializers.

                                              A conforming JSON-LD Processor is a system which can perform the Expansion, Compaction, and Flattening operations in a manner consistent with the algorithms defined in this specification.

                                              JSON-LD Processors MUST NOT attempt to correct malformed IRIs or language tags; however, they SHOULD issue validation warnings. IRIs are not modified other than conversion between relative and absolute IRIs.

                                              A conforming RDF Serializer/Deserializer is a system that can deserialize JSON-LD to RDF and serialize RDF as JSON-LD as defined in this specification.

                                              Unless specified using processingMode API option, the processing mode is set using the @version entry in a local context and affects the behavior of algorithms including expansion and compaction. Once set, it is an error to attempt to change to a different processing mode, and processors MUST generate, a processing mode conflict error and abort further processing.

                                              The algorithms in this specification are generally written with more concern for clarity than efficiency. Thus, JSON-LD Processors may implement the algorithms given in this specification in any way desired, so long as the end result is indistinguishable from the result that would be obtained by the specification's algorithms.

                                              In algorithm steps that describe operations on keywords, those steps also apply to keyword aliases.

                                              Note

                                              Implementers can partially check their level of conformance to this specification by successfully passing the test cases of the JSON-LD test suite. Note, however, that passing all the tests in the test suite does not imply complete conformance to this specification. It only implies that the implementation conforms to aspects tested by the test suite.

                                              This specification makes use of the following namespace prefixes:

                                              Prefix IRI
                                              rdf http://www.w3.org/1999/02/22-rdf-syntax-ns#
                                              xsd http://www.w3.org/2001/XMLSchema#

                                              4. Context Processing Algorithms

                                              The following sections describe algorithms for processing a JSON-LD context.

                                              4.1 Context Processing Algorithm

                                              When processing a JSON-LD data structure, each processing rule is applied using information provided by the active context. This section describes how to produce an active context.

                                              The active context consists of:

                                              Each term definition consists of:

                                              • an IRI mapping (IRI),
                                              • a prefix flag (boolean),
                                              • a protected flag (boolean),
                                              • a reverse property flag (boolean),
                                              • an optional base URL (IRI),
                                              • an optional context (context),
                                              • an optional container mapping (array of strings),
                                              • an optional direction mapping ("ltr" or "rtl"),
                                              • an optional index mapping (string),
                                              • an optional language mapping (string),
                                              • an optional nest value (string),
                                              • and an optional type mapping (IRI).

                                              A term definition can not only be used to map a term to an IRI, but also to map a term to a keyword, in which case it is referred to as a keyword alias .

                                              When processing, active context is initialized with a null inverse context, without any term definitions, vocabulary mapping, default base direction, or default language. If a local context is encountered during processing, a new active context is created by cloning the existing active context. Then the information from the local context is merged into the new active context. Given that local contexts may contain references to remote contexts, this includes their retrieval.

                                              4.1.1 Overview

                                              This section is non-normative.

                                              First we prepare a new active context result by cloning the current active context. Then we normalize the form of the original local context to an array. Local contexts may be in the form of a map, a string, or an array containing a combination of the two. Finally we process each context contained in the local context array as follows.

                                              If context is a string, it represents a reference to a remote context. We dereference the remote context and replace context with the value of the @context entry of the top-level object in the retrieved JSON-LD document. If there's no such entry, an invalid remote context has been detected. Otherwise, we process context by recursively using this algorithm ensuring that there is no cyclical reference.

                                              If context is a map, it is a context definition. We first update the base IRI, the default base direction, the default language, context propagation, the processing mode, and the vocabulary mapping by processing six specific keywords: @base, @direction, @language, @propagate, @version, and @vocab. These are handled before any other entries in the local context because they affect how the other entries are processed. If context contains @import, it is retrieved and is reverse-merged into the containing context, allowing JSON-LD 1.0 contexts to be upgraded to JSON-LD 1.1. Please note that @base is ignored when processing remote contexts.

                                              If context is not to be propagated, a reference to the previous context is retained so that it may be rolled back when a new node object is entered. By default, all contexts are propagated, other than type-scoped contexts.

                                              When an active context is initialized, the value of the original base URL is initialized from the original documentUrl of the document containing the initial context, if available, otherwise from the base API option. This is necessary when resetting the active context by setting it to null to retain the original default base IRI.

                                              When initialized, or when any entry of an active context is changed, or any associated term definition is added, changed, or removed, the inverse context field in active context is set to null.

                                              Then, for every other entry in local context, we update the term definition in result. Since term definitions in a local context may themselves contain terms or compact IRIs, we may need to recurse. When doing so, we must ensure that there is no cyclical dependency, which is an error. After we have processed any term definition dependencies, we update the current term definition, which may be a keyword alias.

                                              Finally, we return result as the new active context.

                                              4.1.2 Algorithm

                                              This algorithm specifies how a new active context is updated with a local context. The algorithm takes three required and four optional input variables. The required inputs are an active context, a local context, and a base URL used when resolving relative context URLs. The optional inputs are an array remote contexts, defaulting to a new empty array, which is used to detect cyclical context inclusions, override protected, defaulting to false, which is used to allow changes to protected terms, propagate, defaulting to true to mark term definitions associated with non-propagated contexts, and validate scoped context defaulting to true, which is used to limit recursion when validating possibly recursive scoped contexts..

                                              1. Initialize result to the result of cloning active context, with inverse context set to null..
                                              2. If local context is an object containing the member @propagate, its value MUST be boolean true or false, set propagate to that value.

                                                Note

                                                Error handling is performed in step 5.11.

                                              3. If propagate is false, and result does not have a previous context, set previous context in result to active context.
                                              4. If local context is not an array, set local context to an array containing only local context.
                                              5. For each item context in local context:
                                                1. If context is null:
                                                  1. If override protected is false and active context contains any protected term definitions, an invalid context nullification has been detected and processing is aborted.
                                                  2. Initialize result as a newly-initialized active context, setting both base IRI and original base URL to the value of original base URL in active context, and, if propagate is false, previous context in result to the previous value of result.
                                                  3. Continue with the next context.
                                                2. If context is a string,
                                                  1. Initialize context to the result of resolving context against base URL. If base URL is not a valid IRI, then context MUST be a valid IRI, otherwise a loading document failed error has been detected and processing is aborted.

                                                    Note

                                                    base URL is often not the same as base or the base IRI of the active context.

                                                  2. If validate scoped context is false, and remote contexts already includes context do not process context further and continue to any next context in local context.
                                                  3. If the number of entries in the remote contexts array exceeds a processor defined limit, a context overflow error has been detected and processing is aborted; otherwise, add context to remote contexts.
                                                  4. If context was previously dereferenced, then the processor MUST NOT do a further dereference, and context is set to the previously established internal representation: set context document to the previously dereferenced document, and set loaded context to the value of the @context entry from the document in context document.

                                                    Note

                                                    Only the @context entry need be retained.

                                                  5. Otherwise, set context document to the RemoteDocument obtained by dereferencing context using the LoadDocumentCallback, passing context for url, and http://www.w3.org/ns/json-ld#context for profile and for requestProfile.
                                                    1. If context cannot be dereferenced, or the document from context document cannot be transformed into the internal representation , a loading remote context failed error has been detected and processing is aborted.
                                                    2. If the document has no top-level map with an @context entry, an invalid remote context has been detected and processing is aborted.
                                                    3. Set loaded context to the value of that entry.
                                                  6. Set result to the result of recursively calling this algorithm, passing result for active context, loaded context for local context, the documentUrl of context document for base URL, a copy of remote contexts, and validate scoped context.

                                                    Note

                                                    If context was previously dereferenced, processors MUST make provisions for retaining the base URL of that context for this step to enable the resolution of any relative context URLs that may be encountered during processing.

                                                  7. Continue with the next context.
                                                3. If context is not a map, an invalid local context error has been detected and processing is aborted.
                                                4. Otherwise, context is a context definition.
                                                5. If context has an @version entry:
                                                  1. If the associated value is not 1.1, an invalid @version value has been detected, and processing is aborted.

                                                    Note

                                                    The use of 1.1 for the value of @version is intended to cause a JSON-LD 1.0 processor to stop processing. Although it is clearly meant to be related to JSON-LD 1.1, it does not otherwise adhere to the requirements for Semantic Versioning. Implementations may require special consideration when comparing the values of numbers with a non-zero fractional part.

                                                  2. If processing mode is set to json-ld-1.0, a processing mode conflict error has been detected and processing is aborted.
                                                6. If context has an @import entry:
                                                  1. If processing mode is json-ld-1.0, an invalid context entry error has been detected and processing is aborted.
                                                  2. Otherwise, if the value of @import is not a string, an invalid @import value error has been detected and processing is aborted.
                                                  3. Initialize import to the result of resolving the value of @import against base URL.
                                                  4. Dereference import using the LoadDocumentCallback, passing import for url, and http://www.w3.org/ns/json-ld#context for profile and for requestProfile.
                                                  5. If import cannot be dereferenced, or cannot be transformed into the internal representation, a loading remote context failed error has been detected and processing is aborted.
                                                  6. If the dereferenced document has no top-level map with an @context entry, or if the value of @context is not a context definition (i.e., it is not an map), an invalid remote context has been detected and processing is aborted; otherwise, set import context to the value of that entry.
                                                  7. If import context has a @import entry, an invalid context entry error has been detected and processing is aborted.
                                                  8. Set context to the result of merging context into import context, replacing common entries with those from context.
                                                7. If context has an @base entry and remote contexts is empty, i.e., the currently being processed context is not a remote context:
                                                  1. Initialize value to the value associated with the @base entry.
                                                  2. If value is null, remove the base IRI of result.
                                                  3. Otherwise, if value is an IRI, the base IRI of result is set to value.
                                                  4. Otherwise, if value is a relative IRI reference and the base IRI of result is not null, set the base IRI of result to the result of resolving value against the current base IRI of result.
                                                  5. Otherwise, an invalid base IRI error has been detected and processing is aborted.
                                                8. If context has an @vocab entry:
                                                  1. Initialize value to the value associated with the @vocab entry.
                                                  2. If value is null, remove any vocabulary mapping from result.
                                                  3. Otherwise, if value is an IRI or blank node identifier, the vocabulary mapping of result is set to the result of IRI expanding value using true for document relative . If it is not an IRI, or a blank node identifier, an invalid vocab mapping error has been detected and processing is aborted.

                                                    Note

                                                    The use of blank node identifiers to value for @vocab is obsolete, and may be removed in a future version of JSON-LD.

                                                9. If context has an @language entry:
                                                  1. Initialize value to the value associated with the @language entry.
                                                  2. If value is null, remove any default language from result.
                                                  3. Otherwise, if value is a string, the default language of result is set to value. If it is not a string, an invalid default language error has been detected and processing is aborted. If value is not well-formed according to section 2.2.9 of [BCP47], processors SHOULD issue a warning.
                                                10. If context has an @direction entry:
                                                  1. If processing mode is json-ld-1.0, an invalid context entry error has been detected and processing is aborted.
                                                  2. Initialize value to the value associated with the @direction entry.
                                                  3. If value is null, remove any base direction from result.
                                                  4. Otherwise, if value is a string, the base direction of result is set to value. If it is not null, "ltr", or "rtl", an invalid base direction error has been detected and processing is aborted.
                                                11. If context has an @propagate entry:
                                                  1. If processing mode is json-ld-1.0, an invalid context entry error has been detected and processing is aborted.
                                                  2. Otherwise, if the value of @propagate is not boolean true or false, an invalid @propagate value error has been detected and processing is aborted.

                                                    Note

                                                    The previous context is actually set earlier in this algorithm; the previous two steps exist for error checking only.

                                                12. Create a map defined to keep track of whether or not a term has already been defined or is currently being defined during recursion.
                                                13. For each key-value pair in context where key is not @base, @direction, @import, @language, @propagate, @protected, @version, or @vocab, invoke the Create Term Definition algorithm, passing result for active context, context for local context, key, defined, base URL, the value of the @protected entry from context, if any, for protected, override protected, and a copy of remote contexts.
                                              6. Return result.

                                              4.2 Create Term Definition

                                              This algorithm is called from the Context Processing algorithm to create a term definition in the active context for a term being processed in a local context.

                                              4.2.1 Overview

                                              This section is non-normative.

                                              Term definitions are created by parsing the information in the given local context for the given term. If the given term is a compact IRI, it may omit an IRI mapping by depending on its prefix having its own term definition. If the prefix is an entry in the local context, then its term definition must first be created, through recursion, before continuing. Because a term definition can depend on other term definitions, a mechanism must be used to detect cyclical dependencies. The solution employed here uses a map, defined, that keeps track of whether or not a term has been defined or is currently in the process of being defined. This map is checked before any recursion is attempted.

                                              After all dependencies for a term have been defined, the rest of the information in the local context for the given term is taken into account, creating the appropriate IRI mapping, container mapping, and type mapping, language mapping, or direction mapping for the term.

                                              4.2.2 Algorithm

                                              The algorithm has four required and five optional inputs. The required inputs are an active context, a local context, a term, and a map defined. The optional inputs are base URL defaulting to null, protected which defaults to false, and override protected, defaulting to false, which is used to allow changes to protected terms, an array remote contexts, defaulting to a new empty array, which is used to detect cyclical context inclusions, and validate scoped context defaulting to true, which is used to limit recursion when validating possibly recursive scoped contexts..

                                              1. If defined contains the entry term and the associated value is true (indicating that the term definition has already been created), return. Otherwise, if the value is false, a cyclic IRI mapping error has been detected and processing is aborted.
                                              2. If term is the empty string (""), an invalid term definition error has been detected and processing is aborted. Otherwise, set the value associated with defined's term entry to false. This indicates that the term definition is now being created but is not yet complete.
                                              3. Initialize value to a copy of the value associated with the entry term in local context.
                                              4. If term is @type, and processing mode is json-ld-1.0, a keyword redefinition error has been detected and processing is aborted. At this point, value MUST be a map with only either or both of the following entries:
                                                • An entry for @container with value @set.
                                                • An entry for @protected.
                                                Any other value means that a keyword redefinition error has been detected and processing is aborted.
                                              5. Otherwise, since keywords cannot be overridden, term MUST NOT be a keyword and a keyword redefinition error has been detected and processing is aborted. If term has the form of a keyword (i.e., it matches the ABNF rule "@"1*ALPHA from [RFC5234]), return; processors SHOULD generate a warning.
                                              6. Initialize previous definition to any existing term definition for term in active context, removing that term definition from active context.
                                              7. If value is null, convert it to a map consisting of a single entry whose key is @id and whose value is null.
                                              8. Otherwise, if value is a string, convert it to a map consisting of a single entry whose key is @id and whose value is value. Set simple term to true.
                                              9. Otherwise, value MUST be a map, if not, an invalid term definition error has been detected and processing is aborted. Set simple term to false.
                                              10. Create a new term definition, definition, initializing prefix flag to false, protected to protected, and reverse property to false.
                                              11. If value has an @protected entry, set the protected flag in definition to the value of this entry. If the value of @protected is not a boolean, an invalid @protected value error has been detected and processing is aborted. If processing mode is json-ld-1.0, an invalid term definition has been detected and processing is aborted.
                                              12. If value contains the entry @type:
                                                1. Initialize type to the value associated with the @type entry, which MUST be a string. Otherwise, an invalid type mapping error has been detected and processing is aborted.
                                                2. Set type to the result of IRI expanding type, using local context, and defined.
                                                3. If the expanded type is @json or @none, and processing mode is json-ld-1.0, an invalid type mapping error has been detected and processing is aborted.
                                                4. Otherwise, if the expanded type is neither @id, nor @json, nor @none, nor @vocab, nor an IRI, an invalid type mapping error has been detected and processing is aborted.
                                                5. Set the type mapping for definition to type.
                                              13. If value contains the entry @reverse:
                                                1. If value contains @id or @nest, entries, an invalid reverse property error has been detected and processing is aborted.
                                                2. If the value associated with the @reverse entry is not a string, an invalid IRI mapping error has been detected and processing is aborted.
                                                3. If the value associated with the @reverse entry is a string having the form of a keyword (i.e., it matches the ABNF rule "@"1*ALPHA from [RFC5234]), return; processors SHOULD generate a warning.
                                                4. Otherwise, set the IRI mapping of definition to the result of IRI expanding the value associated with the @reverse entry, using local context, and defined. If the result does not have the form of an IRI or a blank node identifier, an invalid IRI mapping error has been detected and processing is aborted.
                                                5. If value contains an @container entry, set the container mapping of definition to an array containing its value; if its value is neither @set, nor @index, nor null, an invalid reverse property error has been detected (reverse properties only support set- and index-containers) and processing is aborted.
                                                6. Set the reverse property flag of definition to true.
                                                7. Set the term definition of term in active context to definition and the value associated with defined's entry term to true and return.
                                              14. If value contains the entry @id and its value does not equal term:
                                                1. If the @id entry of value is null, the term is not used for IRI expansion, but is retained to be able to detect future redefinitions of this term.
                                                2. Otherwise:
                                                  1. If the value associated with the @id entry is not a string, an invalid IRI mapping error has been detected and processing is aborted.
                                                  2. If the value associated with the @id entry is not a keyword, but has the form of a keyword (i.e., it matches the ABNF rule "@"1*ALPHA from [RFC5234]), return; processors SHOULD generate a warning.
                                                  3. Otherwise, set the IRI mapping of definition to the result of IRI expanding the value associated with the @id entry, using local context, and defined. If the resulting IRI mapping is neither a keyword, nor an IRI, nor a blank node identifier, an invalid IRI mapping error has been detected and processing is aborted; if it equals @context, an invalid keyword alias error has been detected and processing is aborted.
                                                  4. If the term contains a colon (:) anywhere but as the first or last character of term, or if it contains a slash (/) anywhere:
                                                    1. Set the value associated with defined's term entry to true.
                                                    2. If the result of IRI expanding term using local context, and defined, is not the same as the IRI mapping of definition, an invalid IRI mapping error has been detected and processing is aborted.
                                                  5. If term contains neither a colon (:) nor a slash (/), simple term is true, and if the IRI mapping of definition is either an IRI ending with a gen-delim character, or a blank node identifier, set the prefix flag in definition to true.
                                              15. Otherwise if the term contains a colon (:) anywhere after the first character:
                                                1. If term is a compact IRI with a prefix that is an entry in local context a dependency has been found. Use this algorithm recursively passing active context, local context, the prefix as term, and defined.
                                                2. If term's prefix has a term definition in active context, set the IRI mapping of definition to the result of concatenating the value associated with the prefix's IRI mapping and the term's suffix.
                                                3. Otherwise, term is an IRI or blank node identifier. Set the IRI mapping of definition to term.
                                              16. Otherwise if the term contains a slash (/):
                                                1. Term is a relative IRI reference.
                                                2. Set the IRI mapping of definition to the result of IRI expanding term. If the resulting IRI mapping is not an IRI, an invalid IRI mapping error has been detected and processing is aborted.
                                              17. Otherwise, if term is @type, set the IRI mapping of definition to @type.
                                              18. Otherwise, if active context has a vocabulary mapping, the IRI mapping of definition is set to the result of concatenating the value associated with the vocabulary mapping and term. If it does not have a vocabulary mapping, an invalid IRI mapping error been detected and processing is aborted.
                                              19. If value contains the entry @container:
                                                1. Initialize container to the value associated with the @container entry, which MUST be either @graph, @id, @index, @language, @list, @set, @type, or an array containing exactly any one of those keywords, an array containing @graph and either @id or @index optionally including @set, or an array containing a combination of @set and any of @index, @graph, @id, @type, @language in any order . Otherwise, an invalid container mapping has been detected and processing is aborted.
                                                2. If the container value is @graph, @id, or @type, or is otherwise not a string, generate an invalid container mapping error and abort processing if processing mode is json-ld-1.0.
                                                3. Set the container mapping of definition to container coercing to an array, if necessary.
                                                4. If the container mapping of definition includes @type:
                                                  1. If type mapping in definition is undefined, set it to @id.
                                                  2. If type mapping in definition is neither @id nor @vocab, an invalid type mapping error has been detected and processing is aborted.
                                              20. If value contains the entry @index:
                                                1. If processing mode is json-ld-1.0 or container mapping does not include @index, an invalid term definition has been detected and processing is aborted.
                                                2. Initialize index to the value associated with the @index entry. If the result of IRI expanding that value is not an IRI, an invalid term definition has been detected and processing is aborted.
                                                3. Set the index mapping of definition to index
                                              21. If value contains the entry @context:
                                                1. If processing mode is json-ld-1.0, an invalid term definition has been detected and processing is aborted.
                                                2. Initialize context to the value associated with the @context entry, which is treated as a local context.
                                                3. Invoke the Context Processing algorithm using the active context, context as local context, base URL, true for override protected, a copy of remote contexts, and false for validate scoped context. If any error is detected, an invalid scoped context error has been detected and processing is aborted.

                                                  Note

                                                  The result of the Context Processing algorithm is discarded; it is called to detect errors at definition time. If used, the context will be re-processed and applied to the active context as part of expansion or compaction.

                                                4. Set the local context of definition to context, and base URL to base URL.
                                              22. If value contains the entry @language and does not contain the entry @type:
                                                1. Initialize language to the value associated with the @language entry, which MUST be either null or a string. If language is not well-formed according to section 2.2.9 of [BCP47], processors SHOULD issue a warning. Otherwise, an invalid language mapping error has been detected and processing is aborted.
                                                2. Set the language mapping of definition to language.
                                              23. If value contains the entry @direction and does not contain the entry @type:
                                                1. Initialize direction to the value associated with the @direction entry, which MUST be either null, "ltr", or "rtl". Otherwise, an invalid base direction error has been detected and processing is aborted.
                                                2. Set the direction mapping of definition to direction.
                                              24. If value contains the entry @nest:
                                                1. If processing mode is json-ld-1.0, an invalid term definition has been detected and processing is aborted.
                                                2. Initialize nest value in definition to the value associated with the @nest entry, which MUST be a string and MUST NOT be a keyword other than @nest. Otherwise, an invalid @nest value error has been detected and processing is aborted.
                                              25. If value contains the entry @prefix:
                                                1. If processing mode is json-ld-1.0, or if term contains a colon (:) or slash (/), an invalid term definition has been detected and processing is aborted.
                                                2. Set the prefix flag to the value associated with the @prefix entry, which MUST be a boolean. Otherwise, an invalid @prefix value error has been detected and processing is aborted.
                                                3. If the prefix flag of definition is set to true, and its IRI mapping is a keyword, an invalid term definition has been detected and processing is aborted.
                                              26. If value contains any entry other than @id, @reverse, @container, @context, @direction, @index, @language, @nest, @prefix, @protected, or @type, an invalid term definition error has been detected and processing is aborted.
                                              27. If override protected is false and previous definition exists and is protected;
                                                1. If definition is not the same as previous definition (other than the value of protected), a protected term redefinition error has been detected, and processing is aborted.
                                                2. Set definition to previous definition to retain the value of protected.
                                              28. Set the term definition of term in active context to definition and set the value associated with defined's entry term to true.

                                              4.3 Inverse Context Creation

                                              When there is more than one term that could be chosen to compact an IRI, it has to be ensured that the term selection is both deterministic and represents the most context-appropriate choice whilst taking into consideration algorithmic complexity.

                                              In order to make term selections, the concept of an inverse context is introduced. An inverse context is essentially a reverse lookup table that maps container mapping, type mappings, and language mappings to a simple term for a given active context. A inverse context only needs to be generated for an active context if it is being used for compaction.

                                              To make use of an inverse context, a list of preferred container mapping and the type mapping or language mapping are gathered for a particular value associated with an IRI. These parameters are then fed to the Term Selection algorithm, which will find the term that most appropriately matches the value's mappings.

                                              4.3.1 Overview

                                              This section is non-normative.

                                              To create an inverse context for a given active context, each term in the active context is visited, ordered by length, shortest first (ties are broken by choosing the lexicographically least term). For each term, an entry is added to the inverse context for each possible combination of container mapping and type mapping or language mapping that would legally match the term. Illegal matches include differences between a value's type mapping or language mapping and that of the term. If a term has no container mapping, type mapping, or language mapping (or some combination of these), then it will have an entry in the inverse context using the special key @none. This allows the Term Selection algorithm to fall back to choosing more generic terms when a more specifically-matching term is not available for a particular IRI and value combination.

                                              Although normalizing language tags is optional, the inverse context creates entries based on normalized language tags, so that the proper term can be selected regardless of representation.

                                              4.3.2 Algorithm

                                              The algorithm takes one required input: the active context that the inverse context is being created for.

                                              1. Initialize result to an empty map.
                                              2. Initialize default language to @none. If the active context has a default language, set default language to the default language from the active context normalized to lower case.
                                              3. For each key term and value term definition in the active context, ordered by shortest term first (breaking ties by choosing the lexicographically least term):
                                                1. If the term definition is null, term cannot be selected during compaction, so continue to the next term.
                                                2. Initialize container to @none. If the container mapping is not empty, set container to the concatenation of all values of the container mapping in lexicographical order .
                                                3. Initialize var to the value of the IRI mapping for the term definition.
                                                4. If var is not an entry of result, add an entry where the key is var and the value is an empty map to result.
                                                5. Reference the value associated with the var entry in result using the variable container map.
                                                6. If container map has no container entry, create one and set its value to a new map with three entries. The first entry is @language and its value is a new empty map, the second entry is @type and its value is a new empty map, and the third entry is @any and its value is a new map with the entry @none set to the term being processed.
                                                7. Reference the value associated with the container entry in container map using the variable type/language map.
                                                8. Reference the value associated with the @type entry in type/language map using the variable type map.
                                                9. Reference the value associated with the @language entry in type/language map using the variable language map.
                                                10. If the term definition indicates that the term represents a reverse property:
                                                  1. If type map does not have an @reverse entry, create one and set its value to the term being processed.
                                                11. Otherwise, if term definition has a type mapping which is @none:
                                                  1. If language map does not have an @any entry, create one and set its value to the term being processed.
                                                  2. If type map does not have an @any entry, create one and set its value to the term being processed.
                                                12. Otherwise, if term definition has a type mapping:
                                                  1. If type map does not have an entry corresponding to the type mapping in term definition, create one and set its value to the term being processed.
                                                13. Otherwise, if term definition has both a language mapping and a direction mapping:
                                                  1. Create a new variable lang dir.
                                                  2. If neither the language mapping nor the direction mapping are null, set lang dir to the concatenation of language mapping and direction mapping separated by an underscore ("_") normalized to lower case.
                                                  3. Otherwise, if language mapping is not null, set lang dir to the language mapping, normalized to lower case.
                                                  4. Otherwise, if direction mapping is not null, set lang dir to direction mapping preceded by an underscore ("_").
                                                  5. Otherwise, set lang dir to @null.
                                                  6. If language map does not have a lang dir entry, create one and set its value to the term being processed.
                                                14. Otherwise, if term definition has a language mapping (might be null):
                                                  1. If the language mapping equals null, set language to @null; otherwise to the language mapping, normalized to lower case.
                                                  2. If language map does not have a language entry, create one and set its value to the term being processed.
                                                15. Otherwise, if term definition has a direction mapping (might be null):
                                                  1. If the direction mapping equals null, set direction to @none; otherwise to direction mapping preceded by an underscore ("_").
                                                  2. If language map does not have a direction entry, create one and set its value to the term being processed.
                                                16. Otherwise, if active context has a default base direction:
                                                  1. Initialize a variable lang dir with the concatenation of default language and default base direction, separate by an underscore ("_"), normalized to lower case.
                                                  2. If language map does not have a lang dir entry, create one and set its value to the term being processed.
                                                  3. If language map does not have an @none entry, create one and set its value to the term being processed.
                                                  4. If type map does not have an @none entry, create one and set its value to the term being processed.
                                                17. Otherwise:
                                                  1. If language map does not have a default language entry (after being normalized to lower case), create one and set its value to the term being processed.
                                                  2. If language map does not have an @none entry, create one and set its value to the term being processed.
                                                  3. If type map does not have an @none entry, create one and set its value to the term being processed.
                                              4. Return result.

                                              4.4 Term Selection

                                              This algorithm, invoked via the IRI Compaction algorithm, makes use of an active context's inverse context to find the term that is best used to compact an IRI. Other information about a value associated with the IRI is given, including which container mapping and which type mapping or language mapping would be best used to express the value.

                                              4.4.1 Overview

                                              This section is non-normative.

                                              The inverse context's entry for the IRI will be first searched according to the preferred container mapping, in the order that they are given. Amongst terms with a matching container mapping, preference will be given to those with a matching type mapping or language mapping, over those without a type mapping or language mapping. If there is no term with a matching container mapping then the term without a container mapping that matches the given type mapping or language mapping is selected. If there is still no selected term, then a term with no type mapping or language mapping will be selected if available. No term will be selected that has a conflicting type mapping or language mapping. Ties between terms that have the same mappings are resolved by first choosing the shortest terms, and then by choosing the lexicographically least term. Note that these ties are resolved automatically because they were previously resolved when the Inverse Context Creation algorithm was used to create the inverse context.

                                              4.4.2 Algorithm

                                              This algorithm has five required inputs. They are: an active context, a keyword or IRI var, an array containers that represents an ordered list of preferred container mapping, a string type/language that indicates whether to look for a term with a matching type mapping or language mapping, and an array representing an ordered list of preferred values for the type mapping or language mapping to look for.

                                              1. If the active context has a null inverse context, set inverse context in active context to the result of calling the Inverse Context Creation algorithm using active context.
                                              2. Initialize inverse context to the value of inverse context in active context.
                                              3. Initialize container map to the value associated with var in the inverse context.
                                              4. For each item container in containers:
                                                1. If container is not an entry of container map, then there is no term with a matching container mapping for it, so continue to the next container.
                                                2. Initialize type/language map to the value associated with the container entry in container map.
                                                3. Initialize value map to the value associated with type/language entry in type/language map.
                                                4. For each item in preferred values:
                                                  1. If item is not an entry of value map, then there is no term with a matching type mapping or language mapping, so continue to the next item.
                                                  2. Otherwise, a matching term has been found, return the value associated with the item entry in value map.
                                              5. No matching term has been found. Return null.

                                              4.4.3 Examples

                                              This section is non-normative.

                                              The following examples are intended to illustrate how the term selection algorithm behaves for different term definitions and values. It is not comprehensive, but intended to illustrate different parts of the algorithm.

                                              Language Map Term

                                              If the term definition has "@container": "@language", it will only match a value object having no @type.

                                              Datatyped Term

                                              If the term definition has a datatype, it will only match a value object having a matching datatype.

                                              5. Expansion Algorithms

                                              The following sections describe algorithms for expanding JSON-LD documents, IRIs and values.

                                              5.1 Expansion Algorithm

                                              This algorithm expands a JSON-LD document, such that all context definitions are removed, all terms and compact IRIs are expanded to IRIs, blank node identifiers, or keywords and all JSON-LD values are expressed in arrays in expanded form.

                                              5.1.1 Overview

                                              This section is non-normative.

                                              Starting with its root element, we can process the JSON-LD document recursively, until we have a fully expanded result. When expanding an element, we can treat each one differently according to its type, in order to break down the problem:

                                              1. If the element is null, there is nothing to expand.
                                              2. Otherwise, if element is a scalar, we expand it according to the Value Expansion algorithm.
                                              3. Otherwise, if the element is an array, then we expand each of its items recursively and return them in a new array.
                                              4. Otherwise, element is a map. We expand each of its entries, adding them to our result, and then we expand each value for each entry recursively. Some of the entry keys will be terms or compact IRIs and others will be keywords or simply ignored because they do not have definitions in the context. Any IRIs will be expanded using the IRI Expansion algorithm.

                                              Finally, after ensuring result is in an array, we return result.

                                              Note

                                              Although the data model, based on [RDF11-CONCEPTS], does not support multiple unordered property values, this algorithm does not remove duplicates that may be found during expansion within an unordered array. Other algorithms, such as §  6.1 Compaction Algorithm, and §  7.1 Flattening Algorithm, do eliminate duplicate values from unordered arrays. A future version of this specification may be updated to remove duplicate array values when the form a set.

                                              5.1.2 Algorithm

                                              The algorithm takes four required and three optional input variables. The required inputs are an active context, an active property, an element to be expanded, and a base URL associated with the documentUrl of the original document to expand. The optional inputs are the frameExpansion flag allowing special forms of input used for frame expansion, the ordered flag, used to order map entry keys lexicographically, where noted, and the from map flag, used to control reverting previous term definitions in the active context associated with non-propagated contexts. If not passed, the optional flags are set to false.

                                              The algorithm also performs processing steps specific to expanding a JSON-LD Frame. For a frame, the @id and @type entries can accept an array of IRIs or an empty map. The entries of a value object can also accept an array of strings, or an empty map. Framing also uses additional keyword entries: (@explicit, @default, @embed, @explicit, @omitDefault, or @requireAll) which are preserved through expansion. Special processing for a JSON-LD Frame is invoked when the frameExpansion flag is set to true.

                                              Note

                                              As mentioned in Terms [JSON-LD11], to avoid forward-compatibility issues, terms should not start with an @ character as future versions of JSON-LD may introduce additional keywords. This algorithm will treat such terms like any other term, i.e., they are ignored unless mapped to an IRI. Implementations of this algorithm may consider providing a runtime flag to show a warning if such terms are encountered.

                                              Note

                                              The use of empty terms ("") is not allowed as not all programming languages are able to handle empty JSON keys. Implementations of this algorithm may consider providing a runtime flag to show a warning if such terms are encountered.

                                              Note

                                              The use of blank node identifiers to label properties is obsolete, and may be removed in a future version of JSON-LD. Implementations of this algorithm may consider providing a runtime flag to show a warning if such terms are encountered.

                                              1. If element is null, return null.
                                              2. If active property is @default, initialize the frameExpansion flag to false.
                                              3. If active property has a term definition in active context with a local context, initialize property-scoped context to that local context.
                                              4. If element is a scalar,
                                                1. If active property is null or @graph, drop the free-floating scalar by returning null.
                                                2. If property-scoped context is defined, set active context to the result of the Context Processing algorithm, passing active context, property-scoped context as local context, and base URL from the term definition for active property in active context.
                                                3. Return the result of the Value Expansion algorithm, passing the active context, active property, and element as value.
                                              5. If element is an array,
                                                1. Initialize an empty array, result.
                                                2. For each item in element:
                                                  1. Initialize expanded item to the result of using this algorithm recursively, passing active context, active property, item as element, base URL, the frameExpansion ordered, and from map flags.
                                                  2. If the container mapping of active property includes @list, and expanded item is an array, set expanded item to a new map containing the entry @list where the value is the original expanded item.
                                                  3. If expanded item is an array, append each of its items to result. Otherwise, if expanded item is not null, append it to result.
                                                3. Return result.
                                              6. Otherwise element is a map.
                                              7. If active context has a previous context, the active context is not propagated. If from map is undefined or false, and element does not contain an entry expanding to @value, and element does not consist of a single entry expanding to @id (where entries are IRI expanded, set active context to previous context from active context, as the scope of a term-scoped context does not apply when processing new node objects.
                                              8. If property-scoped context is defined, set active context to the result of the Context Processing algorithm, passing active context, property-scoped context as local context, base URL from the term definition for active property, in active context and true for override protected.
                                              9. If element contains the entry @context, set active context to the result of the Context Processing algorithm, passing active context, the value of the @context entry as local context and base URL.
                                              10. Initialize type-scoped context to active context. This is used for expanding values that may be relevant to any previous type-scoped context.
                                              11. For each key and value in element ordered lexicographically by key where key IRI expands to @type:
                                                1. Convert value into an array, if necessary.
                                                2. For each term which is a value of value ordered lexicographically, if term is a string, and term's term definition in type-scoped context has a local context, set active context to the result Context Processing algorithm, passing active context, the value of the term's local context as local context, base URL from the term definition for value in active context, and false for propagate.
                                              12. Initialize two empty maps, result and nests. Initialize input type to expansion of the last value of the first entry in element expanding to @type (if any), ordering entries lexicographically by key. Both the key and value of the matched entry are IRI expanded.
                                              13. For each key and value in element, ordered lexicographically by key if ordered is true:
                                                1. If key is @context, continue to the next key.
                                                2. Initialize expanded property to the result of IRI expanding key.
                                                3. If expanded property is null or it neither contains a colon (:) nor it is a keyword, drop key by continuing to the next key.
                                                4. If expanded property is a keyword:
                                                  1. If active property equals @reverse, an invalid reverse property map error has been detected and processing is aborted.
                                                  2. If result already has an expanded property entry, other than @included or @type (unless processing mode is json-ld-1.0), a colliding keywords error has been detected and processing is aborted.
                                                  3. If expanded property is @id:
                                                    1. If value is not a string, an invalid @id value error has been detected and processing is aborted. When the frameExpansion flag is set, value MAY be an empty map, or an array of one or more strings.
                                                    2. Otherwise, set expanded value to the result of IRI expanding value using true for document relative and false for vocab. When the frameExpansion flag is set, expanded value will be an array of one or more of the values, with string values expanded using the IRI Expansion algorithm as above.
                                                  4. If expanded property is @type:
                                                    1. If value is neither a string nor an array of strings, an invalid type value error has been detected and processing is aborted. When the frameExpansion flag is set, value MAY be an empty map, or a default object where the value of @default is restricted to be an IRI. All other values mean that invalid type value error has been detected and processing is aborted.
                                                    2. If value is an empty map, set expanded value to value.
                                                    3. Otherwise, if value is a default object, set expanded value to a new default object with the value of @default set to the result of IRI expanding value using type-scoped context for active context, and true for document relative.
                                                    4. Otherwise, set expanded value to the result of IRI expanding each of its values using type-scoped context for active context, and true for document relative.
                                                    5. If result already has an entry for @type, prepend the value of @type in result to expanded value, transforming it into an array, if necessary.

                                                      Note

                                                      No transformation from a string value to an array expanded value is implied, and the form or value should be preserved in expanded value.

                                                  5. If expanded property is @graph, set expanded value to the result of using this algorithm recursively passing active context, @graph for active property, value for element, base URL, and the frameExpansion and ordered flags, ensuring that expanded value is an array of one or more maps.
                                                  6. If expanded property is @included:
                                                    1. If processing mode is json-ld-1.0, continue with the next key from element.
                                                    2. Set expanded value to the result of using this algorithm recursively passing active context, null for active property, value for element, base URL, and the frameExpansion and ordered flags, ensuring that the result is an array.
                                                    3. If any element of expanded value is not a node object, an invalid @included value error has been detected and processing is aborted.
                                                    4. If result already has an entry for @included, prepend the value of @included in result to expanded value.
                                                  7. If expanded property is @value:
                                                    1. If input type is @json, set expanded value to value. If processing mode is json-ld-1.0, an invalid value object value error has been detected and processing is aborted.
                                                    2. Otherwise, if value is not a scalar or null, an invalid value object value error has been detected and processing is aborted. When the frameExpansion flag is set, value MAY be an empty map or an array of scalar values.
                                                    3. Otherwise, set expanded value to value. When the frameExpansion flag is set, expanded value will be an array of one or more string values or an array containing an empty map.
                                                    4. If expanded value is null, set the @value entry of result to null and continue with the next key from element. Null values need to be preserved in this case as the meaning of an @type entry depends on the existence of an @value entry.
                                                  8. If expanded property is @language:
                                                    1. If value is not a string, an invalid language-tagged string error has been detected and processing is aborted. When the frameExpansion flag is set, value MAY be an empty map or an array of zero or more strings.
                                                    2. Otherwise, set expanded value to value. If value is not well-formed according to section 2.2.9 of [BCP47], processors SHOULD issue a warning. When the frameExpansion flag is set, expanded value will be an array of one or more string values or an array containing an empty map.
                                                  9. If expanded property is @direction:
                                                    1. If processing mode is json-ld-1.0, continue with the next key from element.
                                                    2. If value is neither "ltr" nor "rtl", an invalid base direction error has been detected and processing is aborted. When the frameExpansion flag is set, value MAY be an empty map or an array of zero or more strings.
                                                    3. Otherwise, set expanded value to value. When the frameExpansion flag is set, expanded value will be an array of one or more string values or an array containing an empty map.
                                                  10. If expanded property is @index:
                                                    1. If value is not a string, an invalid @index value error has been detected and processing is aborted.
                                                    2. Otherwise, set expanded value to value.
                                                  11. If expanded property is @list:
                                                    1. If active property is null or @graph, continue with the next key from element to remove the free-floating list.
                                                    2. Otherwise, initialize expanded value to the result of using this algorithm recursively passing active context, active property, value for element, base URL, and the frameExpansion and ordered flags, ensuring that the result is an array..
                                                  12. If expanded property is @set, set expanded value to the result of using this algorithm recursively, passing active context, active property, value for element, base URL, and the frameExpansion and ordered flags.
                                                  13. If expanded property is @reverse:
                                                    1. If value is not a map, an invalid @reverse value error has been detected and processing is aborted.
                                                    2. Otherwise initialize expanded value to the result of using this algorithm recursively, passing active context, @reverse as active property, value as element, base URL, and the frameExpansion and ordered flags.
                                                    3. If expanded value contains an @reverse entry, i.e., properties that are reversed twice, execute for each of its property and item the following steps:
                                                      1. Use add value to add item to the property entry in result using true for as array.
                                                    4. If expanded value contains an entry other than @reverse:
                                                      1. Set reverse map to the value of the @reverse entry in result, initializing it to an empty map, if necessary.
                                                      2. For each property and items in expanded value other than @reverse:
                                                        1. For each item in items:
                                                          1. If item is a value object or list object, an invalid reverse property value has been detected and processing is aborted.
                                                          2. Use add value to add item to the property entry in reverse map using true for as array.
                                                    5. Continue with the next key from element.
                                                  14. If expanded property is @nest, add key to nests, initializing it to an empty array, if necessary. Continue with the next key from element.
                                                  15. When the frameExpansion flag is set, if expanded property is any other framing keyword (@default, @embed, @explicit, @omitDefault, or @requireAll), set expanded value to the result of performing the Expansion Algorithm recursively, passing active context, active property, value for element, base URL, and the frameExpansion and ordered flags.
                                                  16. Unless expanded value is null, expanded property is @value, and input type is not @json, set the expanded property entry of result to expanded value.
                                                  17. Continue with the next key from element.
                                                5. Initialize container mapping to key's container mapping in active context.
                                                6. If key's term definition in active context has a type mapping of @json, set expanded value to a new map, set the entry @value to value, and set the entry @type to @json.
                                                7. Otherwise, if container mapping includes @language and value is a map then value is expanded from a language map as follows:
                                                  1. Initialize expanded value to an empty array.
                                                  2. Initialize direction to the default base direction from active context.
                                                  3. If key's term definition in active context has a direction mapping, update direction with that value.
                                                  4. For each key-value pair language-language value in value, ordered lexicographically by language if ordered is true:
                                                    1. If language value is not an array set language value to an array containing only language value.
                                                    2. For each item in language value:
                                                      1. If item is null, continue to the next entry in language value.
                                                      2. item must be a string, otherwise an invalid language map value error has been detected and processing is aborted.
                                                      3. Initialize a new map v consisting of two key-value pairs: (@value-item) and (@language-language). If item is neither @none nor well-formed according to section 2.2.9 of [BCP47], processors SHOULD issue a warning.
                                                      4. If language is @none, or expands to @none, remove @language from v.
                                                      5. If direction is not null, add an entry for @direction to v with direction.
                                                      6. Append v to expanded value.
                                                8. Otherwise, if container mapping includes @index, @type, or @id and value is a map then value is expanded from an map as follows:
                                                  1. Initialize expanded value to an empty array.
                                                  2. Initialize index key to the key's index mapping in active context, or @index, if it does not exist.
                                                  3. For each key-value pair index-index value in value, ordered lexicographically by index if ordered is true:
                                                    1. If container mapping includes @id or @type, initialize map context to the previous context from active context if it exists, otherwise, set map context to active context.
                                                    2. If container mapping includes @type and index's term definition in map context has a local context, update map context to the result of the Context Processing algorithm, passing map context as active context the value of the index's local context as local context and base URL from the term definition for index in map context.
                                                    3. Otherwise, set map context to active context.
                                                    4. Initialize expanded index to the result of IRI expanding index.
                                                    5. If index value is not an array set index value to an array containing only index value.
                                                    6. Initialize index value to the result of using this algorithm recursively, passing map context as active context, key as active property, index value as element, base URL, true for from map, and the frameExpansion and ordered flags.
                                                    7. For each item in index value:
                                                      1. If container mapping includes @graph, and item is not a graph object, set item to a new map containing the key-value pair @graph-item, ensuring that the value is represented using an array.
                                                      2. If container mapping includes @index, index key is not @index, and expanded index is not @none:
                                                        1. Initialize re-expanded index to the result of calling the Value Expansion algorithm, passing the active context, index key as active property, and index as value.
                                                        2. Initialize expanded index key to the result of IRI expanding index key.
                                                        3. Initialize index property values to an array consisting of re-expanded index followed by the existing values of the concatenation of expanded index key in item, if any.
                                                        4. Add the key-value pair (expanded index key-index property values) to item.
                                                        5. If item is a value object, it MUST NOT contain any extra properties; an invalid value object error has been detected and processing is aborted.
                                                      3. Otherwise, if container mapping includes @index, item does not have an entry @index, and expanded index is not @none, add the key-value pair (@index-index) to item.
                                                      4. Otherwise, if container mapping includes @id item does not have the entry @id, and expanded index is not @none, add the key-value pair (@id-expanded index) to item, where expanded index is set to the result of IRI expandingindex using true for document relative and false for vocab.
                                                      5. Otherwise, if container mapping includes @type and expanded index is not @none, initialize types to a new array consisting of expanded index followed by any existing values of @type in item. Add the key-value pair (@type-types) to item.
                                                      6. Append item to expanded value.
                                                9. Otherwise, initialize expanded value to the result of using this algorithm recursively, passing active context, key for active property, value for element, base URL, and the frameExpansion and ordered flags.
                                                10. If expanded value is null, ignore key by continuing to the next key from element.
                                                11. If container mapping includes @list and expanded value is not already a list object, convert expanded value to a list object by first setting it to an array containing only expanded value if it is not already an array, and then by setting it to a map containing the key-value pair @list-expanded value.
                                                12. If container mapping includes @graph, and includes neither @id nor @index, convert expanded value into an array, if necessary, then convert each value ev in expanded value into a graph object:
                                                  1. Convert ev into a graph object by creating a map containing the key-value pair @graph-ev where ev is represented as an array.

                                                    Note

                                                13. If the term definition associated to key indicates that it is a reverse property
                                                  1. If result has no @reverse entry, create one and initialize its value to an empty map.
                                                  2. Reference the value of the @reverse entry in result using the variable reverse map.
                                                  3. If expanded value is not an array, set it to an array containing expanded value.
                                                  4. For each item in expanded value
                                                    1. If item is a value object or list object, an invalid reverse property value has been detected and processing is aborted.
                                                    2. If reverse map has no expanded property entry, create one and initialize its value to an empty array.
                                                    3. Use add value to add item to the expanded property entry in reverse map using true for as array.
                                                14. Otherwise, key is not a reverse property use add value to add expanded value to the expanded property entry in result using true for as array.
                                              14. For each key nesting-key in nests, ordered lexicographically if ordered is true:
                                                1. Initialize nested values to the value of nesting-key in element, ensuring that it is an array.
                                                2. For each nested value in nested values:
                                                  1. If nested value is not a map, or any key within nested value expands to @value, an invalid @nest value error has been detected and processing is aborted.
                                                  2. Recursively repeat steps 13 and 14 using nested value for element.

                                                    Note

                                                    By invoking steps 13 and 14 on nested value we are able to unfold arbitrary levels of nesting, with results being merged into result. Step 13 iterates through each entry in nested value and expands it, while collecting new nested values found at each level, until all nesting has been extracted.

                                              15. If result contains the entry @value:
                                                1. The result must not contain any entries other than @direction, @index, @language, @type, and @value. It must not contain an @type entry if it contains either @language or @direction entries. Otherwise, an invalid value object error has been detected and processing is aborted.
                                                2. If the result's @type entry is @json, then the @value entry may contain any value, and is treated as a JSON literal.
                                                3. Otherwise, if the value of result's @value entry is null, or an empty array, return null.
                                                4. Otherwise, if the value of result's @value entry is not a string and result contains the entry @language, an invalid language-tagged value error has been detected (only strings can be language-tagged) and processing is aborted.
                                                5. Otherwise, if the result has an @type entry and its value is not an IRI, an invalid typed value error has been detected and processing is aborted.
                                              16. Otherwise, if result contains the entry @type and its associated value is not an array, set it to an array containing only the associated value.
                                              17. Otherwise, if result contains the entry @set or @list:
                                                1. The result must contain at most one other entry which must be @index. Otherwise, an invalid set or list object error has been detected and processing is aborted.
                                                2. If result contains the entry @set, then set result to the entry's associated value.
                                              18. If result is a map that contains only the entry @language, return null.
                                              19. If active property is null or @graph, drop free-floating values as follows:
                                                1. If result is a map which is empty, or contains only the entries @value or @list, set result to null.
                                                2. Otherwise, if result is a map whose only entry is @id, set result to null. When the frameExpansion flag is set, a map containing only the @id entry is retained.
                                              20. Return result.

                                              5.2 IRI Expansion

                                              In JSON-LD documents, some keys and values may represent IRIs. This section defines an algorithm for transforming a string that represents an IRI into an absolute IRI or blank node identifier. It also covers transforming keyword aliases into keywords.

                                              IRI expansion may occur during context processing or during any of the other JSON-LD algorithms. If IRI expansion occurs during context processing, then the local context and its related defined map from the Context Processing algorithm are passed to this algorithm. This allows for term definition dependencies to be processed via the Create Term Definition algorithm.

                                              5.2.1 Overview

                                              This section is non-normative.

                                              In order to expand value to an IRI, we must first determine if it is null, a term, a keyword alias, or some form of IRI. Based on what we find, we handle the specific kind of expansion; for example, we expand a keyword alias to a keyword and a term to an IRI according to its IRI mapping in the active context. While inspecting value we may also find that we need to create term definition dependencies because we're running this algorithm during context processing. We can tell whether or not we're running during context processing by checking local context against null. We know we need to create a term definition in the active context when value is an entry in the local context and the defined map does not have an entry for value with an associated value of true. The defined map is used during Context Processing to keep track of which terms have already been defined or are in the process of being defined. We create a term definition by using the Create Term Definition algorithm.

                                              Note

                                              Values that have the form of a keyword, but are not keywords (i.e., they begin with "@") do not map to any value, as they are reserved for future use. The algorithm returns null, so that they will be ignored when encountered.

                                              5.2.2 Algorithm

                                              The algorithm takes two required and four optional input variables. The required inputs are an active context and a value to be expanded. The optional inputs are two flags, document relative and vocab, that specifying whether value can be interpreted as a relative IRI reference against the document's base IRI or the active context's vocabulary mapping, respectively, and a local context and a map defined to be used when this algorithm is used during Context Processing. If not passed, the two flags are set to false and local context and defined are initialized to null.

                                              1. If value is a keyword or null, return value as is.
                                              2. If value has the form of a keyword (i.e., it matches the ABNF rule "@"1*ALPHA from [RFC5234]), a processor SHOULD generate a warning and return null.
                                              3. If local context is not null, it contains an entry with a key that equals value, and the value of the entry for value in defined is not true, invoke the Create Term Definition algorithm, passing active context, local context, value as term, and defined. This will ensure that a term definition is created for value in active context during Context Processing.
                                              4. If active context has a term definition for value, and the associated IRI mapping is a keyword, return that keyword.
                                              5. If vocab is true and the active context has a term definition for value, return the associated IRI mapping.
                                              6. If value contains a colon (:) anywhere after the first character, it is either an IRI, a compact IRI, or a blank node identifier:
                                                1. Split value into a prefix and suffix at the first occurrence of a colon (:).
                                                2. If prefix is underscore (_) or suffix begins with double-forward-slash (//), return value as it is already an IRI or a blank node identifier.
                                                3. If local context is not null, it contains a prefix entry, and the value of the prefix entry in defined is not true, invoke the Create Term Definition algorithm, passing active context, local context, prefix as term, and defined. This will ensure that a term definition is created for prefix in active context during Context Processing.
                                                4. If active context contains a term definition for prefix having a non-null IRI mapping and the prefix flag of the term definition is true, return the result of concatenating the IRI mapping associated with prefix and suffix.
                                                5. If value has the form of an IRI, return value.
                                              7. If vocab is true, and active context has a vocabulary mapping, return the result of concatenating the vocabulary mapping with value.
                                              8. Otherwise, if document relative is true set value to the result of resolving value against the base IRI from active context. Only the basic algorithm in section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization nor Scheme-Based Normalization are performed. Characters additionally allowed in IRI references are treated in the same way that unreserved characters are treated in URI references, per section 6.5 of [RFC3987].
                                              9. Return value as is.

                                              5.3 Value Expansion

                                              Some values in JSON-LD can be expressed in a compact form. These values are required to be expanded at times when processing JSON-LD documents. A value is said to be in expanded form after the application of this algorithm.

                                              5.3.1 Overview

                                              This section is non-normative.

                                              If active property has a type mapping in the active context set to @id or @vocab, and the value is a string, a map with a single entry @id whose value is the result of using the IRI Expansion algorithm on value is returned.

                                              Otherwise, the result will be a map containing an @value entry whose value is the passed value. Additionally, an @type entry will be included if there is a type mapping associated with the active property or an @language entry if value is a string and there is language mapping associated with the active property.

                                              Note that values interpreted as IRIs fall into two categories: those that are document relative, and those that are vocabulary relative. Properties and values of @type, along with terms marked as "@type": "@vocab" are vocabulary relative, meaning that they need to be either a defined term, a compact IRI where the prefix is a term, or a string which is turned into an IRI using the vocabulary mapping.

                                              5.3.2 Algorithm

                                              The algorithm takes three required inputs: an active context, an active property, and a value to expand.

                                              1. If the active property has a type mapping in active context that is @id, and the value is a string, return a new map containing a single entry where the key is @id and the value is the result IRI expanding value using true for document relative and false for vocab.
                                              2. If active property has a type mapping in active context that is @vocab, and the value is a string, return a new map containing a single entry where the key is @id and the value is the result of IRI expanding value using true for document relative.
                                              3. Otherwise, initialize result to a map with an @value entry whose value is set to value.
                                              4. If active property has a type mapping in active context, other than @id, @vocab, or @none, add @type to result and set its value to the value associated with the type mapping.
                                              5. Otherwise, if value is a string:
                                                1. Initialize language to the language mapping for active property in active context, if any, otherwise to the default language of active context.
                                                2. Initialize direction to the direction mapping for active property in active context, if any, otherwise to the default base direction of active context.
                                                3. If language is not null, add @language to result with the value language.
                                                4. If direction is not null, add @direction to result with the value direction.
                                              6. Return result.

                                              6. Compaction Algorithms

                                              The following sections describe algorithms for compacting JSON-LD documents, IRIs and values.

                                              6.1 Compaction Algorithm

                                              This algorithm compacts a JSON-LD document, such that the given context is applied. This must result in shortening any applicable IRIs to terms or compact IRIs, any applicable keywords to keyword aliases, and any applicable JSON-LD values expressed in expanded form to simple values such as strings or numbers.

                                              6.1.1 Overview

                                              This section is non-normative.

                                              Starting with its root element, we can process the JSON-LD document recursively, until we have a fully compacted result. When compacting an element, we can treat each one differently according to its type, in order to break down the problem:

                                              1. If the element is a scalar, it is already in compacted form, so we simply return it.
                                              2. If the element is an array, we compact each of its items recursively and return them in a new array.
                                              3. Otherwise element is a map. The value of each entry in element is compacted recursively. Some of the entry keys will be compacted, using the IRI Compaction algorithm, to terms or compact IRIs and others will be compacted from keywords to keyword aliases or simply left unchanged because they do not have definitions in the context. Values will be converted to compacted form via the Value Compaction algorithm. Some data will be reshaped based on container mapping specified in the context such as @index or @language maps.

                                              6.1.2 Algorithm

                                              The algorithm takes three required and two optional input variables. The required inputs are an active context, an active property, and an element to be compacted. The optional inputs are the compactArrays flag and the ordered flag, used to order map entry keys lexicographically, where noted. If not passed, both flags are set to false.

                                              1. Initialize type-scoped context to active context. This is used for compacting values that may be relevant to any previous type-scoped context.
                                              2. If element is a scalar, it is already in its most compact form, so simply return element.
                                              3. If element is an array:
                                                1. Initialize result to an empty array.
                                                2. For each item in element:
                                                  1. Initialize compacted item to the result of using this algorithm recursively, passing active context, active property, item for element, and the compactArrays and ordered flags.
                                                  2. If compacted item is not null, then append it to result.
                                                3. If result is empty or contains more than one value, or compactArrays is false, or active property is either @graph or @set, or container mapping for active property in active context includes either @list or @set, return result.
                                                4. Otherwise, return the value in result.
                                              4. Otherwise element is a map.
                                              5. If active context has a previous context, the active context is not propagated. If element does not contain an @value entry, and element does not consist of a single @id entry, set active context to previous context from active context, as the scope of a term-scoped context does not apply when processing new node objects.
                                              6. If the term definition for active property in active context has a local context:
                                                1. Set active context to the result of the Context Processing algorithm, passing active context, the value of the active property's local context as local context, base URL from the term definition for active property in active context, and true for override protected.
                                              7. If element has an @value or @id entry and the result of using the Value Compaction algorithm, passing active context, active property, and element as value is a scalar, or the term definition for active property has a type mapping of @json, return that result.
                                              8. If element is a list object, and the container mapping for active property in active context includes @list, return the result of using this algorithm recursively, passing active context, active property, value of @list in element for element, and the compactArrays and ordered flags.
                                              9. Initialize inside reverse to true if active property equals @reverse, otherwise to false.
                                              10. Initialize result to an empty map.
                                              11. If element has an @type entry, create a new array compacted types initialized by transforming each expanded type of that entry into its compacted form by IRI compacting expanded type. Then, for each term in compacted types ordered lexicographically:
                                                1. If the term definition for term in type-scoped context has a local context set active context to the result of the Context Processing algorithm, passing active context and the value of term's local context in type-scoped context as local context base URL from the term definition for term in type-scoped context, and false for propagate.
                                              12. For each key expanded property and value expanded value in element, ordered lexicographically by expanded property if ordered is true:
                                                1. If expanded property is @id:
                                                  1. If expanded value is a string, then initialize compacted value by IRI compacting expanded value with vocab set to false.
                                                  2. Initialize alias by IRI compacting expanded property.
                                                  3. Add an entry alias to result whose value is set to compacted value and continue to the next expanded property.
                                                2. If expanded property is @type:
                                                  1. If expanded value is a string, then initialize compacted value by IRI compacting expanded value using type-scoped context for active context.
                                                  2. Otherwise, expanded value must be a @type array:
                                                    1. Initialize compacted value to an empty array.
                                                    2. For each item expanded type in expanded value:
                                                      1. Set term by IRI compacting expanded type using type-scoped context for active context.
                                                      2. Append term, to compacted value.
                                                  3. Initialize alias by IRI compacting expanded property.
                                                  4. Initialize as array to true if processing mode is json-ld-1.1 and the container mapping for alias in the active context includes @set, otherwise to the negation of compactArrays.
                                                  5. Use add value to add compacted value to the alias entry in result using as array.
                                                  6. Continue to the next expanded property.
                                                3. If expanded property is @reverse:
                                                  1. Initialize compacted value to the result of using this algorithm recursively, passing active context, @reverse for active property, expanded value for element, and the compactArrays and ordered flags.
                                                  2. For each property and value in compacted value:
                                                    1. If the term definition for property in the active context indicates that property is a reverse property
                                                      1. Initialize as array to true if the container mapping for property in the active context includes @set, otherwise the negation of compactArrays.
                                                      2. Use add value to add value to the property entry in result using as array.
                                                      3. Remove the property entry from compacted value.
                                                  3. If compacted value has some remaining map entries, i.e., it is not an empty map:
                                                    1. Initialize alias by IRI compacting @reverse.
                                                    2. Set the value of the alias entry of result to compacted value.
                                                  4. Continue with the next expanded property from element.
                                                4. If expanded property is @preserve then:
                                                  1. Initialize compacted value to the result of using this algorithm recursively, passing active context, active property, expanded value for element, and the compactArrays and ordered flags.
                                                  2. Add compacted value as the value of @preserve in result unless expanded value is an empty array.
                                                5. If expanded property is @index and active property has a container mapping in active context that includes @index, then the compacted result will be inside of an @index container, drop the @index entry by continuing to the next expanded property.
                                                6. Otherwise, if expanded property is @direction, @index, @language, or @value:
                                                  1. Initialize alias by IRI compacting expanded property.
                                                  2. Add an entry alias to result whose value is set to expanded value and continue with the next expanded property.
                                                7. If expanded value is an empty array:
                                                  1. Initialize item active property by IRI compacting expanded property using expanded value for value and inside reverse for reverse.
                                                  2. If the term definition for item active property in the active context has a nest value entry (nest term):
                                                    1. If nest term is not @nest, or a term in the active context that expands to @nest, an invalid @nest value error has been detected, and processing is aborted.
                                                    2. If result does not have a nest term entry, initialize it to an empty map.
                                                    3. Initialize nest result to the value of nest term in result.
                                                  3. Otherwise, initialize nest result to result.
                                                  4. Use add value to add an empty array to the item active property entry in nest result using true for as array.
                                                8. At this point, expanded value must be an array due to the Expansion algorithm. For each item expanded item in expanded value:
                                                  1. Initialize item active property by IRI compacting expanded property using expanded item for value and inside reverse for reverse.
                                                  2. If the term definition for item active property in the active context has a nest value entry (nest term):
                                                    1. If nest term is not @nest, or a term in the active context that expands to @nest, an invalid @nest value error has been detected, and processing is aborted.
                                                    2. If result does not have a nest term entry, initialize it to an empty map.
                                                    3. Initialize nest result to the value of nest term in result.
                                                  3. Otherwise, initialize nest result to result.
                                                  4. Initialize container to container mapping for item active property in active context, or to a new empty array, if there is no such container mapping.
                                                  5. Initialize as array to true if container includes @set, or if item active property is @graph or @list, otherwise the negation of compactArrays.
                                                  6. Initialize compacted item to the result of using this algorithm recursively, passing active context, item active property for active property, expanded item for element, along with the compactArrays and ordered flags. If expanded item is a list object or a graph object, use the value of the @list or @graph entries, respectively, for element instead of expanded item.
                                                  7. If expanded item is a list object:
                                                    1. If compacted item is not an array, then set compacted item to an array containing only compacted item.
                                                    2. If container does not include @list:
                                                      1. Convert compacted item to a list object by setting it to a map containing an entry where the key is the result of IRI compacting @list and the value is the original compacted item.
                                                      2. If expanded item contains the entry @index-value, then add an entry to compacted item where the key is the result of IRI compacting @index and value is value.
                                                      3. Use add value to add compacted item to the item active property entry in nest result using as array.
                                                    3. Otherwise, set the value of the item active property entry in nest result to compacted item.
                                                  8. If expanded item is a graph object:
                                                    1. If container includes @graph and @id:
                                                      1. Initialize map object to the value of item active property in nest result, initializing it to a new empty map, if necessary.
                                                      2. Initialize map key by IRI compacting the value of @id in expanded item or @none if no such value exists with vocab set to false if there is an @id entry in expanded item.
                                                      3. Use add value to add compacted item to the map key entry in map object using as array.
                                                    2. Otherwise, if container includes @graph and @index and expanded item is a simple graph object:
                                                      1. Initialize map object to the value of item active property in nest result, initializing it to a new empty map, if necessary.
                                                      2. Initialize map key the value of @index in expanded item or @none, if no such value exists.
                                                      3. Use add value to add compacted item to the map key entry in map object using as array.
                                                    3. Otherwise, if container includes @graph and expanded item is a simple graph object the value cannot be represented as a map object.
                                                      1. If compacted item is an array with more than one value, it cannot be directly represented, as multiple objects would be interpreted as different named graphs. Set compacted item to a new map, containing the key from IRI compacting @included and the original compacted item as the value.
                                                      2. Use add value to add compacted item to the item active property entry in nest result using as array.
                                                    4. Otherwise, container does not include @graph or otherwise does not match one of the previous cases.
                                                      1. Set compacted item to a new map containing the key from IRI compacting @graph using the original compacted item as a value.
                                                      2. If expanded item contains an @id entry, add an entry in compacted item using the key from IRI compacting @id using the value of IRI compacting the value of @id in expanded item using false for vocab.
                                                      3. If expanded item contains an @index entry, add an entry in compacted item using the key from IRI compacting @index and the value of @index in expanded item.
                                                      4. Use add value to add compacted item to the item active property entry in nest result using as array.
                                                  9. Otherwise, if container includes @language, @index, @id, or @type and container does not include @graph:
                                                    1. Initialize map object to the value of item active property in nest result, initializing it to a new empty map, if necessary.
                                                    2. Initialize container key by IRI compacting either @language, @index, @id, or @type based on the contents of container.
                                                    3. Initialize index key to the value of index mapping in the term definition associated with item active property in active context, or @index, if no such value exists.
                                                    4. If container includes @language and expanded item contains a @value entry, then set compacted item to the value associated with its @value entry. Set map key to the value of @language in expanded item, if any.
                                                    5. Otherwise, if container includes @index and index key is @index, set map key to the value of @index in expanded item, if any.
                                                    6. Otherwise, if container includes @index and index key is not @index:
                                                      1. Reinitialize container key by IRI compacting index key.
                                                      2. Set map key to the first value of container key in compacted item, if any.
                                                      3. If there are remaining values in compacted item for container key, use add value to add those remaining values to the container key in compacted item. Otherwise, remove that entry from compacted item.
                                                    7. Otherwise, if container includes @id, set map key to the value of container key in compacted item and remove container key from compacted item.
                                                    8. Otherwise, if container includes @type:
                                                      1. Set map key to the first value of container key in compacted item, if any.
                                                      2. If there are remaining values in compacted item for container key, use add value to add those remaining values to the container key in compacted item.
                                                      3. Otherwise, remove that entry from compacted item.
                                                      4. If compacted item contains a single entry with a key expanding to @id, set compacted item to the result of using this algorithm recursively, passing active context, item active property for active property, and a map composed of the single entry for @id from expanded item for element

                                              Read the original on w3.org ↗