diff --git a/specifications/did-1.0.md b/specifications/did-1.0.md new file mode 100644 index 0000000..457cf15 --- /dev/null +++ b/specifications/did-1.0.md @@ -0,0 +1,3927 @@ +--- +description: Decentralized identifiers (DIDs) are a new type of identifier that enables verifiable, decentralized digital identity. A DID refers to any subject (e.g., a person, organization, thing, data model, abstract entity, etc.) as determined by the controller of the DID. In contrast to typical, federated identifiers, DIDs have been designed so that they may be decoupled from centralized registries, identity providers, and certificate authorities. Specifically, while other parties might be used to help enable the discovery of information related to a DID, the design enables the controller of a DID to prove control over it without requiring permission from any other party. DIDs are URIs that associate a DID subject with a DID document allowing trustable interactions associated with that subject. +generator: ReSpec 32.1.10 +lang: en +title: Decentralized Identifiers (DIDs) v1.0 +viewport: width=device-width, initial-scale=1, shrink-to-fit=no +--- + +[![W3C](https://www.w3.org/StyleSheets/TR/2021/logos/W3C)](https://www.w3.org/) + +# Decentralized Identifiers (DIDs) v1.0 + +## Core architecture, data model, and representations + +[W3C Recommendation](https://www.w3.org/standards/types#REC) 19 July 2022 + +More details about this document + +This version: +: [https://www.w3.org/TR/2022/REC-did-core-20220719/](https://www.w3.org/TR/2022/REC-did-core-20220719/) + +Latest published version: +: + +Latest editor\'s draft: +: + +History: +: +: [Commit history](https://github.com/w3c/did-core/commits/main) + +Implementation report: +: + +Editors: +: [Manu Sporny](http://manu.sporny.org/) ([Digital Bazaar](https://digitalbazaar.com/)) +: [Amy Guy](https://rhiaro.co.uk/) ([Digital Bazaar](https://digitalbazaar.com/)) +: [Markus Sabadello](https://www.linkedin.com/in/markus-sabadello-353a0821) ([Danube Tech](https://danubetech.com/)) +: [Drummond Reed](https://www.linkedin.com/in/drummondreed/) ([Evernym/Avast](https://www.evernym.com/)) + +Authors: +: [Manu Sporny](http://manu.sporny.org/) ([Digital Bazaar](https://digitalbazaar.com/)) +: [Dave Longley](https://github.com/dlongley) ([Digital Bazaar](https://digitalbazaar.com/)) +: [Markus Sabadello](https://www.linkedin.com/in/markus-sabadello-353a0821) ([Danube Tech](https://danubetech.com/)) +: [Drummond Reed](https://www.linkedin.com/in/drummondreed/) ([Evernym/Avast](https://www.evernym.com/)) +: [Orie Steele](https://www.linkedin.com/in/or13b/) ([Transmute](https://transmute.industries/)) +: [Christopher Allen](https://www.linkedin.com/in/christophera) ([Blockchain Commons](https://www.BlockchainCommons.com)) + +Feedback: +: [GitHub w3c/did-core](https://github.com/w3c/did-core/) ([pull requests](https://github.com/w3c/did-core/pulls/), [new issue](https://github.com/w3c/did-core/issues/new/choose), [open issues](https://github.com/w3c/did-core/issues/)) +: [public-did-wg@w3.org](mailto:public-did-wg@w3.org?subject=%5Bdid-core%5D%20YOUR%20TOPIC%20HERE) with subject line \[did-core\] *... message topic ...* ([archives](https://lists.w3.org/Archives/Public/public-did-wg/)) + +Errata: +: [Errata exists](https://w3c.github.io/did-core/errata.html). + +Related Documents +: [DID Use Cases and Requirements](https://www.w3.org/TR/did-use-cases/) +: [DID Specification Registries](https://www.w3.org/TR/did-spec-registries/) +: [DID Core Implementation Report](https://w3c.github.io/did-test-suite/) + +See also [**translations**](https://www.w3.org/Translations/?technology=did-core). + +[Copyright](https://www.w3.org/Consortium/Legal/ipr-notice#Copyright) © 2022 [W3C](https://www.w3.org/)^®^ ([MIT](https://www.csail.mit.edu/), [ERCIM](https://www.ercim.eu/), [Keio](https://www.keio.ac.jp/), [Beihang](https://ev.buaa.edu.cn/)). W3C [liability](https://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer), [trademark](https://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks) and [permissive document license](https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document "W3C Software and Document Notice and License") rules apply. + +------------------------------------------------------------------------ + +## Abstract + +[Decentralized identifiers](#dfn-decentralized-identifiers) (DIDs) are a new type of identifier that enables verifiable, decentralized digital identity. A [DID](#dfn-decentralized-identifiers) refers to any subject (e.g., a person, organization, thing, data model, abstract entity, etc.) as determined by the controller of the [DID](#dfn-decentralized-identifiers). In contrast to typical, federated identifiers, [DIDs](#dfn-decentralized-identifiers) have been designed so that they may be decoupled from centralized registries, identity providers, and certificate authorities. Specifically, while other parties might be used to help enable the discovery of information related to a [DID](#dfn-decentralized-identifiers), the design enables the controller of a [DID](#dfn-decentralized-identifiers) to prove control over it without requiring permission from any other party. [DIDs](#dfn-decentralized-identifiers) are [URIs](#dfn-uri) that associate a [DID subject](#dfn-did-subjects) with a [DID document](#dfn-did-documents) allowing trustable interactions associated with that subject. + +Each [DID document](#dfn-did-documents) can express cryptographic material, [verification methods](#dfn-verification-method), or [services](#dfn-service), which provide a set of mechanisms enabling a [DID controller](#dfn-did-controllers) to prove control of the [DID](#dfn-decentralized-identifiers). [Services](#dfn-service) enable trusted interactions associated with the [DID subject](#dfn-did-subjects). A [DID](#dfn-decentralized-identifiers) might provide the means to return the [DID subject](#dfn-did-subjects) itself, if the [DID subject](#dfn-did-subjects) is an information resource such as a data model. + +This document specifies the DID syntax, a common data model, core properties, serialized representations, DID operations, and an explanation of the process of resolving DIDs to the resources that they represent. + +## Status of This Document + +*This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the [W3C technical reports index](https://www.w3.org/TR/) at https://www.w3.org/TR/.* + +At the time of publication, there existed [103 experimental DID Method specifications](https://www.w3.org/TR/did-extensions-methods/#did-methods), 32 experimental DID Method driver implementations, a [test suite](https://w3c.github.io/did-test-suite/) that determines whether or not a given implementation is conformant with this specification and 46 implementations submitted to the conformance test suite. Readers are advised to heed the [DID Core issues](https://github.com/w3c/did-core/issues) and [DID Core Test Suite issues](https://github.com/w3c/did-test-suite/issues) that each contain the latest list of concerns and proposed changes that might result in alterations to this specification. At the time of publication, no additional substantive issues, changes, or modifications are expected. + +Comments regarding this document are welcome. Please file issues directly on [GitHub](https://github.com/w3c/did-core/issues/), or send them to ( [subscribe](mailto:public-did-wg-request@w3.org?subject=subscribe), [archives](https://lists.w3.org/Archives/Public/public-did-wg/)). + +This document was published by the [Decentralized Identifier Working Group](https://www.w3.org/groups/wg/did) as a Recommendation using the [Recommendation track](https://www.w3.org/2021/Process-20211102/#recs-and-notes). + +W3C recommends the wide deployment of this specification as a standard for the Web. + +A W3C Recommendation is a specification that, after extensive consensus-building, is endorsed by W3C and its Members, and has commitments from Working Group members to [royalty-free licensing](https://www.w3.org/Consortium/Patent-Policy/#sec-Requirements) for implementations. + +This document was produced by a group operating under the [W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy/). W3C maintains a [public list of any patent disclosures](https://www.w3.org/groups/wg/did/ipr) 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)](https://www.w3.org/Consortium/Patent-Policy/#def-essential) must disclose the information in accordance with [section 6 of the W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy/#sec-Disclosure). + +This document is governed by the [2 November 2021 W3C Process Document](https://www.w3.org/2021/Process-20211102/). + +## Table of Contents + +1. [Abstract](#abstract) +2. [Status of This Document](#sotd) +3. [1. Introduction](#introduction) + 1. [1.1 A Simple Example](#a-simple-example) + 2. [1.2 Design Goals](#design-goals) + 3. [1.3 Architecture Overview](#architecture-overview) + 4. [1.4 Conformance](#conformance) +4. [2. Terminology](#terminology) +5. [3. Identifier](#identifier) + 1. [3.1 DID Syntax](#did-syntax) + 2. [3.2 DID URL Syntax](#did-url-syntax) + 1. [3.2.1 DID Parameters](#did-parameters) + 2. [3.2.2 Relative DID URLs](#relative-did-urls) +6. [4. Data Model](#data-model) + 1. [4.1 Extensibility](#extensibility) +7. [5. Core Properties](#core-properties) + 1. [5.1 Identifiers](#identifiers) + 1. [5.1.1 DID Subject](#did-subject) + 2. [5.1.2 DID Controller](#did-controller) + 3. [5.1.3 Also Known As](#also-known-as) + 2. [5.2 Verification Methods](#verification-methods) + 1. [5.2.1 Verification Material](#verification-material) + 2. [5.2.2 Referring to Verification Methods](#referring-to-verification-methods) + 3. [5.3 Verification Relationships](#verification-relationships) + 1. [5.3.1 Authentication](#authentication) + 2. [5.3.2 Assertion](#assertion) + 3. [5.3.3 Key Agreement](#key-agreement) + 4. [5.3.4 Capability Invocation](#capability-invocation) + 5. [5.3.5 Capability Delegation](#capability-delegation) + 4. [5.4 Services](#services) +8. [6. Representations](#representations) + 1. [6.1 Production and Consumption](#production-and-consumption) + 2. [6.2 JSON](#json) + 1. [6.2.1 Production](#production) + 2. [6.2.2 Consumption](#consumption) + 3. [6.3 JSON-LD](#json-ld) + 1. [6.3.1 Production](#production-0) + 2. [6.3.2 Consumption](#consumption-0) +9. [7. Resolution](#resolution) + 1. [7.1 DID Resolution](#did-resolution) + 1. [7.1.1 DID Resolution Options](#did-resolution-options) + 2. [7.1.2 DID Resolution Metadata](#did-resolution-metadata) + 3. [7.1.3 DID Document Metadata](#did-document-metadata) + 2. [7.2 DID URL Dereferencing](#did-url-dereferencing) + 1. [7.2.1 DID URL Dereferencing Options](#did-url-dereferencing-options) + 2. [7.2.2 DID URL Dereferencing Metadata](#did-url-dereferencing-metadata) + 3. [7.3 Metadata Structure](#metadata-structure) +10. [8. Methods](#methods) + 1. [8.1 Method Syntax](#method-syntax) + 2. [8.2 Method Operations](#method-operations) + 3. [8.3 Security Requirements](#security-requirements) + 4. [8.4 Privacy Requirements](#privacy-requirements) +11. [9. Security Considerations](#security-considerations) + 1. [9.1 Choosing DID Resolvers](#choosing-did-resolvers) + 2. [9.2 Proving Control and Binding](#proving-control-and-binding) + 3. [9.3 Authentication Service Endpoints](#authentication-service-endpoints) + 4. [9.4 Non-Repudiation](#non-repudiation) + 5. [9.5 Notification of DID Document Changes](#notification-of-did-document-changes) + 6. [9.6 Key and Signature Expiration](#key-and-signature-expiration) + 7. [9.7 Verification Method Rotation](#verification-method-rotation) + 8. [9.8 Verification Method Revocation](#verification-method-revocation) + 9. [9.9 DID Recovery](#did-recovery) + 10. [9.10 The Role of Human-Friendly Identifiers](#the-role-of-human-friendly-identifiers) + 11. [9.11 DIDs as Enhanced URNs](#dids-as-enhanced-urns) + 12. [9.12 Immutability](#immutability) + 13. [9.13 Encrypted Data in DID Documents](#encrypted-data-in-did-documents) + 14. [9.14 Equivalence Properties](#equivalence-properties) + 15. [9.15 Content Integrity Protection](#content-integrity-protection) + 16. [9.16 Persistence](#persistence) + 17. [9.17 Level of Assurance](#level-of-assurance) +12. [10. Privacy Considerations](#privacy-considerations) + 1. [10.1 Keep Personal Data Private](#keep-personal-data-private) + 2. [10.2 DID Correlation Risks](#did-correlation-risks) + 3. [10.3 DID Document Correlation Risks](#did-document-correlation-risks) + 4. [10.4 DID Subject Classification](#did-subject-classification) + 5. [10.5 Herd Privacy](#herd-privacy) + 6. [10.6 Service Privacy](#service-privacy) +13. [A. Examples](#examples) + 1. [A.1 DID Documents](#did-documents) + 2. [A.2 Proving](#proving) + 3. [A.3 Encrypting](#encrypting) +14. [B. Architectural Considerations](#architectural-considerations) + 1. [B.1 Detailed Architecture Diagram](#detailed-architecture-diagram) + 2. [B.2 Creation of a DID](#creation-of-a-did) + 3. [B.3 Determining the DID subject](#determining-the-did-subject) + 4. [B.4 Referring to the DID document](#referring-to-the-did-document) + 5. [B.5 Statements in the DID document](#statements-in-the-did-document) + 6. [B.6 Discovering more information about the DID subject](#discovering-more-information-about-the-did-subject) + 7. [B.7 Serving a representation of the DID subject](#serving-a-representation-of-the-did-subject) + 8. [B.8 Assigning DIDs to existing web resources](#assigning-dids-to-existing-web-resources) + 9. [B.9 The relationship between DID controllers and DID subjects](#the-relationship-between-did-controllers-and-did-subjects) + 1. [B.9.1 Set #1: The DID subject *is* the DID controller](#set-1-the-did-subject-is-the-did-controller) + 2. [B.9.2 Set #2: The DID subject is *not* the DID controller](#set-2-the-did-subject-is-not-the-did-controller) + 10. [B.10 Multiple DID controllers](#multiple-did-controllers) + 1. [B.10.1 Independent Control](#independent-control) + 2. [B.10.2 Group Control](#group-control) + 11. [B.11 Changing the DID subject](#changing-the-did-subject) + 12. [B.12 Changing the DID controller](#changing-the-did-controller) +15. [C. Revision History](#revision-history) +16. [D. Acknowledgements](#acknowledgements) +17. [E. IANA Considerations](#iana-considerations) + 1. [E.1 application/did+json](#application-did-json) + 2. [E.2 application/did+ld+json](#application-did-ld-json) +18. [F. References](#references) + 1. [F.1 Normative references](#normative-references) + 2. [F.2 Informative references](#informative-references) + +## 1. Introduction + +[](#introduction) + +*This section is non-normative.* + +As individuals and organizations, many of us use globally unique identifiers in a wide variety of contexts. They serve as communications addresses (telephone numbers, email addresses, usernames on social media), ID numbers (for passports, drivers licenses, tax IDs, health insurance), and product identifiers (serial numbers, barcodes, RFIDs). URIs (Uniform Resource Identifiers) are used for resources on the Web and each web page you view in a browser has a globally unique URL (Uniform Resource Locator). + +The vast majority of these globally unique identifiers are not under our control. They are issued by external authorities that decide who or what they refer to and when they can be revoked. They are useful only in certain contexts and recognized only by certain bodies not of our choosing. They might disappear or cease to be valid with the failure of an organization. They might unnecessarily reveal personal information. In many cases, they can be fraudulently replicated and asserted by a malicious third-party, which is more commonly known as \"identity theft\". + +The Decentralized Identifiers (DIDs) defined in this specification are a new type of globally unique identifier. They are designed to enable individuals and organizations to generate their own identifiers using systems they trust. These new identifiers enable entities to prove control over them by authenticating using cryptographic proofs such as digital signatures. + +Since the generation and assertion of Decentralized Identifiers is entity-controlled, each entity can have as many DIDs as necessary to maintain their desired separation of identities, personas, and interactions. The use of these identifiers can be scoped appropriately to different contexts. They support interactions with other people, institutions, or systems that require entities to identify themselves, or things they control, while providing control over how much personal or private data should be revealed, all without depending on a central authority to guarantee the continued existence of the identifier. These ideas are explored in the DID Use Cases document \[[DID-USE-CASES](#bib-did-use-cases "Use Cases and Requirements for Decentralized Identifiers")\]. + +This specification does not presuppose any particular technology or cryptography to underpin the generation, persistence, resolution, or interpretation of DIDs. For example, implementers can create Decentralized Identifiers based on identifiers registered in federated or centralized identity management systems. Indeed, almost all types of identifier systems can add support for DIDs. This creates an interoperability bridge between the worlds of centralized, federated, and decentralized identifiers. This also enables implementers to design specific types of DIDs to work with the computing infrastructure they trust, such as distributed ledgers, decentralized file systems, distributed databases, and peer-to-peer networks. + +This specification is for: + +- Anyone that wants to understand the core architectural principles that are the foundation for Decentralized Identifiers; +- Software developers that want to produce and consume Decentralized Identifiers and their associated data formats; +- Systems integrators that want to understand how to use Decentralized Identifiers in their software and hardware systems; +- Specification authors that want to create new DID infrastructures, known as DID methods, that conform to the ecosystem described by this document. + +In addition to this specification, readers might find the Use Cases and Requirements for Decentralized Identifiers \[[DID-USE-CASES](#bib-did-use-cases "Use Cases and Requirements for Decentralized Identifiers")\] document useful. + +### 1.1 A Simple Example + +[](#a-simple-example) + +*This section is non-normative.* + +A [DID](#dfn-decentralized-identifiers) is a simple text string consisting of three parts: 1) the `did` URI scheme identifier, 2) the identifier for the [DID method](#dfn-did-methods), and 3) the DID method-specific identifier. + +![ A diagram showing the parts of a DID. The left-most letters spell \'did\' in blue, are enclosed in a horizontal bracket from above and a label that reads \'scheme\' above the bracket. A gray colon follows the \'did\' letters. The middle letters spell \'example\' in magenta, are enclosed in a horizontal bracket from below and a label that reads \'DID Method\' below the bracket. A gray colon follows the DID Method. Finally, the letters at the end read \'123456789abcdefghi\' in green, are enclosed in a horizontal bracket from below and a label that reads \'DID Method Specific String\' below the bracket. ](diagrams/parts-of-a-did.svg) + +Figure 1 A simple example of a decentralized identifier (DID) + +The example [DID](#dfn-decentralized-identifiers) above resolves to a [DID document](#dfn-did-documents). A [DID document](#dfn-did-documents) contains information associated with the [DID](#dfn-decentralized-identifiers), such as ways to cryptographically [authenticate](#dfn-authenticated) a [DID controller](#dfn-did-controllers). + +[Example 1](#example-a-simple-did-document): A simple DID document + +``` nohighlight +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ] + "id": "did:example:123456789abcdefghi", + "authentication": [{ + // used to authenticate as did:...fghi + "id": "did:example:123456789abcdefghi#keys-1", + "type": "Ed25519VerificationKey2020", + "controller": "did:example:123456789abcdefghi", + "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + }] +} +``` + +### 1.2 Design Goals + +[](#design-goals) + +*This section is non-normative.* + +[Decentralized Identifiers](#dfn-decentralized-identifiers) are a component of larger systems, such as the Verifiable Credentials ecosystem \[[VC-DATA-MODEL](#bib-vc-data-model "Verifiable Credentials Data Model v1.1")\], which influenced the design goals for this specification. The design goals for Decentralized Identifiers are summarized here. + + Goal Description + ------------------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Decentralization Eliminate the requirement for centralized authorities or single point failure in identifier management, including the registration of globally unique identifiers, public verification keys, [services](#dfn-service), and other information. + Control Give entities, both human and non-human, the power to directly control their digital identifiers without the need to rely on external authorities. + Privacy Enable entities to control the privacy of their information, including minimal, selective, and progressive disclosure of attributes or other data. + Security Enable sufficient security for requesting parties to depend on [DID documents](#dfn-did-documents) for their required level of assurance. + Proof-based Enable [DID controllers](#dfn-did-controllers) to provide cryptographic proof when interacting with other entities. + Discoverability Make it possible for entities to discover [DIDs](#dfn-decentralized-identifiers) for other entities, to learn more about or interact with those entities. + Interoperability Use interoperable standards so [DID](#dfn-decentralized-identifiers) infrastructure can make use of existing tools and software libraries designed for interoperability. + Portability Be system- and network-independent and enable entities to use their digital identifiers with any system that supports [DIDs](#dfn-decentralized-identifiers) and [DID methods](#dfn-did-methods). + Simplicity Favor a reduced set of simple features to make the technology easier to understand, implement, and deploy. + Extensibility Where possible, enable extensibility provided it does not greatly hinder interoperability, portability, or simplicity. + +### 1.3 Architecture Overview + +[](#architecture-overview) + +*This section is non-normative.* + +This section provides a basic overview of the major components of Decentralized Identifier architecture. + +![ DIDs and DID documents are recorded on a Verifiable Data Registry; DIDs resolve to DID documents; DIDs refer to DID subjects; a DID controller controls a DID document; DID URLs contains a DID; DID URLs dereferenced to DID document fragments or external resources. ](diagrams/did_brief_architecture_overview.svg) + +Figure 2 Overview of DID architecture and the relationship of the basic components. See also: [narrative description](#brief-architecture-overview-longdesc). + +Six internally-labeled shapes appear in the diagram, with labeled arrows between them, as follows. In the center of the diagram is a rectangle labeled DID URL, containing small typewritten text \"did:example:123/path/to/rsrc\". At the center top of the diagram is a rectangle labeled, \"DID\", containing small typewritten text \"did:example:123\". At the top left of the diagram is an oval, labeled \"DID Subject\". At the bottom center of the diagram is a rectangle labeled, \"DID document\". At the bottom left is an oval, labeled, \"DID Controller\". On the center right of the diagram is a two-dimensional rendering of a cylinder, labeled, \"Verifiable Data Registry\". + +From the top of the \"DID URL\" rectangle, an arrow, labeled \"contains\", extends upwards, pointing to the \"DID\" rectangle. From the bottom of the \"DID URL\" rectangle, an arrow, labeled \"refers, and ***dereferences***, to\", extends downward, pointing to the \"DID document\" rectangle. An arrow from the \"DID\" rectangle, labeled \"***resolves*** to\", points down to the \"DID document\" rectangle. An arrow from the \"DID\" rectangle, labeled \"refers to\", points left to the \"DID subject\" oval. An arrow from the \"DID controller\" oval, labeled \"controls\", points right to the \"DID document\" rectangle. An arrow from the \"DID\" rectangle, labeled \"recorded on\", points downards to the right, to the \"Verifiable Data Registry\" cylinder. An arrow from the \"DID document\" rectangle, labeled \"recorded on\", points upwards to the right to the \"Verifiable Data Registry\" cylinder. + +DIDs and DID URLs +: A Decentralized Identifier, or [DID](#dfn-decentralized-identifiers), is a [URI](#dfn-uri) composed of three parts: the scheme `did:`, a method identifier, and a unique, method-specific identifier specified by the [DID method](#dfn-did-methods). [DIDs](#dfn-decentralized-identifiers) are resolvable to [DID documents](#dfn-did-documents). A [DID URL](#dfn-did-urls) extends the syntax of a basic [DID](#dfn-decentralized-identifiers) to incorporate other standard [URI](#dfn-uri) components such as path, query, and fragment in order to locate a particular [resource](#dfn-resources)---for example, a cryptographic public key inside a [DID document](#dfn-did-documents), or a [resource](#dfn-resources) external to the [DID document](#dfn-did-documents). These concepts are elaborated upon in [3.1 DID Syntax](#did-syntax) and [3.2 DID URL Syntax](#did-url-syntax). + +DID subjects +: The subject of a [DID](#dfn-decentralized-identifiers) is, by definition, the entity identified by the [DID](#dfn-decentralized-identifiers). The [DID subject](#dfn-did-subjects) might also be the [DID controller](#dfn-did-controllers). Anything can be the subject of a [DID](#dfn-decentralized-identifiers): person, group, organization, thing, or concept. This is further defined in [5.1.1 DID Subject](#did-subject). + +DID controllers +: The [controller](#dfn-controller) of a [DID](#dfn-decentralized-identifiers) is the entity (person, organization, or autonomous software) that has the capability---as defined by a [DID method](#dfn-did-methods)---to make changes to a [DID document](#dfn-did-documents). This capability is typically asserted by the control of a set of cryptographic keys used by software acting on behalf of the controller, though it might also be asserted via other mechanisms. Note that a [DID](#dfn-decentralized-identifiers) might have more than one controller, and the [DID subject](#dfn-did-subjects) can be the [DID controller](#dfn-did-controllers), or one of them. This concept is documented in [5.1.2 DID Controller](#did-controller). + +Verifiable data registries +: In order to be resolvable to [DID documents](#dfn-did-documents), [DIDs](#dfn-decentralized-identifiers) are typically recorded on an underlying system or network of some kind. Regardless of the specific technology used, any such system that supports recording [DIDs](#dfn-decentralized-identifiers) and returning data necessary to produce [DID documents](#dfn-did-documents) is called a [verifiable data registry](#dfn-verifiable-data-registry). Examples include [distributed ledgers](#dfn-distributed-ledger-technology), decentralized file systems, databases of any kind, peer-to-peer networks, and other forms of trusted data storage. This concept is further elaborated upon in [8. Methods](#methods). + +DID documents +: [DID documents](#dfn-did-documents) contain information associated with a [DID](#dfn-decentralized-identifiers). They typically express [verification methods](#dfn-verification-method), such as cryptographic public keys, and [services](#dfn-service) relevant to interactions with the [DID subject](#dfn-did-subjects). The generic properties supported in a [DID document](#dfn-did-documents) are specified in [5. Core Properties](#core-properties). A [DID document](#dfn-did-documents) can be serialized to a byte stream (see [6. Representations](#representations)). The properties present in a [DID document](#dfn-did-documents) can be updated according to the applicable operations outlined in [8. Methods](#methods). + +DID methods +: [DID methods](#dfn-did-methods) are the mechanism by which a particular type of [DID](#dfn-decentralized-identifiers) and its associated [DID document](#dfn-did-documents) are created, resolved, updated, and deactivated. [DID methods](#dfn-did-methods) are defined using separate DID method specifications as defined in [8. Methods](#methods). + +DID resolvers and DID resolution +: A [DID resolver](#dfn-did-resolvers) is a system component that takes a [DID](#dfn-decentralized-identifiers) as input and produces a conforming [DID document](#dfn-did-documents) as output. This process is called [DID resolution](#dfn-did-resolution). The steps for resolving a specific type of [DID](#dfn-decentralized-identifiers) are defined by the relevant [DID method](#dfn-did-methods) specification. The process of [DID resolution](#dfn-did-resolution) is elaborated upon in [7. Resolution](#resolution). + +DID URL dereferencers and DID URL dereferencing +: A [DID URL dereferencer](#dfn-did-url-dereferencers) is a system component that takes a [DID URL](#dfn-did-urls) as input and produces a [resource](#dfn-resources) as output. This process is called [DID URL dereferencing](#dfn-did-url-dereferencing). The process of [DID URL dereferencing](#dfn-did-url-dereferencing) is elaborated upon in [7.2 DID URL Dereferencing](#did-url-dereferencing). + +### 1.4 Conformance + +[](#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*, *OPTIONAL*, *RECOMMENDED*, *REQUIRED*, *SHOULD*, and *SHOULD NOT* in this document are to be interpreted as described in [BCP 14](https://datatracker.ietf.org/doc/html/bcp14) \[[RFC2119](#bib-rfc2119 "Key words for use in RFCs to Indicate Requirement Levels")\] \[[RFC8174](#bib-rfc8174 "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words")\] when, and only when, they appear in all capitals, as shown here. + +This document contains examples that contain JSON and JSON-LD content. Some of these examples contain characters that are invalid, such as inline comments (`//`) and the use of ellipsis (`...`) to denote information that adds little value to the example. Implementers are cautioned to remove this content if they desire to use the information as valid JSON or JSON-LD. + +Some examples contain terms, both property names and values, that are not defined in this specification. These are indicated with a comment (`// external (property name|value)`). Such terms, when used in a [DID document](#dfn-did-documents), are expected to be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\] with links to both a formal definition and a JSON-LD context. + +Interoperability of implementations for [DIDs](#dfn-decentralized-identifiers) and [DID documents](#dfn-did-documents) is tested by evaluating an implementation\'s ability to create and parse [DIDs](#dfn-decentralized-identifiers) and [DID documents](#dfn-did-documents) that conform to this specification. Interoperability for producers and consumers of [DIDs](#dfn-decentralized-identifiers) and [DID documents](#dfn-did-documents) is provided by ensuring the [DIDs](#dfn-decentralized-identifiers) and [DID documents](#dfn-did-documents) conform. Interoperability for [DID method](#dfn-did-methods) specifications is provided by the details in each [DID method](#dfn-did-methods) specification. It is understood that, in the same way that a web browser is not required to implement all known [URI](#dfn-uri) schemes, conformant software that works with [DIDs](#dfn-decentralized-identifiers) is not required to implement all known [DID methods](#dfn-did-methods). However, all implementations of a given [DID method](#dfn-did-methods) are expected to be interoperable for that method. + +A conforming DID is any concrete expression of the rules specified in [3. Identifier](#identifier) which complies with relevant normative statements in that section. + +A conforming DID document is any concrete expression of the data model described in this specification which complies with the relevant normative statements in [4. Data Model](#data-model) and [5. Core Properties](#core-properties). A serialization format for the conforming document is deterministic, bi-directional, and lossless, as described in [6. Representations](#representations). + +A conforming producer is any algorithm realized as software and/or hardware that generates [conforming DIDs](#dfn-conforming-did) or [conforming DID Documents](#dfn-conforming-did-document) and complies with the relevant normative statements in [6. Representations](#representations). + +A conforming consumer is any algorithm realized as software and/or hardware that consumes [conforming DIDs](#dfn-conforming-did) or [conforming DID documents](#dfn-conforming-did-document) and complies with the relevant normative statements in [6. Representations](#representations). + +A conforming DID resolver is any algorithm realized as software and/or hardware that complies with the relevant normative statements in [7.1 DID Resolution](#did-resolution). + +A conforming DID URL dereferencer is any algorithm realized as software and/or hardware that complies with the relevant normative statements in [7.2 DID URL Dereferencing](#did-url-dereferencing). + +A conforming DID method is any specification that complies with the relevant normative statements in [8. Methods](#methods). + +## 2. Terminology + +[](#terminology) + +*This section is non-normative.* + +This section defines the terms used in this specification and throughout [decentralized identifier](#dfn-decentralized-identifiers) infrastructure. A link to these terms is included whenever they appear in this specification. + +amplification attack +: A class of attack where the attacker attempts to exhaust a target system\'s CPU, storage, network, or other resources by providing small, valid inputs into the system that result in damaging effects that can be exponentially more costly to process than the inputs themselves. + +authenticate +: Authentication is a process by which an entity can prove it has a specific attribute or controls a specific secret using one or more [verification methods](#dfn-verification-method). With [DIDs](#dfn-decentralized-identifiers), a common example would be proving control of the cryptographic private key associated with a public key published in a [DID document](#dfn-did-documents). + +cryptographic suite +: A specification defining the usage of specific cryptographic primitives in order to achieve a particular security goal. These documents are often used to specify [verification methods](#dfn-verification-method), digital signature types, their identifiers, and other related properties. + +decentralized identifier (DID) +: A globally unique persistent identifier that does not require a centralized registration authority and is often generated and/or registered cryptographically. The generic format of a DID is defined in [3.1 DID Syntax](#did-syntax). A specific [DID scheme](#dfn-did-schemes) is defined in a [DID method](#dfn-did-methods) specification. Many---but not all---DID methods make use of [distributed ledger technology](#dfn-distributed-ledger-technology) (DLT) or some other form of decentralized network. + +decentralized identity management +: [Identity management](https://en.wikipedia.org/wiki/Identity_management) that is based on the use of [decentralized identifiers](#dfn-decentralized-identifiers). Decentralized identity management extends authority for identifier generation, registration, and assignment beyond traditional roots of trust such as [X.500 directory services](https://en.wikipedia.org/wiki/X.500), the [Domain Name System](https://en.wikipedia.org/wiki/Domain_Name_System), and most national ID systems. + +DID controller +: An entity that has the capability to make changes to a [DID document](#dfn-did-documents). A [DID](#dfn-decentralized-identifiers) might have more than one DID controller. The DID controller(s) can be denoted by the optional `controller` property at the top level of the [DID document](#dfn-did-documents). Note that a DID controller might be the [DID subject](#dfn-did-subjects). + +DID delegate +: An entity to whom a [DID controller](#dfn-did-controllers) has granted permission to use a [verification method](#dfn-verification-method) associated with a [DID](#dfn-decentralized-identifiers) via a [DID document](#dfn-did-documents). For example, a parent who controls a child\'s [DID document](#dfn-did-documents) might permit the child to use their personal device in order to [authenticate](#dfn-authenticated). In this case, the child is the [DID delegate](#dfn-did-delegate). The child\'s personal device would contain the private cryptographic material enabling the child to [authenticate](#dfn-authenticated) using the [DID](#dfn-decentralized-identifiers). However, the child might not be permitted to add other personal devices without the parent\'s permission. + +DID document +: A set of data describing the [DID subject](#dfn-did-subjects), including mechanisms, such as cryptographic public keys, that the [DID subject](#dfn-did-subjects) or a [DID delegate](#dfn-did-delegate) can use to [authenticate](#dfn-authenticated) itself and prove its association with the [DID](#dfn-decentralized-identifiers). A DID document might have one or more different [representations](#dfn-representations) as defined in [6. Representations](#representations) or in the W3C DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. + +DID fragment +: The portion of a [DID URL](#dfn-did-urls) that follows the first hash sign character (`#`). DID fragment syntax is identical to URI fragment syntax. + +DID method +: A definition of how a specific [DID method scheme](#dfn-did-schemes) is implemented. A DID method is defined by a DID method specification, which specifies the precise operations by which [DIDs](#dfn-decentralized-identifiers) and [DID documents](#dfn-did-documents) are created, resolved, updated, and deactivated. See [8. Methods](#methods). + +DID path +: The portion of a [DID URL](#dfn-did-urls) that begins with and includes the first forward slash (`/`) character and ends with either a question mark (`?`) character, a fragment hash sign (`#`) character, or the end of the [DID URL](#dfn-did-urls). DID path syntax is identical to URI path syntax. See [Path](#path). + +DID query +: The portion of a [DID URL](#dfn-did-urls) that follows and includes the first question mark character (`?`). DID query syntax is identical to URI query syntax. See [Query](#query). + +DID resolution +: The process that takes as its input a [DID](#dfn-decentralized-identifiers) and a set of resolution options and returns a [DID document](#dfn-did-documents) in a conforming [representation](#dfn-representations) plus additional metadata. This process relies on the \"Read\" operation of the applicable [DID method](#dfn-did-methods). The inputs and outputs of this process are defined in [7.1 DID Resolution](#did-resolution). + +DID resolver +: A [DID resolver](#dfn-did-resolvers) is a software and/or hardware component that performs the [DID resolution](#dfn-did-resolution) function by taking a [DID](#dfn-decentralized-identifiers) as input and producing a conforming [DID document](#dfn-did-documents) as output. + +DID scheme +: The formal syntax of a [decentralized identifier](#dfn-decentralized-identifiers). The generic DID scheme begins with the prefix `did:` as defined in [3.1 DID Syntax](#did-syntax). Each [DID method](#dfn-did-methods) specification defines a specific DID method scheme that works with that specific [DID method](#dfn-did-methods). In a specific DID method scheme, the DID method name follows the first colon and terminates with the second colon, e.g., `did:example:` + +DID subject +: The entity identified by a [DID](#dfn-decentralized-identifiers) and described by a [DID document](#dfn-did-documents). Anything can be a DID subject: person, group, organization, physical thing, digital thing, logical thing, etc. + +DID URL +: A [DID](#dfn-decentralized-identifiers) plus any additional syntactic component that conforms to the definition in [3.2 DID URL Syntax](#did-url-syntax). This includes an optional [DID path](#dfn-did-paths) (with its leading `/` character), optional [DID query](#dfn-did-queries) (with its leading `?` character), and optional [DID fragment](#dfn-did-fragments) (with its leading `#` character). + +DID URL dereferencing +: The process that takes as its input a [DID URL](#dfn-did-urls) and a set of input metadata, and returns a [resource](#dfn-resources). This resource might be a [DID document](#dfn-did-documents) plus additional metadata, a secondary resource contained within the [DID document](#dfn-did-documents), or a resource entirely external to the [DID document](#dfn-did-documents). The process uses [DID resolution](#dfn-did-resolution) to fetch a [DID document](#dfn-did-documents) indicated by the [DID](#dfn-decentralized-identifiers) contained within the [DID URL](#dfn-did-urls). The dereferencing process can then perform additional processing on the [DID document](#dfn-did-documents) to return the dereferenced resource indicated by the [DID URL](#dfn-did-urls). The inputs and outputs of this process are defined in [7.2 DID URL Dereferencing](#did-url-dereferencing). + +DID URL dereferencer +: A software and/or hardware system that performs the [DID URL dereferencing](#dfn-did-url-dereferencing) function for a given [DID URL](#dfn-did-urls) or [DID document](#dfn-did-documents). + +distributed ledger (DLT) +: A non-centralized system for recording events. These systems establish sufficient confidence for participants to rely upon the data recorded by others to make operational decisions. They typically use distributed databases where different nodes use a consensus protocol to confirm the ordering of cryptographically signed transactions. The linking of digitally signed transactions over time often makes the history of the ledger effectively immutable. + +public key description +: A data object contained inside a [DID document](#dfn-did-documents) that contains all the metadata necessary to use a public key or a verification key. + +resource +: As defined by \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]: \"\...the term \'resource\' is used in a general sense for whatever might be identified by a URI.\" Similarly, any resource might serve as a [DID subject](#dfn-did-subjects) identified by a [DID](#dfn-decentralized-identifiers). + +representation +: As defined for HTTP by \[[RFC7231](#bib-rfc7231 "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content")\]: \"information that is intended to reflect a past, current, or desired state of a given resource, in a format that can be readily communicated via the protocol, and that consists of a set of representation metadata and a potentially unbounded stream of representation data.\" A [DID document](#dfn-did-documents) is a representation of information describing a [DID subject](#dfn-did-subjects). See [6. Representations](#representations). + +representation-specific entries +: Entries in a [DID document](#dfn-did-documents) whose meaning is particular to a specific [representation](#dfn-representations). Defined in [4. Data Model](#data-model) and [6. Representations](#representations). For example, [`@context`](#dfn-context) in the [JSON-LD representation](#json-ld) is a *representation-specific entry*. + +services +: Means of communicating or interacting with the [DID subject](#dfn-did-subjects) or associated entities via one or more [service endpoints](#dfn-service-endpoints). Examples include discovery services, agent services, social networking services, file storage services, and verifiable credential repository services. + +service endpoint +: A network address, such as an HTTP URL, at which [services](#dfn-service) operate on behalf of a [DID subject](#dfn-did-subjects). + +Uniform Resource Identifier (URI) +: The standard identifier format for all resources on the World Wide Web as defined by \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]. A [DID](#dfn-decentralized-identifiers) is a type of URI scheme. + +verifiable credential +: A standard data model and representation format for cryptographically-verifiable digital credentials as defined by the W3C Verifiable Credentials specification \[[VC-DATA-MODEL](#bib-vc-data-model "Verifiable Credentials Data Model v1.1")\]. + + verifiable data registry +: A system that facilitates the creation, verification, updating, and/or deactivation of [decentralized identifiers](#dfn-decentralized-identifiers) and [DID documents](#dfn-did-documents). A verifiable data registry might also be used for other cryptographically-verifiable data structures such as [verifiable credentials](#dfn-verifiable-credentials). For more information, see the W3C Verifiable Credentials specification \[[VC-DATA-MODEL](#bib-vc-data-model "Verifiable Credentials Data Model v1.1")\]. + +verifiable timestamp +: A verifiable timestamp enables a third-party to verify that a data object existed at a specific moment in time and that it has not been modified or corrupted since that moment in time. If the data integrity could reasonably have been modified or corrupted since that moment in time, the timestamp is not verifiable. + +verification method + +: A set of parameters that can be used together with a process to independently verify a proof. For example, a cryptographic public key can be used as a verification method with respect to a digital signature; in such usage, it verifies that the signer possessed the associated cryptographic private key. + + \"Verification\" and \"proof\" in this definition are intended to apply broadly. For example, a cryptographic public key might be used during Diffie-Hellman key exchange to negotiate a shared symmetric key for encryption. This guarantees the integrity of the key agreement process. It is thus another type of verification method, even though descriptions of the process might not use the words \"verification\" or \"proof.\" + +verification relationship + +: An expression of the relationship between the [DID subject](#dfn-did-subjects) and a [verification method](#dfn-verification-method). An example of a verification relationship is [5.3.1 Authentication](#authentication). + +Universally Unique Identifier (UUID) +: A type of globally unique identifier defined by \[[RFC4122](#bib-rfc4122 "A Universally Unique IDentifier (UUID) URN Namespace")\]. UUIDs are similar to DIDs in that they do not require a centralized registration authority. UUIDs differ from DIDs in that they are not resolvable or cryptographically-verifiable. + +In addition to the terminology above, this specification also uses terminology from the \[[INFRA](#bib-infra "Infra Standard")\] specification to formally define the [data model](#data-model). When \[[INFRA](#bib-infra "Infra Standard")\] terminology is used, such as [string](https://infra.spec.whatwg.org/#strings), [set](https://infra.spec.whatwg.org/#ordered-set), and [map](https://infra.spec.whatwg.org/#maps), it is linked directly to that specification. + +## 3. Identifier + +[](#identifier) + +This section describes the formal syntax for [DIDs](#dfn-decentralized-identifiers) and [DID URLs](#dfn-did-urls). The term \"generic\" is used to differentiate the syntax defined here from syntax defined by *specific* [DID methods](#dfn-did-methods) in their respective specifications. The creation processes, and their timing, for [DIDs](#dfn-decentralized-identifiers) and [DID URLs](#dfn-did-urls) are described in [8.2 Method Operations](#method-operations) and [B.2 Creation of a DID](#creation-of-a-did). + +### 3.1 DID Syntax + +[](#did-syntax) + +The generic [DID scheme](#dfn-did-schemes) is a [URI](#dfn-uri) scheme conformant with \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]. The ABNF definition can be found below, which uses the syntax in \[[RFC5234](#bib-rfc5234 "Augmented BNF for Syntax Specifications: ABNF")\] and the corresponding definitions for `ALPHA` and `DIGIT`. All other rule names not defined in the ABNF below are defined in \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]. All [DIDs](#dfn-decentralized-identifiers) *MUST* conform to the DID Syntax ABNF Rules. + ++-----------------------------------------------------------------------+ +| The DID Syntax ABNF Rules | ++=======================================================================+ +| ``` nohighlight | +| did = "did:" method-name ":" method-specific-id | +| method-name = 1*method-char | +| method-char = %x61-7A / DIGIT | +| method-specific-id = *( *idchar ":" ) 1*idchar | +| idchar = ALPHA / DIGIT / "." / "-" / "_" / pct-encoded | +| pct-encoded = "%" HEXDIG HEXDIG | +| ``` | ++-----------------------------------------------------------------------+ + +For requirements on [DID methods](#dfn-did-methods) relating to the [DID](#dfn-decentralized-identifiers) syntax, see Section [8.1 Method Syntax](#method-syntax). + +### 3.2 DID URL Syntax + +[](#did-url-syntax) + +A [DID URL](#dfn-did-urls) is a network location identifier for a specific [resource](#dfn-resources). It can be used to retrieve things like representations of [DID subjects](#dfn-did-subjects), [verification methods](#dfn-verification-method), [services](#dfn-service), specific parts of a [DID document](#dfn-did-documents), or other resources. + +The following is the ABNF definition using the syntax in \[[RFC5234](#bib-rfc5234 "Augmented BNF for Syntax Specifications: ABNF")\]. It builds on the `did` scheme defined in [3.1 DID Syntax](#did-syntax). The [`path-abempty`](https://www.rfc-editor.org/rfc/rfc3986#section-3.3), [`query`](https://www.rfc-editor.org/rfc/rfc3986#section-3.4), and [`fragment`](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) components are defined in \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]. All [DID URLs](#dfn-did-urls) *MUST* conform to the DID URL Syntax ABNF Rules. [DID methods](#dfn-did-methods) can further restrict these rules, as described in [8.1 Method Syntax](#method-syntax). + ++-----------------------------------------------------------------------+ +| The DID URL Syntax ABNF Rules | ++=======================================================================+ +| ``` nohighlight | +| did-url = did path-abempty [ "?" query ] [ "#" fragment ] | +| ``` | ++-----------------------------------------------------------------------+ + +Note: Semicolon character is reserved for future use + +Although the semicolon (`;`) character can be used according to the rules of the [DID URL](#dfn-did-urls) syntax, future versions of this specification may use it as a sub-delimiter for parameters as described in \[[MATRIX-URIS](#bib-matrix-uris "Matrix URIs - Ideas about Web Architecture")\]. To avoid future conflicts, developers ought to refrain from using it. + +#### Path + +[](#path) + +A [DID path](#dfn-did-paths) is identical to a generic [URI](#dfn-uri) path and conforms to the `path-abempty` ABNF rule in [RFC 3986, section 3.3](https://www.rfc-editor.org/rfc/rfc3986#section-3.3). As with [URIs](#dfn-uri), path semantics can be specified by [DID Methods](#dfn-did-methods), which in turn might enable [DID controllers](#dfn-did-controllers) to further specialize those semantics. + +[Example 2](#example-2) + +``` nohighlight +did:example:123456/path +``` + +#### Query + +[](#query) + +A [DID query](#dfn-did-queries) is identical to a generic [URI](#dfn-uri) query and conforms to the `query` ABNF rule in [RFC 3986, section 3.4](https://www.rfc-editor.org/rfc/rfc3986#section-3.4). This syntax feature is elaborated upon in [3.2.1 DID Parameters](#did-parameters). + +[Example 3](#example-3) + +``` nohighlight +did:example:123456?versionId=1 +``` + +#### Fragment + +[](#fragment) + +[DID fragment](#dfn-did-fragments) syntax and semantics are identical to a generic [URI](#dfn-uri) fragment and conforms to the `fragment` ABNF rule in [RFC 3986, section 3.5](https://www.rfc-editor.org/rfc/rfc3986#section-3.5). + +A [DID fragment](#dfn-did-fragments) is used as a method-independent reference into a [DID document](#dfn-did-documents) or external [resource](#dfn-resources). Some examples of DID fragment identifiers are shown below. + +[Example 4](#example-a-unique-verification-method-in-a-did-document): A unique verification method in a DID Document + +``` nohighlight +did:example:123#public-key-0 +``` + +[Example 5](#example-a-unique-service-in-a-did-document): A unique service in a DID Document + +``` nohighlight +did:example:123#agent +``` + +[Example 6](#example-a-resource-external-to-a-did-document): A resource external to a DID Document + +``` nohighlight +did:example:123?service=agent&relativeRef=/credentials#degree +``` + +Note: Fragment semantics across representations + +In order to maximize interoperability, implementers are urged to ensure that [DID fragments](#dfn-did-fragments) are interpreted in the same way across [representations](#dfn-representations) (see [6. Representations](#representations)). For example, while JSON Pointer \[[RFC6901](#bib-rfc6901 "JavaScript Object Notation (JSON) Pointer")\] can be used in a [DID fragment](#dfn-did-fragments), it will not be interpreted in the same way across non-JSON [representations](#dfn-representations). + +Additional semantics for fragment identifiers, which are compatible with and layered upon the semantics in this section, are described for JSON-LD representations in [E.2 application/did+ld+json](#application-did-ld-json). For information about how to dereference a [DID fragment](#dfn-did-fragments), see [7.2 DID URL Dereferencing](#did-url-dereferencing). + +#### 3.2.1 DID Parameters + +[](#did-parameters) + +The [DID URL](#dfn-did-urls) syntax supports a simple format for parameters based on the `query` component described in [Query](#query). Adding a DID parameter to a [DID URL](#dfn-did-urls) means that the parameter becomes part of the identifier for a [resource](#dfn-resources). + +[Example 7](#example-a-did-url-with-a-versiontime-did-parameter): A DID URL with a \'versionTime\' DID parameter + +``` nohighlight +did:example:123?versionTime=2021-05-10T17:00:00Z +``` + +[Example 8](#example-a-did-url-with-a-service-and-a-relativeref-did-parameter): A DID URL with a \'service\' and a \'relativeRef\' DID parameter + +``` nohighlight +did:example:123?service=files&relativeRef=/resume.pdf +``` + +Some DID parameters are completely independent of of any specific [DID method](#dfn-did-methods) and function the same way for all [DIDs](#dfn-decentralized-identifiers). Other DID parameters are not supported by all [DID methods](#dfn-did-methods). Where optional parameters are supported, they are expected to operate uniformly across the [DID methods](#dfn-did-methods) that do support them. The following table provides common DID parameters that function the same way across all [DID methods](#dfn-did-methods). Support for all [DID Parameters](#did-parameters) is *OPTIONAL*. + +Note + +It is generally expected that DID URL dereferencer implementations will reference \[[DID-RESOLUTION](#bib-did-resolution "Decentralized Identifier Resolution")\] for additional implementation details. The scope of this specification only defines the contract of the most common query parameters. + + Parameter Name Description + --------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + [`service`](#dfn-service) Identifies a service from the [DID document](#dfn-did-documents) by service ID. If present, the associated value *MUST* be an [ASCII string](https://infra.spec.whatwg.org/#ascii-string). + `relativeRef` A relative [URI](#dfn-uri) reference according to [RFC3986 Section 4.2](https://www.rfc-editor.org/rfc/rfc3986#section-4.2) that identifies a [resource](#dfn-resources) at a [service endpoint](#dfn-service-endpoints), which is selected from a [DID document](#dfn-did-documents) by using the `service` parameter. If present, the associated value *MUST* be an [ASCII string](https://infra.spec.whatwg.org/#ascii-string) and *MUST* use percent-encoding for certain characters as specified in [RFC3986 Section 2.1](https://www.rfc-editor.org/rfc/rfc3986#section-2.1). + `versionId` Identifies a specific version of a [DID document](#dfn-did-documents) to be resolved (the version ID could be sequential, or a [UUID](#dfn-uuid), or method-specific). If present, the associated value *MUST* be an [ASCII string](https://infra.spec.whatwg.org/#ascii-string). + `versionTime` Identifies a certain version timestamp of a [DID document](#dfn-did-documents) to be resolved. That is, the [DID document](#dfn-did-documents) that was valid for a [DID](#dfn-decentralized-identifiers) at a certain time. If present, the associated value *MUST* be an [ASCII string](https://infra.spec.whatwg.org/#ascii-string) which is a valid XML datetime value, as defined in section 3.3.7 of [W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes](https://www.w3.org/TR/xmlschema11-2/) \[[XMLSCHEMA11-2](#bib-xmlschema11-2 "W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes")\]. This datetime value *MUST* be normalized to UTC 00:00:00 and without sub-second decimal precision. For example: `2020-12-20T19:17:47Z`. + `hl` A resource hash of the [DID document](#dfn-did-documents) to add integrity protection, as specified in \[[HASHLINK](#bib-hashlink "Cryptographic Hyperlinks")\]. This parameter is non-normative. If present, the associated value *MUST* be an [ASCII string](https://infra.spec.whatwg.org/#ascii-string). + +Implementers as well as [DID method](#dfn-did-methods) specification authors might use additional DID parameters that are not listed here. For maximum interoperability, it is *RECOMMENDED* that DID parameters use the DID Specification Registries mechanism \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\], to avoid collision with other uses of the same DID parameter with different semantics. + +DID parameters might be used if there is a clear use case where the parameter needs to be part of a [URL](https://url.spec.whatwg.org/#concept-url) that references a [resource](#dfn-resources) with more precision than using the [DID](#dfn-decentralized-identifiers) alone. It is expected that DID parameters are *not* used if the same functionality can be expressed by passing input metadata to a [DID resolver](#dfn-did-resolvers). Additional considerations for processing these parameters are discussed in \[[DID-RESOLUTION](#bib-did-resolution "Decentralized Identifier Resolution")\]. + +Note: DID parameters and DID resolution + +The [DID resolution](#dfn-did-resolution) and the [DID URL dereferencing](#dfn-did-url-dereferencing) functions can be influenced by passing input metadata to a [DID resolver](#dfn-did-resolvers) that are not part of the [DID URL](#dfn-did-urls) (see [7.1.1 DID Resolution Options](#did-resolution-options)). This is comparable to HTTP, where certain parameters could either be included in an HTTP URL, or alternatively passed as HTTP headers during the dereferencing process. The important distinction is that DID parameters that are part of the [DID URL](#dfn-did-urls) should be used to specify *what [resource](#dfn-resources) is being identified*, whereas input metadata that is not part of the [DID URL](#dfn-did-urls) should be use to control *how that [resource](#dfn-resources) is resolved or dereferenced*. + +#### 3.2.2 Relative DID URLs + +[](#relative-did-urls) + +A relative [DID URL](#dfn-did-urls) is any URL value in a [DID document](#dfn-did-documents) that does not start with `did::`. More specifically, it is any URL value that does not start with the ABNF defined in [3.1 DID Syntax](#did-syntax). The URL is expected to reference a [resource](#dfn-resources) in the same [DID document](#dfn-did-documents). Relative [DID URLs](#dfn-did-urls) *MAY* contain relative path components, query parameters, and fragment identifiers. + +When resolving a relative [DID URL](#dfn-did-urls) reference, the algorithm specified in [RFC3986 Section 5: Reference Resolution](https://www.rfc-editor.org/rfc/rfc3986#section-5) *MUST* be used. The **base URI** value is the [DID](#dfn-decentralized-identifiers) that is associated with the [DID subject](#dfn-did-subjects), see [5.1.1 DID Subject](#did-subject). The **scheme** is `did`. The **authority** is a combination of `:`, and the **path**, **query**, and **fragment** values are those defined in [Path](#path), [Query](#query), and [Fragment](#fragment), respectively. + +Relative [DID URLs](#dfn-did-urls) are often used to reference [verification methods](#dfn-verification-method) and [services](#dfn-service) in a [DID Document](#dfn-did-documents) without having to use absolute URLs. [DID methods](#dfn-did-methods) where storage size is a consideration might use relative URLs to reduce the storage size of [DID documents](#dfn-did-documents). + +[Example 9](#example-an-example-of-a-relative-did-url): An example of a relative DID URL + +``` nohighlight +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ] + "id": "did:example:123456789abcdefghi", + "verificationMethod": [{ + "id": "did:example:123456789abcdefghi#key-1", + "type": "Ed25519VerificationKey2020", // external (property value) + "controller": "did:example:123456789abcdefghi", + "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + }, ...], + "authentication": [ + // a relative DID URL used to reference a verification method above + "#key-1" + ] +} +``` + +In the example above, the relative [DID URL](#dfn-did-urls) value will be transformed to an absolute [DID URL](#dfn-did-urls) value of `did:example:123456789abcdefghi#key-1`. + +## 4. Data Model + +[](#data-model) + +This specification defines a data model that can be used to express [DID documents](#dfn-did-documents) and DID document data structures, which can then be serialized into multiple concrete [representations](#dfn-representations). This section provides a high-level description of the data model, descriptions of the ways different types of properties are expressed in the data model, and instructions for extending the data model. + +A [DID document](#dfn-did-documents) consists of a [map](https://infra.spec.whatwg.org/#maps) of [entries](https://infra.spec.whatwg.org/#map-entry), where each entry consists of a key/value pair. The [DID document](#dfn-did-documents) data model contains at least two different classes of entries. The first class of entries is called properties, and is specified in section [5. Core Properties](#core-properties). The second class is made up of [representation-specific entries](#dfn-representation-specific-entry), and is specified in section [6. Representations](#representations). + +![ Diagram illustrating the entries in the DID document, including properties and representation-specific entries; some entries are defined by this specification; others are defined by registered or unregistered extensions.](diagrams/diagram-did-document-entries.svg) + +Figure 3 The entries in a DID document. See also: [narrative description](#did-document-entries-longdesc). + +The diagram is titled, \"Entries in the DID Document map\". A dotted grey line runs horizontally through the center of the diagram. The space above the line is labeled \"Properties\", and the space below it, \"Representation-specific entries\". Six labeled rectangles appear in the diagram, three lying above the dotted grey line and three below it. A large green rectangle, labeled \"DID Specification Registries\", encloses the four leftmost rectangles (upper left, upper center, lower left, and lower center). The two leftmost rectangles (upper left and lower left) are outlined in blue and labeled in blue, as follows. The upper left rectangle is labeled \"Core Properties\", and contains text \"id, alsoKnownAs, controller, authentication, verificationMethod, service, serviceEndpoint, \...\". The lower left rectangle is labeled \"Core Representation-specific Entries\", and contains text \"@context\". The four rightmost rectangles (upper center, upper right, lower center, and lower right) are outlined in grey and labeled in black, as follows. The upper center rectangle is labeled, \"Property Extensions\", and contains text \"ethereumAddress\". The lower center rectangle is labeled, \"Representation-specific Entry Extensions\", and contains no other text. The upper right rectangle is labeled, \"Unregistered Property Extensions\", and contains text \"foo\". The lower right rectangle is labeled \"Unregistered Representation-specific Entry Extensions\", and contains text \"%YAML, xmlns\". + +All entry keys in the [DID document](#dfn-did-documents) data model are [strings](https://infra.spec.whatwg.org/#strings). All entry values are expressed using one of the abstract data types in the table below, and each [representation](#dfn-representations) specifies the concrete serialization format of each data type. + + Data Type Considerations + --------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + [map](https://infra.spec.whatwg.org/#maps) A finite ordered sequence of key/value pairs, with no key appearing twice as specified in \[[INFRA](#bib-infra "Infra Standard")\]. A map is sometimes referred to as an [ordered map](https://infra.spec.whatwg.org/#maps) in \[[INFRA](#bib-infra "Infra Standard")\]. + [list](https://infra.spec.whatwg.org/#list) A finite ordered sequence of items as specified in \[[INFRA](#bib-infra "Infra Standard")\]. + [set](https://infra.spec.whatwg.org/#ordered-set) A finite ordered sequence of items that does not contain the same item twice as specified in \[[INFRA](#bib-infra "Infra Standard")\]. A set is sometimes referred to as an [ordered set](https://infra.spec.whatwg.org/#ordered-set) in \[[INFRA](#bib-infra "Infra Standard")\]. + datetime A date and time value that is capable of losslessly expressing all values expressible by a `dateTime` as specified in \[[XMLSCHEMA11-2](https://www.w3.org/TR/xmlschema11-2/#dateTime)\]. + [string](https://infra.spec.whatwg.org/#string) A sequence of code units often used to represent human readable language as specified in \[[INFRA](#bib-infra "Infra Standard")\]. + integer A real number without a fractional component as specified in \[[XMLSCHEMA11-2](https://www.w3.org/TR/xmlschema11-2/#decimal)\]. To maximize interoperability, implementers are urged to heed the advice regarding integers in [RFC8259, Section 6: Numbers](https://www.rfc-editor.org/rfc/rfc8259#section-6). + double A value that is often used to approximate arbitrary real numbers as specified in \[[XMLSCHEMA11-2](https://www.w3.org/TR/xmlschema11-2/#double)\]. To maximize interoperability, implementers are urged to heed the advice regarding doubles in [RFC8259, Section 6: Numbers](https://www.rfc-editor.org/rfc/rfc8259#section-6). + [boolean](https://infra.spec.whatwg.org/#boolean) A value that is either true or false as defined in \[[INFRA](#bib-infra "Infra Standard")\]. + [null](https://infra.spec.whatwg.org/#nulls) A value that is used to indicate the lack of a value as defined in \[[INFRA](#bib-infra "Infra Standard")\]. + +As a result of the [data model](#data-model) being defined using terminology from \[[INFRA](#bib-infra "Infra Standard")\], property values which can contain more than one item, such as [lists](https://infra.spec.whatwg.org/#list), [maps](https://infra.spec.whatwg.org/#ordered-map) and [sets](https://infra.spec.whatwg.org/#ordered-set), are explicitly ordered. All list-like value structures in \[[INFRA](#bib-infra "Infra Standard")\] are ordered, whether or not that order is significant. For the purposes of this specification, unless otherwise stated, [map](https://infra.spec.whatwg.org/#ordered-map) and [set](https://infra.spec.whatwg.org/#ordered-set) ordering is not important and implementations are not expected to produce or consume deterministically ordered values. + +### 4.1 Extensibility + +[](#extensibility) + +The data model supports two types of extensibility. + +1. For maximum interoperability, it is *RECOMMENDED* that extensions use the W3C DID Specification Registries mechanism \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. The use of this mechanism for new properties or other extensions is the only specified mechanism that ensures that two different [representations](#dfn-representations) will be able to work together. +2. [Representations](#dfn-representations) *MAY* define other extensibility mechanisms, including ones that do not require the use of the DID Specification Registries. Such extension mechanisms *SHOULD* support lossless conversion into any other conformant [representation](#dfn-representations). Extension mechanisms for a [representation](#dfn-representations) *SHOULD* define a mapping of all properties and [representation](#dfn-representations) syntax into the [data model](#data-model) and its type system. + +Note: Unregistered extensions are less reliable + +It is always possible for two specific implementations to agree out-of-band to use a mutually understood extension or [representation](#dfn-representations) that is not recorded in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]; interoperability between such implementations and the larger ecosystem will be less reliable. + +## 5. Core Properties + +[](#core-properties) + +A [DID](#dfn-decentralized-identifiers) is associated with a [DID document](#dfn-did-documents). [DID documents](#dfn-did-documents) are expressed using the [data model](#data-model) and can be serialized into a [representation](#representations). The following sections define the properties in a [DID document](#dfn-did-documents), including whether these properties are required or optional. These properties describe relationships between the [DID subject](#dfn-did-subjects) and the value of the property. + +The following tables contain informative references for the core properties defined by this specification, with expected values, and whether or not they are required. The property names in the tables are linked to the normative definitions and more detailed descriptions of each property. + +Note: Property names used in maps of different types + +The property names `id`, `type`, and `controller` can be present in maps of different types with possible differences in constraints. + +### DID Document properties + +[](#did-document-properties) + + Property Required? Value constraints + ----------------------------------------------------- ----------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + [`id`](#dfn-id) yes A [string](https://infra.spec.whatwg.org/#string) that conforms to the rules in [3.1 DID Syntax](#did-syntax). + [`alsoKnownAs`](#dfn-alsoknownas) no A [set](https://infra.spec.whatwg.org/#ordered-set) of [strings](https://infra.spec.whatwg.org/#string) that conform to the rules of \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\] for [URIs](#dfn-uri). + [`controller`](#dfn-controller) no A [string](https://infra.spec.whatwg.org/#string) or a [set](https://infra.spec.whatwg.org/#ordered-set) of [strings](https://infra.spec.whatwg.org/#string) that conform to the rules in [3.1 DID Syntax](#did-syntax). + [`verificationMethod`](#dfn-verificationmethod) no A [set](https://infra.spec.whatwg.org/#ordered-set) of [Verification Method](#dfn-verification-method) [maps](https://infra.spec.whatwg.org/#ordered-map) that conform to the rules in [Verification Method properties](#verification-method-properties). + [`authentication`](#dfn-authentication) no A [set](https://infra.spec.whatwg.org/#ordered-set) of either [Verification Method](#dfn-verification-method) [maps](https://infra.spec.whatwg.org/#ordered-map) that conform to the rules in [Verification Method properties](#verification-method-properties)) or [strings](https://infra.spec.whatwg.org/#string) that conform to the rules in [3.2 DID URL Syntax](#did-url-syntax). + [`assertionMethod`](#dfn-assertionmethod) no + [`keyAgreement`](#dfn-keyagreement) no + [`capabilityInvocation`](#dfn-capabilityinvocation) no + [`capabilityDelegation`](#dfn-capabilitydelegation) no + [`service`](#dfn-service) no A [set](https://infra.spec.whatwg.org/#ordered-set) of [Service Endpoint](#dfn-service-endpoints) [maps](https://infra.spec.whatwg.org/#ordered-map) that conform to the rules in [Service properties](#service-properties). + +### Verification Method properties + +[](#verification-method-properties) + + Property Required? Value constraints + ------------------------------------------------- ----------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + `id` yes A [string](https://infra.spec.whatwg.org/#string) that conforms to the rules in [3.2 DID URL Syntax](#did-url-syntax). + [`controller`](#dfn-controller) yes A [string](https://infra.spec.whatwg.org/#string) that conforms to the rules in [3.1 DID Syntax](#did-syntax). + `type` yes A [string](https://infra.spec.whatwg.org/#string). + [`publicKeyJwk`](#dfn-publickeyjwk) no A [map](https://infra.spec.whatwg.org/#maps) representing a JSON Web Key that conforms to \[[RFC7517](#bib-rfc7517 "JSON Web Key (JWK)")\]. See [definition of publicKeyJwk](#dfn-publickeyjwk) for additional constraints. + [`publicKeyMultibase`](#dfn-publickeymultibase) no A [string](https://infra.spec.whatwg.org/#string) that conforms to a \[[MULTIBASE](#bib-multibase "The Multibase Encoding Scheme")\] encoded public key. + +### Service properties + +[](#service-properties) + + Property Required? Value constraints + ------------------------------------------- ----------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + `id` yes A [string](https://infra.spec.whatwg.org/#string) that conforms to the rules of \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\] for [URIs](#dfn-uri). + `type` yes A [string](https://infra.spec.whatwg.org/#string) or a [set](https://infra.spec.whatwg.org/#ordered-set) of [strings](https://infra.spec.whatwg.org/#string). + [`serviceEndpoint`](#dfn-serviceendpoint) yes A [string](https://infra.spec.whatwg.org/#string) that conforms to the rules of \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\] for [URIs](#dfn-uri), a [map](https://infra.spec.whatwg.org/#string), or a [set](https://infra.spec.whatwg.org/#ordered-set) composed of a one or more [strings](https://infra.spec.whatwg.org/#string) that conform to the rules of \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\] for [URIs](#dfn-uri) and/or [maps](https://infra.spec.whatwg.org/#string). + +### 5.1 Identifiers + +[](#identifiers) + +This section describes the mechanisms by which [DID documents](#dfn-did-documents) include identifiers for [DID subjects](#dfn-did-subjects) and [DID controllers](#dfn-did-controllers). + +#### 5.1.1 DID Subject + +[](#did-subject) + +The [DID](#dfn-decentralized-identifiers) for a particular [DID subject](#dfn-did-subjects) is expressed using the [`id`](#dfn-id) property in the [DID document](#dfn-did-documents). + +id +: The value of `id` *MUST* be a [string](https://infra.spec.whatwg.org/#string) that conforms to the rules in [3.1 DID Syntax](#did-syntax) and *MUST* exist in the root [map](https://infra.spec.whatwg.org/#ordered-map) of the [data model](#data-model) for the [DID document](#dfn-did-documents). + +[Example 10](#example-10) + +``` nohighlight +{ + "id": "did:example:123456789abcdefghijk" +} +``` + +The `id` property only denotes the [DID](#dfn-decentralized-identifiers) of the [DID subject](#dfn-did-subjects) when it is present in the *topmost* [map](https://infra.spec.whatwg.org/#ordered-map) of the [DID document](#dfn-did-documents). + +Note: Intermediate representations + +[DID method](#dfn-did-methods) specifications can create intermediate representations of a [DID document](#dfn-did-documents) that do not contain the [`id`](#dfn-id) property, such as when a [DID resolver](#dfn-did-resolvers) is performing [DID resolution](#dfn-did-resolution). However, the fully resolved [DID document](#dfn-did-documents) always contains a valid [`id`](#dfn-id) property. + +#### 5.1.2 DID Controller + +[](#did-controller) + +A [DID controller](#dfn-did-controllers) is an entity that is authorized to make changes to a [DID document](#dfn-did-documents). The process of authorizing a [DID controller](#dfn-did-controllers) is defined by the [DID method](#dfn-did-methods). + +controller +: The `controller` property is *OPTIONAL*. If present, the value *MUST* be a [string](https://infra.spec.whatwg.org/#string) or a [set](https://infra.spec.whatwg.org/#ordered-set) of [strings](https://infra.spec.whatwg.org/#string) that conform to the rules in [3.1 DID Syntax](#did-syntax). The corresponding [DID document](#dfn-did-documents)(s) *SHOULD* contain [verification relationships](#dfn-verification-relationship) that explicitly permit the use of certain [verification methods](#dfn-verification-method) for specific purposes. + +When a [`controller`](#dfn-controller) property is present in a [DID document](#dfn-did-documents), its value expresses one or more [DIDs](#dfn-decentralized-identifiers). Any [verification methods](#dfn-verification-method) contained in the [DID documents](#dfn-did-documents) for those [DIDs](#dfn-decentralized-identifiers) *SHOULD* be accepted as authoritative, such that proofs that satisfy those [verification methods](#dfn-verification-method) are to be considered equivalent to proofs provided by the [DID subject](#dfn-did-subjects). + +[Example 11](#example-did-document-with-a-controller-property): DID document with a controller property + +``` nohighlight +{ + "@context": "https://www.w3.org/ns/did/v1", + "id": "did:example:123456789abcdefghi", + "controller": "did:example:bcehfew7h32f32h7af3", +} +``` + +Note: Authorization vs authentication + +Note that authorization provided by the value of `controller` is separate from authentication as described in [5.3.1 Authentication](#authentication). This is particularly important for key recovery in the case of cryptographic key loss, where the [DID subject](#dfn-did-subjects) no longer has access to their keys, or key compromise, where the [DID controller](#dfn-did-controllers)\'s trusted third parties need to override malicious activity by an attacker. See [9. Security Considerations](#security-considerations) for information related to threat models and attack vectors. + +#### 5.1.3 Also Known As + +[](#also-known-as) + +A [DID subject](#dfn-did-subjects) can have multiple identifiers for different purposes, or at different times. The assertion that two or more [DIDs](#dfn-decentralized-identifiers) (or other types of [URI](#dfn-uri)) refer to the same [DID subject](#dfn-did-subjects) can be made using the [`alsoKnownAs`](#dfn-alsoknownas) property. + +alsoKnownAs +: The `alsoKnownAs` property is *OPTIONAL*. If present, the value *MUST* be a [set](https://infra.spec.whatwg.org/#ordered-set) where each item in the set is a [URI](#dfn-uri) conforming to \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]. +: This relationship is a statement that the subject of this identifier is also identified by one or more other identifiers. + +Note: Equivalence and alsoKnownAs + +Applications might choose to consider two identifiers related by [`alsoKnownAs`](#dfn-alsoknownas) to be equivalent *if* the [`alsoKnownAs`](#dfn-alsoknownas) relationship is reciprocated in the reverse direction. It is best practice *not* to consider them equivalent in the absence of this inverse relationship. In other words, the presence of an [`alsoKnownAs`](#dfn-alsoknownas) assertion does not prove that this assertion is true. Therefore, it is strongly advised that a requesting party obtain independent verification of an `alsoKnownAs` assertion. + +Given that the [DID subject](#dfn-did-subjects) might use different identifiers for different purposes, an expectation of strong equivalence between the two identifiers, or merging the information of the two corresponding [DID documents](#dfn-did-documents), is not necessarily appropriate, *even with* a reciprocal relationship. + +### 5.2 Verification Methods + +[](#verification-methods) + +A [DID document](#dfn-did-documents) can express [verification methods](#dfn-verification-method), such as cryptographic public keys, which can be used to [authenticate](#dfn-authenticated) or authorize interactions with the [DID subject](#dfn-did-subjects) or associated parties. For example, a cryptographic public key can be used as a [verification method](#dfn-verification-method) with respect to a digital signature; in such usage, it verifies that the signer could use the associated cryptographic private key. [Verification methods](#dfn-verification-method) might take many parameters. An example of this is a set of five cryptographic keys from which any three are required to contribute to a cryptographic threshold signature. + +verificationMethod + +: The `verificationMethod` property is *OPTIONAL*. If present, the value *MUST* be a [set](https://infra.spec.whatwg.org/#ordered-set) of [verification methods](#dfn-verification-method), where each [verification method](#dfn-verification-method) is expressed using a [map](https://infra.spec.whatwg.org/#ordered-map). The [verification method](#dfn-verification-method) [map](https://infra.spec.whatwg.org/#ordered-map) *MUST* include the `id`, `type`, `controller`, and specific verification material properties that are determined by the value of `type` and are defined in [5.2.1 Verification Material](#verification-material). A [verification method](#dfn-verification-method) *MAY* include additional properties. [Verification methods](#dfn-verification-method) *SHOULD* be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. + + id + + : The value of the [`id`](#dfn-id) property for a [verification method](#dfn-verification-method) *MUST* be a [string](https://infra.spec.whatwg.org/#string) that conforms to the rules in Section [3.2 DID URL Syntax](#did-url-syntax). + + type + : The value of the `type` property *MUST* be a [string](https://infra.spec.whatwg.org/#string) that references exactly one [verification method](#dfn-verification-method) type. In order to maximize global interoperability, the [verification method](#dfn-verification-method) type *SHOULD* be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. + + controller + : The value of the `controller` property *MUST* be a [string](https://infra.spec.whatwg.org/#string) that conforms to the rules in [3.1 DID Syntax](#did-syntax). + +[Example 12](#example-example-verification-method-structure): Example verification method structure + +``` {aria-busy="false"} +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + "https://w3id.org/security/suites/ed25519-2020/v1" + ] + "id": "did:example:123456789abcdefghi", + ... + "verificationMethod": [{ + "id": ..., + "type": ..., + "controller": ..., + "publicKeyJwk": ... + }, { + "id": ..., + "type": ..., + "controller": ..., + "publicKeyMultibase": ... + }] +} +``` + +Note: Verification method controller(s) and DID controller(s) + +The semantics of the `controller` property are the same when the subject of the relationship is the [DID document](#dfn-did-documents) as when the subject of the relationship is a [verification method](#dfn-verification-method), such as a cryptographic public key. Since a key can\'t control itself, and the key controller cannot be inferred from the [DID document](#dfn-did-documents), it is necessary to explicitly express the identity of the controller of the key. The difference is that the value of `controller` for a [verification method](#dfn-verification-method) is *not* necessarily a [DID controller](#dfn-did-controllers). [DID controllers](#dfn-did-controllers) are expressed using the [`controller`](#dfn-controller) property at the highest level of the [DID document](#dfn-did-documents) (the topmost [map](https://infra.spec.whatwg.org/#ordered-map) in the [data model](#data-model)); see [5.1.2 DID Controller](#did-controller). + +#### 5.2.1 Verification Material + +[](#verification-material) + +Verification material is any information that is used by a process that applies a [verification method](#dfn-verification-method). The `type` of a [verification method](#dfn-verification-method) is expected to be used to determine its compatibility with such processes. Examples of verification material properties are [`publicKeyJwk`](#dfn-publickeyjwk) or [`publicKeyMultibase`](#dfn-publickeymultibase). A [cryptographic suite](#dfn-cryptosuite) specification is responsible for specifying the [verification method](#dfn-verification-method) `type` and its associated verification material. For example, see [JSON Web Signature 2020](https://w3c-ccg.github.io/lds-jws2020/) and [Ed25519 Signature 2020](https://w3c-ccg.github.io/lds-ed25519-2020/). For all registered [verification method](#dfn-verification-method) types and associated verification material available for [DIDs](#dfn-decentralized-identifiers), please see the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. + +To increase the likelihood of interoperable implementations, this specification limits the number of formats for expressing verification material in a [DID document](#dfn-did-documents). The fewer formats that implementers have to implement, the more likely it will be that they will support all of them. This approach attempts to strike a delicate balance between ease of implementation and supporting formats that have historically had broad deployment. Two supported verification material properties are listed below: + +publicKeyJwk + +: The `publicKeyJwk` property is *OPTIONAL*. If present, the value *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map) representing a JSON Web Key that conforms to \[[RFC7517](#bib-rfc7517 "JSON Web Key (JWK)")\]. The [map](https://infra.spec.whatwg.org/#ordered-map) *MUST NOT* contain \"d\", or any other members of the private information class as described in [Registration Template](https://tools.ietf.org/html/rfc7517#section-8.1.1). It is *RECOMMENDED* that verification methods that use JWKs \[[RFC7517](#bib-rfc7517 "JSON Web Key (JWK)")\] to represent their public keys use the value of `kid` as their [fragment identifier](#fragment). It is *RECOMMENDED* that JWK `kid` values are set to the public key fingerprint \[[RFC7638](#bib-rfc7638 "JSON Web Key (JWK) Thumbprint")\]. See the first key in [Example 13](#example-various-verification-method-types) for an example of a public key with a compound key identifier. + +publicKeyMultibase + +: The `publicKeyMultibase` property is *OPTIONAL*. This feature is non-normative. If present, the value *MUST* be a [string](https://infra.spec.whatwg.org/#string) representation of a \[[MULTIBASE](#bib-multibase "The Multibase Encoding Scheme")\] encoded public key. + + Note that the \[[MULTIBASE](#bib-multibase "The Multibase Encoding Scheme")\] specification is not yet a standard and is subject to change. There might be some use cases for this data format where **`public`**`KeyMultibase` is defined, to allow for expression of public keys, but **`private`**`KeyMultibase` is not defined, to protect against accidental leakage of secret keys. + +A [verification method](#dfn-verification-method) *MUST NOT* contain multiple verification material properties for the same material. For example, expressing key material in a [verification method](#dfn-verification-method) using both `publicKeyJwk` and `publicKeyMultibase` at the same time is prohibited. + +An example of a [DID document](#dfn-did-documents) containing [verification methods](#dfn-verification-method) using both properties above is shown below. + +[Example 13](#example-various-verification-method-types): Verification methods using publicKeyJwk and publicKeyMultibase + +``` nohighlight +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ] + "id": "did:example:123456789abcdefghi", + ... + "verificationMethod": [{ + "id": "did:example:123#_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A", + "type": "JsonWebKey2020", // external (property value) + "controller": "did:example:123", + "publicKeyJwk": { + "crv": "Ed25519", // external (property name) + "x": "VCpo2LMLhn6iWku8MKvSLg2ZAoC-nlOyPVQaO3FxVeQ", // external (property name) + "kty": "OKP", // external (property name) + "kid": "_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A" // external (property name) + } + }, { + "id": "did:example:123456789abcdefghi#keys-1", + "type": "Ed25519VerificationKey2020", // external (property value) + "controller": "did:example:pqrstuvwxyz0987654321", + "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + }], + ... +} +``` + +#### 5.2.2 Referring to Verification Methods + +[](#referring-to-verification-methods) + +[Verification methods](#dfn-verification-method) can be embedded in or referenced from properties associated with various [verification relationships](#dfn-verification-relationship) as described in [5.3 Verification Relationships](#verification-relationships). Referencing [verification methods](#dfn-verification-method) allows them to be used by more than one [verification relationship](#dfn-verification-relationship). + +If the value of a [verification method](#dfn-verification-method) property is a [map](https://infra.spec.whatwg.org/#ordered-map), the [verification method](#dfn-verification-method) has been embedded and its properties can be accessed directly. However, if the value is a URL [string](https://infra.spec.whatwg.org/#string), the [verification method](#dfn-verification-method) has been included by reference and its properties will need to be retrieved from elsewhere in the [DID document](#dfn-did-documents) or from another [DID document](#dfn-did-documents). This is done by dereferencing the URL and searching the resulting [resource](#dfn-resources) for a [verification method](#dfn-verification-method) [map](https://infra.spec.whatwg.org/#ordered-map) with an `id` property whose value matches the URL. + +[Example 14](#example-embedding-and-referencing-verification-methods): Embedding and referencing verification methods + +``` nohighlight +{ +... + + "authentication": [ + // this key is referenced and might be used by + // more than one verification relationship + "did:example:123456789abcdefghi#keys-1", + // this key is embedded and may *only* be used for authentication + { + "id": "did:example:123456789abcdefghi#keys-2", + "type": "Ed25519VerificationKey2020", // external (property value) + "controller": "did:example:123456789abcdefghi", + "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + } + ], + +... +} +``` + +### 5.3 Verification Relationships + +[](#verification-relationships) + +A [verification relationship](#dfn-verification-relationship) expresses the relationship between the [DID subject](#dfn-did-subjects) and a [verification method](#dfn-verification-method). + +Different [verification relationships](#dfn-verification-relationship) enable the associated [verification methods](#dfn-verification-method) to be used for different purposes. It is up to a *verifier* to ascertain the validity of a verification attempt by checking that the [verification method](#dfn-verification-method) used is contained in the appropriate [verification relationship](#dfn-verification-relationship) property of the [DID Document](#dfn-did-documents). + +The [verification relationship](#dfn-verification-relationship) between the [DID subject](#dfn-did-subjects) and the [verification method](#dfn-verification-method) is explicit in the [DID document](#dfn-did-documents). [Verification methods](#dfn-verification-method) that are not associated with a particular [verification relationship](#dfn-verification-relationship) cannot be used for that [verification relationship](#dfn-verification-relationship). For example, a [verification method](#dfn-verification-method) in the value of the [`authentication`](#dfn-authentication) property cannot be used to engage in key agreement protocols with the [DID subject](#dfn-did-subjects)---the value of the [`keyAgreement`](#dfn-keyagreement) property needs to be used for that. + +The [DID document](#dfn-did-documents) does not express revoked keys using a [verification relationship](#dfn-verification-relationship). If a referenced verification method is not in the latest [DID Document](#dfn-did-documents) used to dereference it, then that verification method is considered invalid or revoked. Each [DID method](#dfn-did-methods) specification is expected to detail how revocation is performed and tracked. + +The following sections define several useful [verification relationships](#dfn-verification-relationship). A [DID document](#dfn-did-documents) *MAY* include any of these, or other properties, to express a specific [verification relationship](#dfn-verification-relationship). In order to maximize global interoperability, any such properties used *SHOULD* be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. + +#### 5.3.1 Authentication + +[](#authentication) + +The `authentication` [verification relationship](#dfn-verification-relationship) is used to specify how the [DID subject](#dfn-did-subjects) is expected to be [authenticated](#dfn-authenticated), for purposes such as logging into a website or engaging in any sort of challenge-response protocol. + +authentication +: The `authentication` property is *OPTIONAL*. If present, the associated value *MUST* be a [set](https://infra.spec.whatwg.org/#ordered-set) of one or more [verification methods](#dfn-verification-method). Each [verification method](#dfn-verification-method) *MAY* be embedded or referenced. + +[Example 15](#example-authentication-property-containing-three-verification-methods): Authentication property containing three verification methods + +``` nohighlight +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ], + "id": "did:example:123456789abcdefghi", + ... + "authentication": [ + // this method can be used to authenticate as did:...fghi + "did:example:123456789abcdefghi#keys-1", + // this method is *only* approved for authentication, it may not + // be used for any other proof purpose, so its full description is + // embedded here rather than using only a reference + { + "id": "did:example:123456789abcdefghi#keys-2", + "type": "Ed25519VerificationKey2020", + "controller": "did:example:123456789abcdefghi", + "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + } + ], + ... +} +``` + +If authentication is established, it is up to the [DID method](#dfn-did-methods) or other application to decide what to do with that information. A particular [DID method](#dfn-did-methods) could decide that authenticating as a [DID controller](#dfn-did-controllers) is sufficient to, for example, update or delete the [DID document](#dfn-did-documents). Another [DID method](#dfn-did-methods) could require different keys, or a different [verification method](#dfn-verification-method) entirely, to be presented in order to update or delete the [DID document](#dfn-did-documents) than that used to [authenticate](#dfn-authenticated). In other words, what is done *after* the authentication check is out of scope for the [data model](#data-model); [DID methods](#dfn-did-methods) and applications are expected to define this themselves. + +This is useful to any *authentication verifier* that needs to check to see if an entity that is attempting to [authenticate](#dfn-authenticated) is, in fact, presenting a valid proof of authentication. When a *verifier* receives some data (in some protocol-specific format) that contains a proof that was made for the purpose of \"authentication\", and that says that an entity is identified by the [DID](#dfn-decentralized-identifiers), then that *verifier* checks to ensure that the proof can be verified using a [verification method](#dfn-verification-method) (e.g., public key) listed under [`authentication`](#dfn-authentication) in the [DID Document](#dfn-did-documents). + +Note that the [verification method](#dfn-verification-method) indicated by the [`authentication`](#dfn-authentication) property of a [DID document](#dfn-did-documents) can only be used to [authenticate](#dfn-authenticated) the [DID subject](#dfn-did-subjects). To [authenticate](#dfn-authenticated) a different [DID controller](#dfn-did-controllers), the entity associated with the value of `controller`, as defined in [5.1.2 DID Controller](#did-controller), needs to [authenticate](#dfn-authenticated) with its *own* [DID document](#dfn-did-documents) and associated [`authentication`](#dfn-authentication) [verification relationship](#dfn-verification-relationship). + +#### 5.3.2 Assertion + +[](#assertion) + +The `assertionMethod` [verification relationship](#dfn-verification-relationship) is used to specify how the [DID subject](#dfn-did-subjects) is expected to express claims, such as for the purposes of issuing a Verifiable Credential \[[VC-DATA-MODEL](#bib-vc-data-model "Verifiable Credentials Data Model v1.1")\]. + +assertionMethod +: The `assertionMethod` property is *OPTIONAL*. If present, the associated value *MUST* be a [set](https://infra.spec.whatwg.org/#ordered-set) of one or more [verification methods](#dfn-verification-method). Each [verification method](#dfn-verification-method) *MAY* be embedded or referenced. + +This property is useful, for example, during the processing of a [verifiable credential](#dfn-verifiable-credentials) by a verifier. During verification, a verifier checks to see if a [verifiable credential](#dfn-verifiable-credentials) contains a proof created by the [DID subject](#dfn-did-subjects) by checking that the [verification method](#dfn-verification-method) used to assert the proof is associated with the [`assertionMethod`](#dfn-assertionmethod) property in the corresponding [DID document](#dfn-did-documents). + +[Example 16](#example-assertion-method-property-containing-two-verification-methods): Assertion method property containing two verification methods + +``` nohighlight +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ], + "id": "did:example:123456789abcdefghi", + ... + "assertionMethod": [ + // this method can be used to assert statements as did:...fghi + "did:example:123456789abcdefghi#keys-1", + // this method is *only* approved for assertion of statements, it is not + // used for any other verification relationship, so its full description is + // embedded here rather than using a reference + { + "id": "did:example:123456789abcdefghi#keys-2", + "type": "Ed25519VerificationKey2020", // external (property value) + "controller": "did:example:123456789abcdefghi", + "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + } + ], + ... +} +``` + +#### 5.3.3 Key Agreement + +[](#key-agreement) + +The `keyAgreement` [verification relationship](#dfn-verification-relationship) is used to specify how an entity can generate encryption material in order to transmit confidential information intended for the [DID subject](#dfn-did-subjects), such as for the purposes of establishing a secure communication channel with the recipient. + +keyAgreement +: The `keyAgreement` property is *OPTIONAL*. If present, the associated value *MUST* be a [set](https://infra.spec.whatwg.org/#ordered-set) of one or more [verification methods](#dfn-verification-method). Each [verification method](#dfn-verification-method) *MAY* be embedded or referenced. + +An example of when this property is useful is when encrypting a message intended for the [DID subject](#dfn-did-subjects). In this case, the counterparty uses the cryptographic public key information in the [verification method](#dfn-verification-method) to wrap a decryption key for the recipient. + +[Example 17](#example-key-agreement-property-containing-two-verification-methods): Key agreement property containing two verification methods + +``` nohighlight +{ + "@context": "https://www.w3.org/ns/did/v1", + "id": "did:example:123456789abcdefghi", + ... + "keyAgreement": [ + // this method can be used to perform key agreement as did:...fghi + "did:example:123456789abcdefghi#keys-1", + // this method is *only* approved for key agreement usage, it will not + // be used for any other verification relationship, so its full description is + // embedded here rather than using only a reference + { + "id": "did:example:123#zC9ByQ8aJs8vrNXyDhPHHNNMSHPcaSgNpjjsBYpMMjsTdS", + "type": "X25519KeyAgreementKey2019", // external (property value) + "controller": "did:example:123", + "publicKeyMultibase": "z9hFgmPVfmBZwRvFEyniQDBkz9LmV7gDEqytWyGZLmDXE" + } + ], + ... +} +``` + +#### 5.3.4 Capability Invocation + +[](#capability-invocation) + +The `capabilityInvocation` [verification relationship](#dfn-verification-relationship) is used to specify a [verification method](#dfn-verification-method) that might be used by the [DID subject](#dfn-did-subjects) to invoke a cryptographic capability, such as the authorization to update the [DID Document](#dfn-did-documents). + +capabilityInvocation +: The `capabilityInvocation` property is *OPTIONAL*. If present, the associated value *MUST* be a [set](https://infra.spec.whatwg.org/#ordered-set) of one or more [verification methods](#dfn-verification-method). Each [verification method](#dfn-verification-method) *MAY* be embedded or referenced. + +An example of when this property is useful is when a [DID subject](#dfn-did-subjects) needs to access a protected HTTP API that requires authorization in order to use it. In order to authorize when using the HTTP API, the [DID subject](#dfn-did-subjects) uses a capability that is associated with a particular URL that is exposed via the HTTP API. The invocation of the capability could be expressed in a number of ways, e.g., as a digitally signed message that is placed into the HTTP Headers. + +The server providing the HTTP API is the *verifier* of the capability and it would need to verify that the [verification method](#dfn-verification-method) referred to by the invoked capability exists in the [`capabilityInvocation`](#dfn-capabilityinvocation) property of the [DID document](#dfn-did-documents). The verifier would also check to make sure that the action being performed is valid and the capability is appropriate for the resource being accessed. If the verification is successful, the server has cryptographically determined that the invoker is authorized to access the protected resource. + +[Example 18](#example-capability-invocation-property-containing-two-verification-methods): Capability invocation property containing two verification methods + +``` nohighlight +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ], + "id": "did:example:123456789abcdefghi", + ... + "capabilityInvocation": [ + // this method can be used to invoke capabilities as did:...fghi + "did:example:123456789abcdefghi#keys-1", + // this method is *only* approved for capability invocation usage, it will not + // be used for any other verification relationship, so its full description is + // embedded here rather than using only a reference + { + "id": "did:example:123456789abcdefghi#keys-2", + "type": "Ed25519VerificationKey2020", // external (property value) + "controller": "did:example:123456789abcdefghi", + "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + } + ], + ... +} +``` + +#### 5.3.5 Capability Delegation + +[](#capability-delegation) + +The `capabilityDelegation` [verification relationship](#dfn-verification-relationship) is used to specify a mechanism that might be used by the [DID subject](#dfn-did-subjects) to delegate a cryptographic capability to another party, such as delegating the authority to access a specific HTTP API to a subordinate. + +capabilityDelegation +: The `capabilityDelegation` property is *OPTIONAL*. If present, the associated value *MUST* be a [set](https://infra.spec.whatwg.org/#ordered-set) of one or more [verification methods](#dfn-verification-method). Each [verification method](#dfn-verification-method) *MAY* be embedded or referenced. + +An example of when this property is useful is when a [DID controller](#dfn-did-controllers) chooses to delegate their capability to access a protected HTTP API to a party other than themselves. In order to delegate the capability, the [DID subject](#dfn-did-subjects) would use a [verification method](#dfn-verification-method) associated with the `capabilityDelegation` [verification relationship](#dfn-verification-relationship) to cryptographically sign the capability over to another [DID subject](#dfn-did-subjects). The delegate would then use the capability in a manner that is similar to the example described in [5.3.4 Capability Invocation](#capability-invocation). + +[Example 19](#example-capability-delegation-property-containing-two-verification-methods): Capability Delegation property containing two verification methods + +``` nohighlight +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ], + "id": "did:example:123456789abcdefghi", + ... + "capabilityDelegation": [ + // this method can be used to perform capability delegation as did:...fghi + "did:example:123456789abcdefghi#keys-1", + // this method is *only* approved for granting capabilities; it will not + // be used for any other verification relationship, so its full description is + // embedded here rather than using only a reference + { + "id": "did:example:123456789abcdefghi#keys-2", + "type": "Ed25519VerificationKey2020", // external (property value) + "controller": "did:example:123456789abcdefghi", + "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + } + ], + ... +} +``` + +### 5.4 Services + +[](#services) + +[Services](#dfn-service) are used in [DID documents](#dfn-did-documents) to express ways of communicating with the [DID subject](#dfn-did-subjects) or associated entities. A [service](#dfn-service) can be any type of service the [DID subject](#dfn-did-subjects) wants to advertise, including [decentralized identity management](#dfn-decentralized-identity-management) services for further discovery, authentication, authorization, or interaction. + +Due to privacy concerns, revealing public information through [services](#dfn-service), such as social media accounts, personal websites, and email addresses, is discouraged. Further exploration of privacy concerns can be found in [10.1 Keep Personal Data Private](#keep-personal-data-private) and [10.6 Service Privacy](#service-privacy). The information associated with [services](#dfn-service) is often service specific. For example, the information associated with an encrypted messaging service can express how to initiate the encrypted link before messaging begins. + +[Services](#dfn-service) are expressed using the [`service`](#dfn-service) property, which is described below: + +service + +: The `service` property is *OPTIONAL*. If present, the associated value *MUST* be a [set](https://infra.spec.whatwg.org/#ordered-set) of [services](#dfn-service), where each service is described by a [map](https://infra.spec.whatwg.org/#ordered-map). Each [service](#dfn-service) [map](https://infra.spec.whatwg.org/#ordered-map) *MUST* contain [`id`](#dfn-id), `type`, and [`serviceEndpoint`](#dfn-serviceendpoint) properties. Each service extension *MAY* include additional properties and *MAY* further restrict the properties associated with the extension. + + id + : The value of the `id` property *MUST* be a [URI](#dfn-uri) conforming to \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]. A [conforming producer](#dfn-conforming-producer) *MUST NOT* produce multiple `service` entries with the same `id`. A [conforming consumer](#dfn-conforming-consumer) *MUST* produce an error if it detects multiple `service` entries with the same `id`. + + type + : The value of the `type` property *MUST* be a [string](https://infra.spec.whatwg.org/#string) or a [set](https://infra.spec.whatwg.org/#ordered-set) of [strings](https://infra.spec.whatwg.org/#string). In order to maximize interoperability, the [service](#dfn-service) type and its associated properties *SHOULD* be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. + + serviceEndpoint + : The value of the `serviceEndpoint` property *MUST* be a [string](https://infra.spec.whatwg.org/#string), a [map](https://infra.spec.whatwg.org/#string), or a [set](https://infra.spec.whatwg.org/#ordered-set) composed of one or more [strings](https://infra.spec.whatwg.org/#string) and/or [maps](https://infra.spec.whatwg.org/#string). All [string](https://infra.spec.whatwg.org/#string) values *MUST* be valid [URIs](#dfn-uri) conforming to \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\] and normalized according to the [Normalization and Comparison rules in RFC3986](https://www.rfc-editor.org/rfc/rfc3986#section-6) and to any normalization rules in its applicable [URI](#dfn-uri) scheme specification. + +For more information regarding privacy and security considerations related to [services](#dfn-service) see [10.6 Service Privacy](#service-privacy), [10.1 Keep Personal Data Private](#keep-personal-data-private), [10.3 DID Document Correlation Risks](#did-document-correlation-risks), and [9.3 Authentication Service Endpoints](#authentication-service-endpoints). + +[Example 20](#example-usage-of-the-service-property): Usage of the service property + +``` nohighlight +{ + "service": [{ + "id":"did:example:123#linked-domain", + "type": "LinkedDomains", // external (property value) + "serviceEndpoint": "https://bar.example.com" + }] +} +``` + +## 6. Representations + +[](#representations) + +A concrete serialization of a [DID document](#dfn-did-documents) in this specification is called a [representation](#dfn-representations). A [representation](#dfn-representations) is created by serializing the [data model](#data-model) through a process called production. A [representation](#dfn-representations) is transformed into the [data model](#data-model) through a process called consumption. The *production* and *consumption* processes enable the conversion of information from one [representation](#dfn-representations) to another. This specification defines [representations](#dfn-representations) for JSON and JSON-LD, and developers can use any other [representation](#dfn-representations), such as XML or YAML, that is capable of expressing the [data model](#data-model). The following sections define the general rules for [production](#dfn-production) and [consumption](#dfn-consumption), as well as the JSON and JSON-LD [representations](#dfn-representations). + +### 6.1 Production and Consumption + +[](#production-and-consumption) + +In addition to the [representations](#dfn-representations) defined in this specification, implementers can use other [representations](#dfn-representations), providing each such [representation](#dfn-representations) is properly specified (including rules for interoperable handling of properties not listed in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]). See [4.1 Extensibility](#extensibility) for more information. + +The requirements for all [representations](#dfn-representations) are as follows: + +1. A [representation](#dfn-representations) *MUST* define deterministic production and consumption rules for all data types specified in [4. Data Model](#data-model). +2. A [representation](#dfn-representations) *MUST* be uniquely associated with an IANA-registered Media Type. +3. A [representation](#dfn-representations) *MUST* define fragment processing rules for its Media Type that are conformant with the fragment processing rules defined in [Fragment](#fragment). +4. A [representation](#dfn-representations) *SHOULD* use the lexical representation of [data model](#data-model) data types. For example, JSON and JSON-LD use the XML Schema `dateTime` lexical serialization to represent [datetimes](#dfn-datetime). A [representation](#dfn-representations) *MAY* choose to serialize the [data model](#data-model) data types using a different lexical serializations as long as the [consumption](#dfn-consumption) process back into the [data model](#data-model) is lossless. For example, some CBOR-based [representations](#dfn-representations) express [datetime](#dfn-datetime) values using integers to represent the number of seconds since the Unix epoch. +5. A [representation](#dfn-representations) *MAY* define [representation-specific entries](#dfn-representation-specific-entry) that are stored in a [representation-specific entries](#dfn-representation-specific-entry) [map](https://infra.spec.whatwg.org/#maps) for use during the [production](#dfn-production) and [consumption](#dfn-consumption) process. These entries are used when consuming or producing to aid in ensuring lossless conversion. +6. In order to maximize interoperability, [representation](#dfn-representations) specification authors *SHOULD* register their [representation](#dfn-representations) in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. + +The requirements for all [conforming producers](#dfn-conforming-producer) are as follows: + +1. A [conforming producer](#dfn-conforming-producer) *MUST* take a [DID document](#dfn-did-documents) [data model](#data-model) and a [representation-specific entries](#dfn-representation-specific-entry) [map](https://infra.spec.whatwg.org/#maps) as input into the [production](#dfn-production) process. The [conforming producer](#dfn-conforming-producer) *MAY* accept additional options as input into the [production](#dfn-production) process. +2. A [conforming producer](#dfn-conforming-producer) *MUST* serialize all entries in the [DID document](#dfn-did-documents) [data model](#data-model), and the [representation-specific entries](#dfn-representation-specific-entry) [map](https://infra.spec.whatwg.org/#maps), that do not have explicit processing rules for the [representation](#dfn-representations) being produced using only the [representation](#dfn-representations)\'s data type processing rules and return the serialization after the [production](#dfn-production) process completes. +3. A [conforming producer](#dfn-conforming-producer) *MUST* return the Media Type [string](https://infra.spec.whatwg.org/#string) associated with the [representation](#dfn-representations) after the [production](#dfn-production) process completes. +4. A conforming producer *MUST NOT* produce non-conforming [DIDs](#dfn-decentralized-identifiers) or [DID documents](#dfn-did-documents). + +The requirements for all [conforming consumers](#dfn-conforming-consumer) are as follows: + +1. A [conforming consumer](#dfn-conforming-consumer) *MUST* take a [representation](#dfn-representations) and Media Type [string](https://infra.spec.whatwg.org/#string) as input into the [consumption](#dfn-consumption) process. A [conforming consumer](#dfn-conforming-consumer) *MAY* accept additional options as input into the [consumption](#dfn-consumption) process. +2. A [conforming consumer](#dfn-conforming-consumer) *MUST* determine the [representation](#dfn-representations) of a [DID document](#dfn-did-documents) using the Media Type input [string](https://infra.spec.whatwg.org/#string). +3. A [conforming consumer](#dfn-conforming-consumer) *MUST* detect any [representation-specific entry](#dfn-representation-specific-entry) across all known [representations](#dfn-representations) and place the entry into a [representation-specific entries](#dfn-representation-specific-entry) [map](https://infra.spec.whatwg.org/#maps) which is returned after the [consumption](#dfn-consumption) process completes. A list of all known [representation-specific entries](#dfn-representation-specific-entry) is available in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. +4. A [conforming consumer](#dfn-conforming-consumer) *MUST* add all [non-representation-specific entries](#dfn-representation-specific-entry) that do not have explicit processing rules for the [representation](#dfn-representations) being consumed to the [DID document](#dfn-did-documents) [data model](#data-model) using only the [representation](#dfn-representations)\'s data type processing rules and return the [DID document](#dfn-did-documents) data model after the [consumption](#dfn-consumption) process completes. +5. A conforming consumer *MUST* produce errors when consuming non-conforming [DIDs](#dfn-decentralized-identifiers) or [DID documents](#dfn-did-documents). + +![ Diagram illustrating how representations of the data model are produced and consumed, including in JSON and JSON-LD.](diagrams/diagram-production-consumption.svg) + +Figure 4 Production and consumption of representations. See also: [narrative description](#production-consumption-longdesc). + +The upper left quadrant of the diagram contains a rectangle with dashed grey outline, containing two blue-outlined rectangles, one above the other. The upper, larger rectangle is labeled, in blue, \"Core Properties\", and contains the following [INFRA](https://infra.spec.whatwg.org/#maps) notation: + +``` {aria-busy="false"} +«[ + "id" → "example:123", + "verificationMethod" → « «[ + "id": "did:example:123#keys-1", + "controller": "did:example:123", + "type": "Ed25519VerificationKey2018", + "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVA" + ]» », + "authentication" → « + "did:example:123#keys-1" + » +]» +``` + +The lower, smaller rectangle is labeled, in blue, \"Core Representation-specific Entries (JSON-LD)\", and contains the following monospaced [INFRA](https://infra.spec.whatwg.org/#maps) notation: + +``` {aria-busy="false"} +«[ "@context" → "https://www.w3.org/ns/did/v1" ]» +``` + +From the grey-outlined rectangle, three pairs of arrows extend to three different black-outlined rectangles, one on the upper right of the diagram, one in the lower right, and one in the lower left. Each pair of arrows consists of one blue arrow pointing from the grey-outlined rectangle to the respective black-outlined rectangle, labeled \"produce\", and one red arrow pointing in the reverse direction, labeled \"consume\". The black-outlined rectangle in the upper right is labeled \"application/did+cbor\", and contains hexadecimal data. The rectangle in the lower right is labeled \"application/did+json\", and contains the following JSON data: + +``` {aria-busy="false"} +{ + "id": "did:example:123", + "verificationMethod": [{ + "id": "did:example:123#keys-1", + "controller": "did:example:123", + "type": "Ed25519VerificationKey2018", + "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVA" + }], + "authentication": [ + "did:example:123#keys-1" + ] +} +``` + +The rectangle in the lower left is labeled \"application/did+ld+json\", and contains the following JSON-LD data: + +``` {aria-busy="false"} +{ + "@context": ["https://www.w3.org/ns/did/v1"], + "id": "did:example:123", + "verificationMethod": [{ + "id": "did:example:123#keys-1", + "controller": "did:example:123", + "type": "Ed25519VerificationKey2018", + "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVA" + }], + "authentication": [ + "did:example:123#keys-1" + ] +} +``` + +Note: Conversion between representations + +An implementation is expected to convert between [representations](#dfn-representations) by using the *consumption* rules on the source representation resulting in the [data model](#data-model) and then using the *production* rules to serialize [data model](#data-model) to the target representation, or any other mechanism that results in the same target representation. + +### 6.2 JSON + +[](#json) + +This section defines the [production](#dfn-production) and [consumption](#dfn-consumption) rules for the JSON [representation](#dfn-representations). + +#### 6.2.1 Production + +[](#production) + +The [DID document](#dfn-did-documents), DID document data structures, and [representation-specific entries](#dfn-representation-specific-entry) [map](https://infra.spec.whatwg.org/#maps) *MUST* be serialized to the JSON [representation](#dfn-representations) according to the following [production](#dfn-production) rules: + + Data Type JSON Representation Type + --------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + [map](https://infra.spec.whatwg.org/#maps) A [JSON Object](https://www.rfc-editor.org/rfc/rfc8259#section-4), where each entry is serialized as a member of the JSON Object with the entry key as a [JSON String](https://www.rfc-editor.org/rfc/rfc8259#section-7) member name and the entry value according to its type, as defined in this table. + [list](https://infra.spec.whatwg.org/#list) A [JSON Array](https://www.rfc-editor.org/rfc/rfc8259#section-5), where each element of the list is serialized, in order, as a value of the array according to its type, as defined in this table. + [set](https://infra.spec.whatwg.org/#ordered-set) A [JSON Array](https://www.rfc-editor.org/rfc/rfc8259#section-5), where each element of the set is added, in order, as a value of the array according to its type, as defined in this table. + [datetime](#dfn-datetime) A [JSON String](https://www.rfc-editor.org/rfc/rfc8259#section-7) serialized as an [XML Datetime](https://www.w3.org/TR/xmlschema11-2/#dateTime) normalized to UTC 00:00:00 and without sub-second decimal precision. For example: `2020-12-20T19:17:47Z`. + [string](https://infra.spec.whatwg.org/#string) A [JSON String](https://www.rfc-editor.org/rfc/rfc8259#section-7). + [integer](#dfn-integer) A [JSON Number](https://www.rfc-editor.org/rfc/rfc8259#section-6) without a decimal or fractional component. + [double](#dfn-double) A [JSON Number](https://www.rfc-editor.org/rfc/rfc8259#section-6) with a decimal and fractional component. + [boolean](https://infra.spec.whatwg.org/#boolean) A [JSON Boolean](https://www.rfc-editor.org/rfc/rfc8259#section-3). + [null](https://infra.spec.whatwg.org/#nulls) A [JSON null literal](https://www.rfc-editor.org/rfc/rfc8259#section-3). + +All implementers creating [conforming producers](#dfn-conforming-producer) that produce JSON [representations](#dfn-representations) are advised to ensure that their algorithms are aligned with the [JSON serialization rules](https://infra.spec.whatwg.org/#serialize-an-infra-value-to-json-bytes) in the \[[INFRA](#bib-infra "Infra Standard")\] specification and the [precision advisements regarding Numbers](https://www.rfc-editor.org/rfc/rfc8259#section-6) in the JSON \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\] specification. + +All entries of a [DID document](#dfn-did-documents) *MUST* be included in the root [JSON Object](https://www.rfc-editor.org/rfc/rfc8259#section-4). Entries *MAY* contain additional data substructures subject to the value representation rules in the list above. When serializing a [DID document](#dfn-did-documents), a [conforming producer](#dfn-conforming-producer) *MUST* specify a media type of `application/did+json` to downstream applications such as described in [7.1.2 DID Resolution Metadata](#did-resolution-metadata). + +[Example 21](#example-example-did-document-in-json-representation): Example DID document in JSON representation + +``` nohighlight +{ + "id": "did:example:123456789abcdefghi", + "authentication": [{ + "id": "did:example:123456789abcdefghi#keys-1", + "type": "Ed25519VerificationKey2018", + "controller": "did:example:123456789abcdefghi", + "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + }] +} +``` + +#### 6.2.2 Consumption + +[](#consumption) + +The [DID document](#dfn-did-documents) and DID document data structures JSON [representation](#dfn-representations) *MUST* be deserialized into the [data model](#data-model) according to the following [consumption](#dfn-consumption) rules: + + JSON Representation Type Data Type + --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + [JSON Object](https://www.rfc-editor.org/rfc/rfc8259#section-4) A [map](https://infra.spec.whatwg.org/#maps), where each member of the JSON Object is added as an entry to the map. Each entry key is set as the JSON Object member name. Each entry value is set by converting the JSON Object member value according to the JSON representation type as defined in this table. Since order is not specified by JSON Objects, no insertion order is guaranteed. + [JSON Array](https://www.rfc-editor.org/rfc/rfc8259#section-5) where the [data model](#data-model) entry value is a [list](https://infra.spec.whatwg.org/#list) or unknown A [list](https://infra.spec.whatwg.org/#list), where each value of the JSON Array is added to the list in order, converted based on the JSON representation type of the array value, as defined in this table. + [JSON Array](https://www.rfc-editor.org/rfc/rfc8259#section-5) where the [data model](#data-model) entry value is a [set](https://infra.spec.whatwg.org/#ordered-set) A [set](https://infra.spec.whatwg.org/#ordered-set), where each value of the JSON Array is added to the set in order, converted based on the JSON representation type of the array value, as defined in this table. + [JSON String](https://www.rfc-editor.org/rfc/rfc8259#section-7) where [data model](#data-model) entry value is a [datetime](#dfn-datetime) A [datetime](#dfn-datetime). + [JSON String](https://www.rfc-editor.org/rfc/rfc8259#section-7), where the [data model](#data-model) entry value type is [string](https://infra.spec.whatwg.org/#string) or unknown A [string](https://infra.spec.whatwg.org/#string). + [JSON Number](https://www.rfc-editor.org/rfc/rfc8259#section-6) without a decimal or fractional component An [integer](#dfn-integer). + [JSON Number](https://www.rfc-editor.org/rfc/rfc8259#section-6) with a decimal and fractional component, or when entry value is a [double](#dfn-double) regardless of inclusion of fractional component A [double](#dfn-double). + [JSON Boolean](https://www.rfc-editor.org/rfc/rfc8259#section-3) A [boolean](https://infra.spec.whatwg.org/#boolean). + [JSON null literal](https://www.rfc-editor.org/rfc/rfc8259#section-3) A [null](https://infra.spec.whatwg.org/#nulls) value. + +All implementers creating [conforming consumers](#dfn-conforming-consumer) that produce JSON [representations](#dfn-representations) are advised to ensure that their algorithms are aligned with the [JSON conversion rules](https://infra.spec.whatwg.org/#parse-json-bytes-to-an-infra-value) in the \[[INFRA](#bib-infra "Infra Standard")\] specification and the [precision advisements regarding Numbers](https://www.rfc-editor.org/rfc/rfc8259#section-6) in the JSON \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\] specification. + +If media type information is available to a [conforming consumer](#dfn-conforming-consumer) and the media type value is `application/did+json`, then the data structure being consumed is a [DID document](#dfn-did-documents), and the root element *MUST* be a [JSON Object](https://www.rfc-editor.org/rfc/rfc8259#section-4) where all members of the object are entries of the [DID document](#dfn-did-documents). A [conforming consumer](#dfn-conforming-consumer) for a JSON [representation](#dfn-representations) that is consuming a [DID document](#dfn-did-documents) with a root element that is not a [JSON Object](https://www.rfc-editor.org/rfc/rfc8259#section-4) *MUST* report an error. + +### 6.3 JSON-LD + +[](#json-ld) + +JSON-LD \[[JSON-LD11](#bib-json-ld11 "JSON-LD 1.1")\] is a JSON-based format used to serialize [Linked Data](https://www.w3.org/TR/ld-glossary/#linked-data). This section defines the [production](#dfn-production) and [consumption](#dfn-consumption) rules for the JSON-LD [representation](#dfn-representations). + +The JSON-LD [representation](#dfn-representations) defines the following [representation-specific entries](#dfn-representation-specific-entry): + +\@context +: The [JSON-LD Context](https://www.w3.org/TR/json-ld11/#the-context) is either a [string](https://infra.spec.whatwg.org/#string) or a [list](https://infra.spec.whatwg.org/#list) containing any combination of [strings](https://infra.spec.whatwg.org/#string) and/or [ordered maps](https://infra.spec.whatwg.org/#maps). + +#### 6.3.1 Production + +[](#production-0) + +The [DID document](#dfn-did-documents), DID document data structures, and [representation-specific entries](#dfn-representation-specific-entry) [map](https://infra.spec.whatwg.org/#maps) *MUST* be serialized to the JSON-LD [representation](#dfn-representations) according to the JSON [representation](#dfn-representations) [production](#dfn-production) rules as defined in [6.2 JSON](#json). + +In addition to using the JSON [representation](#dfn-representations) [production](#dfn-production) rules, JSON-LD production *MUST* include the [representation-specific](#dfn-representation-specific-entry) [`@context`](#dfn-context) entry. The serialized value of `@context` *MUST* be the [JSON String](https://www.rfc-editor.org/rfc/rfc8259#section-7) `https://www.w3.org/ns/did/v1`, or a [JSON Array](https://www.rfc-editor.org/rfc/rfc8259#section-5) where the first item is the [JSON String](https://www.rfc-editor.org/rfc/rfc8259#section-7) `https://www.w3.org/ns/did/v1` and the subsequent items are serialized according to the JSON [representation](#dfn-representations) [production](#dfn-production) rules. + +[Example 22](#example-a-valid-serialization-of-a-simple-context-entry): A valid serialization of a simple \@context entry + +``` {aria-busy="false"} +{ + "@context": "https://www.w3.org/ns/did/v1", + ... +} +``` + +[Example 23](#example-a-valid-serialization-of-a-layered-context-entry): A valid serialization of a layered \@context entry + +``` {aria-busy="false"} +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://did-method-extension.example/v1" + ], + ... +} +``` + +All implementers creating [conforming producers](#dfn-conforming-producer) that produce JSON-LD [representations](#dfn-representations) are advised to ensure that their algorithms produce valid JSON-LD \[[JSON-LD11](#bib-json-ld11 "JSON-LD 1.1")\] documents. Invalid JSON-LD documents will cause JSON-LD processors to halt and report errors. + +In order to achieve interoperability across different [representations](#dfn-representations), all JSON-LD Contexts and their terms *SHOULD* be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. + +A [conforming producer](#dfn-conforming-producer) that generates a JSON-LD [representation](#dfn-representations) *SHOULD NOT* produce a [DID document](#dfn-did-documents) that contains terms not defined via the `@context` as [conforming consumers](#dfn-conforming-consumer) are expected to remove unknown terms. When serializing a JSON-LD [representation](#dfn-representations) of a [DID document](#dfn-did-documents), a [conforming producer](#dfn-conforming-producer) *MUST* specify a media type of `application/did+ld+json` to downstream applications such as described in [7.1.2 DID Resolution Metadata](#did-resolution-metadata). + +#### 6.3.2 Consumption + +[](#consumption-0) + +The [DID document](#dfn-did-documents) and any DID document data structures expressed by a JSON-LD [representation](#dfn-representations) *MUST* be deserialized into the [data model](#data-model) according to the JSON [representation](#dfn-representations) [consumption](#dfn-consumption) rules as defined in [6.2 JSON](#json). + +All implementers creating [conforming consumers](#dfn-conforming-consumer) that consume JSON-LD [representations](#dfn-representations) are advised to ensure that their algorithms only accept valid JSON-LD \[[JSON-LD11](#bib-json-ld11 "JSON-LD 1.1")\] documents. Invalid JSON-LD documents will cause JSON-LD processors to halt and report errors. + +[Conforming consumers](#dfn-conforming-consumer) that process a JSON-LD [representation](#dfn-representations) *SHOULD* drop all terms from a [DID document](#dfn-did-documents) that are not defined via the `@context`. + +## 7. Resolution + +[](#resolution) + +This section defines the inputs and outputs of [DID resolution](#dfn-did-resolution) and [DID URL dereferencing](#dfn-did-url-dereferencing). Their exact implementation is out of scope for this specification, but some considerations for implementers are discussed in \[[DID-RESOLUTION](#bib-did-resolution "Decentralized Identifier Resolution")\]. + +All conformant [DID resolvers](#dfn-did-resolvers) *MUST* implement the [DID resolution](#dfn-did-resolution) functions for at least one [DID method](#dfn-did-methods) and *MUST* be able to return a [DID document](#dfn-did-documents) in at least one conformant [representation](#dfn-representations). + +### 7.1 DID Resolution + +[](#did-resolution) + +The [DID resolution](#dfn-did-resolution) functions resolve a [DID](#dfn-decentralized-identifiers) into a [DID document](#dfn-did-documents) by using the \"Read\" operation of the applicable [DID method](#dfn-did-methods) as described in [8.2 Method Operations](#method-operations). The details of how this process is accomplished are outside the scope of this specification, but all conforming [DID resolvers](#dfn-did-resolvers) implement the functions below, which have the following abstract forms: + +``` {title="Abstract functions for DID Resolution" aria-busy="false"} +resolve(did, resolutionOptions) → + « didResolutionMetadata, didDocument, didDocumentMetadata » + +resolveRepresentation(did, resolutionOptions) → + « didResolutionMetadata, didDocumentStream, didDocumentMetadata » +``` + +The `resolve` function returns the [DID document](#dfn-did-documents) in its abstract form (a [map](https://infra.spec.whatwg.org/#maps)). The `resolveRepresentation` function returns a byte stream of the [DID Document](#dfn-did-documents) formatted in the corresponding representation. + +![ Diagram illustrating how resolve() returns the DID document data model in its abstract form and resolveRepresenation() returns it in one of the conformant representations; conversion is possible using production and consumption rules.](diagrams/diagram-resolve-resolverepresentation.svg) + +Figure 5 Functions resolve() and resolveRepresentation(). See also: [narrative description](#resolve-resolverepresentation-longdesc). + +The upper middle part of the diagram contains a rectangle with dashed grey outline, containing two blue-outlined rectangles, one above the other. The upper, larger rectangle is labeled, in blue, \"Core Properties\", and contains the following [INFRA](https://infra.spec.whatwg.org/#maps) notation: + +``` {aria-busy="false"} +«[ + "id" → "example:123", + "verificationMethod" → « «[ + "id": "did:example:123#keys-1", + "controller": "did:example:123", + "type": "Ed25519VerificationKey2018", + "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVA" + ]» », + "authentication" → « + "did:example:123#keys-1" + » +]» +``` + +The lower, smaller rectangle is labeled, in blue, \"Core Representation-specific Entries (JSON-LD)\", and contains the following monospaced [INFRA](https://infra.spec.whatwg.org/#maps) notation: + +``` {aria-busy="false"} +«[ "@context" → "https://www.w3.org/ns/did/v1" ]» +``` + +From the grey-outlined rectangle, three pairs of arrows extend to three different black-outlined rectangles, aligned in a horizontal row side-by-side, in the bottom half of the diagram. Each pair of arrows consists of one blue arrow pointing from the grey-outlined rectangle to the respective black-outlined rectangle, labeled \"produce\", and one red arrow pointing in the reverse direction, labeled \"consume\". The first black-outlined rectangle in the row is labeled \"application/did+ld+json\", and contains the following JSON-LD data: + +``` {aria-busy="false"} +{ + "@context": ["https://www.w3.org/ns/did/v1"], + "id": "did:example:123", + "verificationMethod": [{ + "id": "did:example:123#keys-1", + "controller": "did:example:123", + "type": "Ed25519VerificationKey2018", + "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVA" + }], + "authentication": [ + "did:example:123#keys-1" + ] +} +``` + +The second rectangle in the row is labeled \"application/did+json\" and contains the following JSON data: + +``` {aria-busy="false"} +{ + "id": "did:example:123", + "verificationMethod": [{ + "id": "did:example:123#keys-1", + "controller": "did:example:123", + "type": "Ed25519VerificationKey2018", + "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVA" + }], + "authentication": [ + "did:example:123#keys-1" + ] +} +``` + +The third rectangle in the row is labeled \"application/did+cbor\", and contains hexadecimal data. + +In the left part of the diagram, in the middle, there is a box, with black outline and light gray background. This box is labeled \"VERIFIABLE DATA REGISTRY\" and contains a symbol representing a graph with nodes and arcs. From this box, one arrow, labeled \"resolve()\", extends upwards and points to the top half of the diagram where the grey-outlined rectangle is located. Another arrow, labeled \"resolveRepresentation()\", extends downwards and points to the bottom half of the diagram, where the row of three black-outlined rectangles is located. + +The input variables of the `resolve` and `resolveRepresentation` functions are as follows: + +did +: This is the [DID](#dfn-decentralized-identifiers) to resolve. This input is *REQUIRED* and the value *MUST* be a conformant [DID](#dfn-decentralized-identifiers) as defined in [3.1 DID Syntax](#did-syntax). + +resolutionOptions +: A [metadata structure](#metadata-structure) containing properties defined in [7.1.1 DID Resolution Options](#did-resolution-options). This input is *REQUIRED*, but the structure *MAY* be empty. + +These functions each return multiple values, and no limitations are placed on how these values are returned together. The return values of `resolve` are [didResolutionMetadata](#dfn-didresolutionmetadata), [didDocument](#dfn-diddocument), and [didDocumentMetadata](#dfn-diddocumentmetadata). The return values of `resolveRepresentation` are [didResolutionMetadata](#dfn-didresolutionmetadata), [didDocumentStream](#dfn-diddocumentstream), and [didDocumentMetadata](#dfn-diddocumentmetadata). These values are described below: + +didResolutionMetadata +: A [metadata structure](#metadata-structure) consisting of values relating to the results of the [DID resolution](#dfn-did-resolution) process which typically changes between invocations of the `resolve` and `resolveRepresentation` functions, as it represents data about the resolution process itself. This structure is *REQUIRED*, and in the case of an error in the resolution process, this *MUST NOT* be empty. This metadata is defined by [7.1.2 DID Resolution Metadata](#did-resolution-metadata). If `resolveRepresentation` was called, this structure *MUST* contain a `contentType` property containing the Media Type of the representation found in the `didDocumentStream`. If the resolution is not successful, this structure *MUST* contain an `error` property describing the error. + +didDocument +: If the resolution is successful, and if the `resolve` function was called, this *MUST* be a [DID document](#dfn-did-documents) abstract data model (a [map](https://infra.spec.whatwg.org/#maps)) as described in [4. Data Model](#data-model) that is capable of being transformed into a [conforming DID Document](#dfn-conforming-did-document) (representation), using the production rules specified by the representation. The value of [`id`](#dfn-id) in the resolved [DID document](#dfn-did-documents) *MUST* match the [DID](#dfn-decentralized-identifiers) that was resolved. If the resolution is unsuccessful, this value *MUST* be empty. + +didDocumentStream +: If the resolution is successful, and if the `resolveRepresentation` function was called, this *MUST* be a byte stream of the resolved [DID document](#dfn-did-documents) in one of the conformant [representations](#representations). The byte stream might then be parsed by the caller of the `resolveRepresentation` function into a [data model](#data-model), which can in turn be validated and processed. If the resolution is unsuccessful, this value *MUST* be an empty stream. + +didDocumentMetadata +: If the resolution is successful, this *MUST* be a [metadata structure](#metadata-structure). This structure contains metadata about the [DID document](#dfn-did-documents) contained in the `didDocument` property. This metadata typically does not change between invocations of the `resolve` and `resolveRepresentation` functions unless the [DID document](#dfn-did-documents) changes, as it represents metadata about the [DID document](#dfn-did-documents). If the resolution is unsuccessful, this output *MUST* be an empty [metadata structure](#metadata-structure). Properties defined by this specification are in [7.1.3 DID Document Metadata](#did-document-metadata). + +Conforming [DID resolver](#dfn-did-resolvers) implementations do not alter the signature of these functions in any way. [DID resolver](#dfn-did-resolvers) implementations might map the `resolve` and `resolveRepresentation` functions to a method-specific internal function to perform the actual [DID resolution](#dfn-did-resolution) process. [DID resolver](#dfn-did-resolvers) implementations might implement and expose additional functions with different signatures in addition to the `resolve` and `resolveRepresentation` functions specified here. + +#### 7.1.1 DID Resolution Options + +[](#did-resolution-options) + +The possible properties within this structure and their possible values are registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. This specification defines the following common properties. + +accept +: The Media Type of the caller\'s preferred [representation](#dfn-representations) of the [DID document](#dfn-did-documents). The Media Type *MUST* be expressed as an [ASCII string](https://infra.spec.whatwg.org/#ascii-string). The [DID resolver](#dfn-did-resolvers) implementation *SHOULD* use this value to determine the [representation](#dfn-representations) contained in the returned `didDocumentStream` if such a [representation](#dfn-representations) is supported and available. This property is *OPTIONAL* for the `resolveRepresentation` function and *MUST NOT* be used with the `resolve` function. + +#### 7.1.2 DID Resolution Metadata + +[](#did-resolution-metadata) + +The possible properties within this structure and their possible values are registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. This specification defines the following DID resolution metadata properties: + +contentType +: The Media Type of the returned `didDocumentStream`. This property is *REQUIRED* if resolution is successful and if the `resolveRepresentation` function was called. This property *MUST NOT* be present if the `resolve` function was called. The value of this property *MUST* be an [ASCII string](https://infra.spec.whatwg.org/#ascii-string) that is the Media Type of the conformant [representations](#dfn-representations). The caller of the `resolveRepresentation` function *MUST* use this value when determining how to parse and process the `didDocumentStream` returned by this function into the [data model](#data-model). + +error +: The error code from the resolution process. This property is *REQUIRED* when there is an error in the resolution process. The value of this property *MUST* be a single keyword [ASCII string](https://infra.spec.whatwg.org/#ascii-string). The possible property values of this field *SHOULD* be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. This specification defines the following common error values: + + invalidDid + : The [DID](#dfn-decentralized-identifiers) supplied to the [DID resolution](#dfn-did-resolution) function does not conform to valid syntax. (See [3.1 DID Syntax](#did-syntax).) + + notFound + : The [DID resolver](#dfn-did-resolvers) was unable to find the [DID document](#dfn-did-documents) resulting from this resolution request. + + representationNotSupported + : This error code is returned if the [representation](#dfn-representations) requested via the `accept` input metadata property is not supported by the [DID method](#dfn-did-methods) and/or [DID resolver](#dfn-did-resolvers) implementation. + +#### 7.1.3 DID Document Metadata + +[](#did-document-metadata) + +The possible properties within this structure and their possible values *SHOULD* be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. This specification defines the following common properties. + +created +: [DID document](#dfn-did-documents) metadata *SHOULD* include a `created` property to indicate the timestamp of the [Create operation](#method-operations). The value of the property *MUST* be a [string](https://infra.spec.whatwg.org/#string) formatted as an [XML Datetime](https://www.w3.org/TR/xmlschema11-2/#dateTime) normalized to UTC 00:00:00 and without sub-second decimal precision. For example: `2020-12-20T19:17:47Z`. + +updated +: [DID document](#dfn-did-documents) metadata *SHOULD* include an `updated` property to indicate the timestamp of the last [Update operation](#method-operations) for the document version which was resolved. The value of the property *MUST* follow the same formatting rules as the `created` property. The `updated` property is omitted if an Update operation has never been performed on the [DID document](#dfn-did-documents). If an `updated` property exists, it can be the same value as the `created` property when the difference between the two timestamps is less than one second. + +deactivated +: If a DID has been [deactivated](#method-operations), [DID document](#dfn-did-documents) metadata *MUST* include this property with the boolean value `true`. If a DID has not been deactivated, this property is *OPTIONAL*, but if included, *MUST* have the boolean value `false`. + +nextUpdate +: [DID document](#dfn-did-documents) metadata *MAY* include a `nextUpdate` property if the resolved document version is not the latest version of the document. It indicates the timestamp of the next [Update operation](#method-operations). The value of the property *MUST* follow the same formatting rules as the `created` property. + +versionId +: [DID document](#dfn-did-documents) metadata *SHOULD* include a `versionId` property to indicate the version of the last [Update operation](#method-operations) for the document version which was resolved. The value of the property *MUST* be an [ASCII string](https://infra.spec.whatwg.org/#ascii-string). + +nextVersionId +: [DID document](#dfn-did-documents) metadata *MAY* include a `nextVersionId` property if the resolved document version is not the latest version of the document. It indicates the version of the next [Update operation](#method-operations). The value of the property *MUST* be an [ASCII string](https://infra.spec.whatwg.org/#ascii-string). + +equivalentId + +: A [DID method](#dfn-did-methods) can define different forms of a [DID](#dfn-decentralized-identifiers) that are logically equivalent. An example is when a [DID](#dfn-decentralized-identifiers) takes one form prior to registration in a [verifiable data registry](#dfn-verifiable-data-registry) and another form after such registration. In this case, the [DID method](#dfn-did-methods) specification might need to express one or more [DIDs](#dfn-decentralized-identifiers) that are logically equivalent to the resolved [DID](#dfn-decentralized-identifiers) as a property of the [DID document](#dfn-did-documents). This is the purpose of the [`equivalentId`](#dfn-equivalentid) property. + + [DID document](#dfn-did-documents) metadata *MAY* include an `equivalentId` property. If present, the value *MUST* be a [set](https://infra.spec.whatwg.org/#ordered-set) where each item is a [string](https://infra.spec.whatwg.org/#string) that conforms to the rules in Section [3.1 DID Syntax](#did-syntax). The relationship is a statement that each [`equivalentId`](#dfn-equivalentid) value is logically equivalent to the `id` property value and thus refers to the same [DID subject](#dfn-did-subjects). Each [`equivalentId`](#dfn-equivalentid) DID value *MUST* be produced by, and a form of, the same [DID method](#dfn-did-methods) as the `id` property value. (e.g., `did:example:abc` == `did:example:ABC`) + + A conforming [DID method](#dfn-did-methods) specification *MUST* guarantee that each [`equivalentId`](#dfn-equivalentid) value is logically equivalent to the `id` property value. + + A requesting party is expected to retain the values from the `id` and [`equivalentId`](#dfn-equivalentid) properties to ensure any subsequent interactions with any of the values they contain are correctly handled as logically equivalent (e.g., retain all variants in a database so an interaction with any one maps to the same underlying account). + + Note: Stronger equivalence + + [`equivalentId`](#dfn-equivalentid) is a much stronger form of equivalence than [`alsoKnownAs`](#dfn-alsoknownas) because the equivalence *MUST* be guaranteed by the governing [DID method](#dfn-did-methods). [`equivalentId`](#dfn-equivalentid) represents a full graph merge because the same [DID document](#dfn-did-documents) describes both the [`equivalentId`](#dfn-equivalentid) [DID](#dfn-decentralized-identifiers) and the `id` property [DID](#dfn-decentralized-identifiers). + + If a requesting party does not retain the values from the `id` and [`equivalentId`](#dfn-equivalentid) properties and ensure any subsequent interactions with any of the values they contain are correctly handled as logically equivalent, there might be negative or unexpected issues that arise. Implementers are strongly advised to observe the directives related to this metadata property. + +canonicalId + +: The [`canonicalId`](#dfn-canonicalid) property is identical to the [`equivalentId`](#dfn-equivalentid) property except: a) it is associated with a single value rather than a set, and b) the [DID](#dfn-decentralized-identifiers) is defined to be the canonical ID for the [DID subject](#dfn-did-subjects) within the scope of the containing [DID document](#dfn-did-documents). + + [DID document](#dfn-did-documents) metadata *MAY* include a `canonicalId` property. If present, the value *MUST* be a [string](https://infra.spec.whatwg.org/#string) that conforms to the rules in Section [3.1 DID Syntax](#did-syntax). The relationship is a statement that the [`canonicalId`](#dfn-canonicalid) value is logically equivalent to the `id` property value and that the [`canonicalId`](#dfn-canonicalid) value is defined by the [DID method](#dfn-did-methods) to be the canonical ID for the [DID subject](#dfn-did-subjects) in the scope of the containing [DID document](#dfn-did-documents). A [`canonicalId`](#dfn-canonicalid) value *MUST* be produced by, and a form of, the same [DID method](#dfn-did-methods) as the `id` property value. (e.g., `did:example:abc` == `did:example:ABC`). + + A conforming [DID method](#dfn-did-methods) specification *MUST* guarantee that the [`canonicalId`](#dfn-canonicalid) value is logically equivalent to the `id` property value. + + A requesting party is expected to use the [`canonicalId`](#dfn-canonicalid) value as its primary ID value for the [DID subject](#dfn-did-subjects) and treat all other equivalent values as secondary aliases (e.g., update corresponding primary references in their systems to reflect the new canonical ID directive). + + Note: Canonical equivalence + + [`canonicalId`](#dfn-canonicalid) is the same statement of equivalence as [`equivalentId`](#dfn-equivalentid) except it is constrained to a single value that is defined to be canonical for the [DID subject](#dfn-did-subjects) in the scope of the [DID document](#dfn-did-documents). Like [`equivalentId`](#dfn-equivalentid), [`canonicalId`](#dfn-canonicalid) represents a full graph merge because the same [DID document](#dfn-did-documents) describes both the [`canonicalId`](#dfn-canonicalid) DID and the `id` property [DID](#dfn-decentralized-identifiers). + + If a resolving party does not use the [`canonicalId`](#dfn-canonicalid) value as its primary ID value for the DID subject and treat all other equivalent values as secondary aliases, there might be negative or unexpected issues that arise related to user experience. Implementers are strongly advised to observe the directives related to this metadata property. + +### 7.2 DID URL Dereferencing + +[](#did-url-dereferencing) + +The [DID URL dereferencing](#dfn-did-url-dereferencing) function dereferences a [DID URL](#dfn-did-urls) into a [resource](#dfn-resources) with contents depending on the [DID URL](#dfn-did-urls)\'s components, including the [DID method](#dfn-did-methods), method-specific identifier, path, query, and fragment. This process depends on [DID resolution](#dfn-did-resolution) of the [DID](#dfn-decentralized-identifiers) contained in the [DID URL](#dfn-did-urls). [DID URL dereferencing](#dfn-did-url-dereferencing) might involve multiple steps (e.g., when the DID URL being dereferenced includes a fragment), and the function is defined to return the final resource after all steps are completed. The details of how this process is accomplished are outside the scope of this specification. The following figure depicts the relationship described above. + +![ DIDs resolve to DID documents; DID URLs contains a DID; DID URLs dereferenced to DID document fragments or external resources. ](diagrams/did_url_dereference_overview.svg) + +Figure 6 Overview of DID URL dereference See also: [narrative description](#did-url-dereference-overview-longdesc). + +The top left part of the diagram contains a rectangle with black outline, labeled \"DID\". + +The bottom left part of the diagram contains a rectangle with black outline, labeled \"DID URL\". This rectangle contains four smaller black-outlined rectangles, aligned in a horizontal row adjacent to each other. These smaller rectangles are labeled, in order, \"DID\", \"path\", \"query\", and \"fragment. + +The top right part of the diagram contains a rectangle with black outline, labeled \"DID document\". This rectangle contains three smaller black-outlined rectangles. These smaller rectangles are labeled \"id\", \"(property X)\", and \"(property Y)\", and are surrounded by multiple series of three dots (ellipses). A curved black arrow, labeled \"DID document - relative fragment dereference\", extends from the rectangle labeled \"(property X)\", and points to the rectangle labeled \"(property Y)\". + +The bottom right part of the diagram contains an oval shape with black outline, labeled \"Resource\". + +A black arrow, labeled \"resolves to a DID document\", extends from the rectangle in the top left part of the diagram, labeled \"DID\", and points to the rectangle in the top right part of diagram, labeled \"DID document\". + +A black arrow, labeled \"refers to\", extends from the rectangle in the top right part of the diagram, labeled \"DID document\", and points to the oval shape in the bottom right part of diagram, labeled \"Resource\". + +A black arrow, labeled \"contains\", extends from the small rectangle labeled \"DID\" inside the rectangle in the bottom left part of the diagram, labeled \"DID URL\", and points to the rectangle in the top left part of diagram, labeled \"DID\". + +A black arrow, labeled \"dereferences to a DID document\", extends from the rectangle in the bottom left part of the diagram, labeled \"DID URL\", and points to the rectangle in the top right part of diagram, labeled \"DID document\". + +A black arrow, labeled \"dereferences to a resource\", extends from the rectangle in the bottom left part of the diagram, labeled \"DID URL\", and points to the oval shape in the bottom right part of diagram, labeled \"Resource\". + +All conforming [DID resolvers](#dfn-did-resolvers) implement the following function which has the following abstract form: + +``` {title="Abstract functions for DID URL Dereferencing" aria-busy="false"} +dereference(didUrl, dereferenceOptions) → + « dereferencingMetadata, contentStream, contentMetadata » +``` + +The input variables of the `dereference` function are as follows: + +didUrl +: A conformant [DID URL](#dfn-did-urls) as a single [string](https://infra.spec.whatwg.org/#string). This is the [DID URL](#dfn-did-urls) to dereference. To dereference a [DID fragment](#dfn-did-fragments), the complete [DID URL](#dfn-did-urls) including the [DID fragment](#dfn-did-fragments) *MUST* be used. This input is *REQUIRED*. + Note: DID URL dereferencer patterns + + While it is valid for any `didUrl` to be passed to a DID URL dereferencer, implementers are expected to refer to \[[DID-RESOLUTION](#bib-did-resolution "Decentralized Identifier Resolution")\] to further understand common patterns for how a [DID URL](#dfn-did-urls) is expected to be dereferenced. + +dereferencingOptions +: A [metadata structure](#metadata-structure) consisting of input options to the `dereference` function in addition to the `didUrl` itself. Properties defined by this specification are in [7.2.1 DID URL Dereferencing Options](#did-url-dereferencing-options). This input is *REQUIRED*, but the structure *MAY* be empty. + +This function returns multiple values, and no limitations are placed on how these values are returned together. The return values of the `dereference` include `dereferencingMetadata`, `contentStream`, and `contentMetadata`: + +dereferencingMetadata +: A [metadata structure](#metadata-structure) consisting of values relating to the results of the [DID URL dereferencing](#dfn-did-url-dereferencing) process. This structure is *REQUIRED*, and in the case of an error in the dereferencing process, this *MUST NOT* be empty. Properties defined by this specification are in [7.2.2 DID URL Dereferencing Metadata](#did-url-dereferencing-metadata). If the dereferencing is not successful, this structure *MUST* contain an `error` property describing the error. + +contentStream +: If the `dereferencing` function was called and successful, this *MUST* contain a [resource](#dfn-resources) corresponding to the [DID URL](#dfn-did-urls). The `contentStream` *MAY* be a [resource](#dfn-resources) such as a [DID document](#dfn-did-documents) that is serializable in one of the conformant [representations](#dfn-representations), a [Verification Method](#verification-methods), a [service](#services), or any other resource format that can be identified via a Media Type and obtained through the resolution process. If the dereferencing is unsuccessful, this value *MUST* be empty. + +contentMetadata +: If the dereferencing is successful, this *MUST* be a [metadata structure](#metadata-structure), but the structure *MAY* be empty. This structure contains metadata about the `contentStream`. If the `contentStream` is a [DID document](#dfn-did-documents), this *MUST* be a [didDocumentMetadata](#dfn-diddocumentmetadata) structure as described in [DID Resolution](#dfn-did-resolution). If the dereferencing is unsuccessful, this output *MUST* be an empty [metadata structure](#metadata-structure). + +Conforming [DID URL dereferencing](#dfn-did-url-dereferencing) implementations do not alter the signature of these functions in any way. [DID URL dereferencing](#dfn-did-url-dereferencing) implementations might map the `dereference` function to a method-specific internal function to perform the actual [DID URL dereferencing](#dfn-did-url-dereferencing) process. [DID URL dereferencing](#dfn-did-url-dereferencing) implementations might implement and expose additional functions with different signatures in addition to the `dereference` function specified here. + +#### 7.2.1 DID URL Dereferencing Options + +[](#did-url-dereferencing-options) + +The possible properties within this structure and their possible values *SHOULD* be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. This specification defines the following common properties for dereferencing options: + +accept +: The Media Type that the caller prefers for `contentStream`. The Media Type *MUST* be expressed as an [ASCII string](https://infra.spec.whatwg.org/#ascii-string). The [DID URL dereferencing](#dfn-did-url-dereferencing) implementation *SHOULD* use this value to determine the `contentType` of the [representation](#dfn-representations) contained in the returned value if such a [representation](#dfn-representations) is supported and available. + +#### 7.2.2 DID URL Dereferencing Metadata + +[](#did-url-dereferencing-metadata) + +The possible properties within this structure and their possible values are registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. This specification defines the following common properties. + +contentType +: The Media Type of the returned `contentStream` *SHOULD* be expressed using this property if dereferencing is successful. The Media Type value *MUST* be expressed as an [ASCII string](https://infra.spec.whatwg.org/#ascii-string). + +error +: The error code from the dereferencing process. This property is *REQUIRED* when there is an error in the dereferencing process. The value of this property *MUST* be a single keyword expressed as an [ASCII string](https://infra.spec.whatwg.org/#ascii-string). The possible property values of this field *SHOULD* be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. This specification defines the following common error values: + + invalidDidUrl + : The [DID URL](#dfn-did-urls) supplied to the [DID URL dereferencing](#dfn-did-url-dereferencing) function does not conform to valid syntax. (See [3.2 DID URL Syntax](#did-url-syntax).) + + notFound + : The [DID URL dereferencer](#dfn-did-url-dereferencers) was unable to find the `contentStream` resulting from this dereferencing request. + +### 7.3 Metadata Structure + +[](#metadata-structure) + +Input and output metadata is often involved during the [DID Resolution](#dfn-did-resolution), [DID URL dereferencing](#dfn-did-url-dereferencing), and other DID-related processes. The structure used to communicate this metadata *MUST* be a [map](https://infra.spec.whatwg.org/#maps) of properties. Each property name *MUST* be a [string](https://infra.spec.whatwg.org/#string). Each property value *MUST* be a [string](https://infra.spec.whatwg.org/#string), [map](https://infra.spec.whatwg.org/#maps), [list](https://infra.spec.whatwg.org/#list), [set](https://infra.spec.whatwg.org/#ordered-set), [boolean](https://infra.spec.whatwg.org/#boolean), or [null](https://infra.spec.whatwg.org/#nulls). The values within any complex data structures such as maps and lists *MUST* be one of these data types as well. All metadata property definitions registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\] *MUST* define the value type, including any additional formats or restrictions to that value (for example, a string formatted as a date or as a decimal integer). It is *RECOMMENDED* that property definitions use strings for values. The entire metadata structure *MUST* be serializable according to the [JSON serialization rules](https://infra.spec.whatwg.org/#serialize-an-infra-value-to-json-bytes) in the \[[INFRA](#bib-infra "Infra Standard")\] specification. Implementations *MAY* serialize the metadata structure to other data formats. + +All implementations of functions that use metadata structures as either input or output are able to fully represent all data types described here in a deterministic fashion. As inputs and outputs using metadata structures are defined in terms of data types and not their serialization, the method for [representation](#dfn-representations) is internal to the implementation of the function and is out of scope of this specification. + +The following example demonstrates a JSON-encoded metadata structure that might be used as [DID resolution input metadata](#did-resolution-options). + +[Example 24](#example-json-encoded-did-resolution-input-metadata-example): JSON-encoded DID resolution input metadata example + +``` {aria-busy="false"} +{ + "accept": "application/did+ld+json" +} +``` + +This example corresponds to a metadata structure of the following format: + +[Example 25](#example-did-resolution-input-metadata-example): DID resolution input metadata example + +``` {aria-busy="false"} +«[ + "accept" → "application/did+ld+json" +]» +``` + +The next example demonstrates a JSON-encoded metadata structure that might be used as [DID resolution metadata](#did-resolution-options) if a [DID](#dfn-decentralized-identifiers) was not found. + +[Example 26](#example-json-encoded-did-resolution-metadata-example): JSON-encoded DID resolution metadata example + +``` {aria-busy="false"} +{ + "error": "notFound" +} +``` + +This example corresponds to a metadata structure of the following format: + +[Example 27](#example-did-resolution-metadata-example): DID resolution metadata example + +``` {aria-busy="false"} +«[ + "error" → "notFound" +]» +``` + +The next example demonstrates a JSON-encoded metadata structure that might be used as [DID document metadata](#did-document-metadata) to describe timestamps associated with the [DID document](#dfn-did-documents). + +[Example 28](#example-json-encoded-did-document-metadata-example): JSON-encoded DID document metadata example + +``` {aria-busy="false"} +{ + "created": "2019-03-23T06:35:22Z", + "updated": "2023-08-10T13:40:06Z" +} +``` + +This example corresponds to a metadata structure of the following format: + +[Example 29](#example-did-document-metadata-example): DID document metadata example + +``` {aria-busy="false"} +«[ + "created" → "2019-03-23T06:35:22Z", + "updated" → "2023-08-10T13:40:06Z" +]» +``` + +## 8. Methods + +[](#methods) + +A [DID method](#dfn-did-methods) defines how implementers can realize the features described by this specification. [DID methods](#dfn-did-methods) are often associated with a particular [verifiable data registry](#dfn-verifiable-data-registry). New [DID methods](#dfn-did-methods) are defined in their own specifications to enable interoperability between different implementations of the same [DID method](#dfn-did-methods). + +Conceptually, the relationship between this specification and a [DID method](#dfn-did-methods) specification is similar to the relationship between the IETF generic [URI](#dfn-uri) specification \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\] and a specific [URI](#dfn-uri) scheme \[[IANA-URI-SCHEMES](#bib-iana-uri-schemes "Uniform Resource Identifier (URI) Schemes")\], such as the `http` scheme \[[RFC7230](#bib-rfc7230 "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing")\]. In addition to defining a specific [DID scheme](#dfn-did-schemes), a [DID method](#dfn-did-methods) specification also defines the mechanisms for creating, resolving, updating, and deactivating [DIDs](#dfn-decentralized-identifiers) and [DID documents](#dfn-did-documents) using a specific type of [verifiable data registry](#dfn-verifiable-data-registry). It also documents all implementation considerations related to [DIDs](#dfn-decentralized-identifiers) as well as Security and Privacy Considerations. + +This section specifies the requirements for authoring [DID method](#dfn-did-methods) specifications. + +### 8.1 Method Syntax + +[](#method-syntax) + +The requirements for all [DID method](#dfn-did-methods) specifications when defining the method-specific DID Syntax are as follows: + +1. A [DID method](#dfn-did-methods) specification *MUST* define exactly one method-specific [DID scheme](#dfn-did-schemes) that is identified by exactly one method name as specified by the `method-name` rule in [3.1 DID Syntax](#did-syntax). +2. The [DID method](#dfn-did-methods) specification *MUST* specify how to generate the `method-specific-id` component of a [DID](#dfn-decentralized-identifiers). +3. The [DID method](#dfn-did-methods) specification *MUST* define sensitivity and normalization of the value of the `method-specific-id`. +4. The `method-specific-id` value *MUST* be unique within a [DID method](#dfn-did-methods). The `method-specific-id` value itself might be globally unique. +5. Any [DID](#dfn-decentralized-identifiers) generated by a [DID method](#dfn-did-methods) *MUST* be globally unique. +6. To reduce the chances of `method-name` conflicts, a [DID method](#dfn-did-methods) specification *SHOULD* be registered in the DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\]. +7. A [DID method](#dfn-did-methods) *MAY* define multiple `method-specific-id` formats. +8. The `method-specific-id` format *MAY* include colons. The use of colons *MUST* comply syntactically with the `method-specific-id` ABNF rule. +9. A [DID method](#dfn-did-methods) specification *MAY* specify ABNF rules for [DID paths](#dfn-did-paths) that are more restrictive than the generic rules in [Path](#path). +10. A [DID method](#dfn-did-methods) specification *MAY* specify ABNF rules for [DID queries](#dfn-did-queries) that are more restrictive than the generic rules in this section. +11. A [DID method](#dfn-did-methods) specification *MAY* specify ABNF rules for [DID fragments](#dfn-did-fragments) that are more restrictive than the generic rules in this section. + +Note: Colons in method-specific-id + +The meaning of colons in the `method-specific-id` is entirely method-specific. Colons might be used by [DID methods](#dfn-did-methods) for establishing hierarchically partitioned namespaces, for identifying specific instances or parts of the [verifiable data registry](#dfn-verifiable-data-registry), or for other purposes. Implementers are advised to avoid assuming any meanings or behaviors associated with a colon that are generically applicable to all [DID methods](#dfn-did-methods). + +### 8.2 Method Operations + +[](#method-operations) + +The requirements for all [DID method](#dfn-did-methods) specifications when defining the method operations are as follows: + +1. A [DID method](#dfn-did-methods) specification *MUST* define how authorization is performed to execute all operations, including any necessary cryptographic processes. +2. A [DID method](#dfn-did-methods) specification *MUST* specify how a [DID controller](#dfn-did-controllers) creates a [DID](#dfn-decentralized-identifiers) and its associated [DID document](#dfn-did-documents). +3. A [DID method](#dfn-did-methods) specification *MUST* specify how a [DID resolver](#dfn-did-resolvers) uses a [DID](#dfn-decentralized-identifiers) to resolve a [DID document](#dfn-did-documents), including how the [DID resolver](#dfn-did-resolvers) can verify the authenticity of the response. +4. A [DID method](#dfn-did-methods) specification *MUST* specify what constitutes an update to a [DID document](#dfn-did-documents) and how a [DID controller](#dfn-did-controllers) can update a [DID document](#dfn-did-documents) *or* state that updates are not possible. +5. The [DID method](#dfn-did-methods) specification *MUST* specify how a [DID controller](#dfn-did-controllers) can deactivate a [DID](#dfn-decentralized-identifiers) *or* state that deactivation is not possible. + +The authority of a party that is performing authorization to carry out the operations is specific to a [DID method](#dfn-did-methods). For example, a [DID method](#dfn-did-methods) might --- + +- make use of the [`controller`](#dfn-controller) property. +- use the [verification methods](#dfn-verification-method) listed under [`authentication`](#dfn-authentication). +- use other constructs in the [DID Document](#dfn-did-documents) such as the [verification method](#dfn-verification-method) specified via the [`capabilityInvocation`](#dfn-capabilityinvocation) [verification relationship](#dfn-verification-relationship). +- not use the [DID document](#dfn-did-documents) for this decision at all, and depend on an out-of-band mechanism, instead. + +### 8.3 Security Requirements + +[](#security-requirements) + +The requirements for all [DID method](#dfn-did-methods) specifications when authoring the *Security Considerations* section are as follows: + +1. A [DID method](#dfn-did-methods) specifications *MUST* follow all guidelines and normative language provided in [RFC3552: Writing Security Considerations Sections](https://www.rfc-editor.org/rfc/rfc3552#section-5) for the [DID](#dfn-decentralized-identifiers) operations defined in the [DID method](#dfn-did-methods) specification. +2. The Security Considerations section *MUST* document the following forms of attack for the [DID](#dfn-decentralized-identifiers) operations defined in the [DID method](#dfn-did-methods) specification: eavesdropping, replay, message insertion, deletion, modification, denial of service, [amplification](#dfn-amplification), and man-in-the-middle. Other known forms of attack *SHOULD* also be documented. +3. The Security Considerations section *MUST* discuss residual risks, such as the risks from compromise in a related protocol, incorrect implementation, or cipher after threat mitigation was deployed. +4. The Security Considerations section *MUST* provide integrity protection and update authentication for all operations required by Section [8.2 Method Operations](#method-operations). +5. If authentication is involved, particularly user-host authentication, the security characteristics of the authentication method *MUST* be clearly documented. +6. The Security Considerations section *MUST* discuss the policy mechanism by which [DIDs](#dfn-decentralized-identifiers) are proven to be uniquely assigned. +7. Method-specific endpoint authentication *MUST* be discussed. Where [DID methods](#dfn-did-methods) make use of [DLTs](#dfn-distributed-ledger-technology) with varying network topology, sometimes offered as *light node* or *[thin client](https://en.bitcoin.it/wiki/Thin_Client_Security)* implementations to reduce required computing resources, the security assumptions of the topology available to implementations of the [DID method](#dfn-did-methods) *MUST* be discussed. +8. If a protocol incorporates cryptographic protection mechanisms, the [DID method](#dfn-did-methods) specification *MUST* clearly indicate which portions of the data are protected and by what protections, and it *SHOULD* give an indication of the sorts of attacks to which the cryptographic protection is susceptible. Some examples are integrity only, confidentiality, and endpoint authentication. +9. Data which is to be held secret (keying material, random seeds, and so on) *SHOULD* be clearly labeled. +10. [DID method](#dfn-did-methods) specifications *SHOULD* explain and specify the implementation of signatures on [DID documents](#dfn-did-documents), if applicable. +11. Where [DID methods](#dfn-did-methods) use peer-to-peer computing resources, such as with all known [DLTs](#dfn-distributed-ledger-technology), the expected burdens of those resources *SHOULD* be discussed in relation to denial of service. +12. [DID methods](#dfn-did-methods) that introduce new authentication [service](#dfn-service) types, as described in [5.4 Services](#services), *SHOULD* consider the security requirements of the supported authentication protocol. + +### 8.4 Privacy Requirements + +[](#privacy-requirements) + +The requirements for all [DID method](#dfn-did-methods) specifications when authoring the *Privacy Considerations* section are: + +1. The [DID method](#dfn-did-methods) specification\'s Privacy Considerations section *MUST* discuss any subsection of Section 5 of \[[RFC6973](#bib-rfc6973 "Privacy Considerations for Internet Protocols")\] that could apply in a method-specific manner. The subsections to consider are: surveillance, stored data compromise, unsolicited traffic, misattribution, correlation, identification, secondary use, disclosure, and exclusion. + +## 9. Security Considerations + +[](#security-considerations) + +*This section is non-normative.* + +This section contains a variety of security considerations that people using Decentralized Identifiers are advised to consider before deploying this technology in a production setting. [DIDs](#dfn-decentralized-identifiers) are designed to operate under the threat model used by many IETF standards and documented in \[[RFC3552](#bib-rfc3552 "Guidelines for Writing RFC Text on Security Considerations")\]. This section elaborates upon a number of the considerations in \[[RFC3552](#bib-rfc3552 "Guidelines for Writing RFC Text on Security Considerations")\], as well as other considerations that are unique to [DID](#dfn-decentralized-identifiers) architecture. + +### 9.1 Choosing DID Resolvers + +[](#choosing-did-resolvers) + +The DID Specification Registries \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\] contains an informative list of [DID method](#dfn-did-methods) names and their corresponding [DID method](#dfn-did-methods) specifications. Implementers need to bear in mind that there is no central authority to mandate which [DID method](#dfn-did-methods) specification is to be used with any specific [DID method](#dfn-did-methods) name. If there is doubt on whether or not a specific [DID resolver](#dfn-did-resolvers) implements a [DID method](#dfn-did-methods) correctly, the DID Specification Registries can be used to look up the registered specification and make an informed decision regarding which [DID resolver](#dfn-did-resolvers) implementation to use. + +### 9.2 Proving Control and Binding + +[](#proving-control-and-binding) + +Binding an entity in the digital world or the physical world to a [DID](#dfn-decentralized-identifiers), to a [DID document](#dfn-did-documents), or to cryptographic material requires, the use of security protocols contemplated by this specification. The following sections describe some possible scenarios and how an entity therein might prove control over a [DID](#dfn-decentralized-identifiers) or a [DID document](#dfn-did-documents) for the purposes of authentication or authorization. + +#### Proving Control of a DID and/or DID Document + +[](#proving-control-of-a-did-and-or-did-document) + +Proving control over a [DID](#dfn-decentralized-identifiers) and/or a [DID Document](#dfn-did-documents) is useful when updating either in a [verifiable data registry](#dfn-verifiable-data-registry) or authenticating with remote systems. Cryptographic digital signatures and [verifiable timestamps](#dfn-verifiable-timestamp) enable certain security protocols related to [DID documents](#dfn-did-documents) to be cryptographically verifiable. For these purposes, this specification defines useful [verification relationships](#dfn-verification-relationship) in [5.3.1 Authentication](#authentication) and [5.3.4 Capability Invocation](#capability-invocation). The secret cryptographic material associated with the [verification methods](#dfn-verification-method) can be used to generate a cryptographic digital signature as a part of an authentication or authorization security protocol. + +Note: Signed DID documents + +Some [DID methods](#dfn-did-methods) allow digital signatures and other proofs to be included in the [DID document](#dfn-did-documents) or a [7.3 Metadata Structure](#metadata-structure). However, such proofs by themselves do not necessarily prove control over a [DID](#dfn-decentralized-identifiers), or guarantee that the [DID document](#dfn-did-documents) is the correct one for the [DID](#dfn-decentralized-identifiers). In order to obtain the correct [DID document](#dfn-did-documents) and verify control over a [DID](#dfn-decentralized-identifiers), it is necessary to perform the [DID resolution](#dfn-did-resolution) process as defined by the [DID method](#dfn-did-methods). + +#### Binding to Physical Identity + +[](#binding-to-physical-identity) + +A [DID](#dfn-decentralized-identifiers) and [DID document](#dfn-did-documents) do not inherently carry any [personal data](https://en.wikipedia.org/wiki/Personal_data) and it is strongly advised that non-public entities do not publish personal data in [DID documents](#dfn-did-documents). + +It can be useful to express a binding of a [DID](#dfn-decentralized-identifiers) to a person\'s or organization\'s physical identity in a way that is provably asserted by a trusted authority, such as a government. This specification provides the [5.3.2 Assertion](#assertion) [verification relationship](#dfn-verification-relationship) for these purposes. This feature can enable interactions that are private and can be considered legally enforceable under one or more jurisdictions; establishing such bindings has to be carefully balanced against privacy considerations (see [10. Privacy Considerations](#privacy-considerations)). + +The process of binding a [DID](#dfn-decentralized-identifiers) to something in the physical world, such as a person or an organization --- for example, by using [verifiable credentials](#dfn-verifiable-credentials) with the same subject as that [DID](#dfn-decentralized-identifiers) --- is contemplated by this specification and further defined in the Verifiable Credentials Data Model \[[VC-DATA-MODEL](#bib-vc-data-model "Verifiable Credentials Data Model v1.1")\]. + +### 9.3 Authentication Service Endpoints + +[](#authentication-service-endpoints) + +If a [DID document](#dfn-did-documents) publishes a [service](#dfn-service) intended for authentication or authorization of the [DID subject](#dfn-did-subjects) (see Section [5.4 Services](#services)), it is the responsibility of the [service endpoint](#dfn-service-endpoints) provider, subject, or requesting party to comply with the requirements of the authentication protocols supported at that [service endpoint](#dfn-service-endpoints). + +### 9.4 Non-Repudiation + +[](#non-repudiation) + +Non-repudiation of [DIDs](#dfn-decentralized-identifiers) and [DID document](#dfn-did-documents) updates is supported if: + +- The [verifiable data registry](#dfn-verifiable-data-registry) supports [verifiable timestamps](#dfn-verifiable-timestamp). See [7.1.3 DID Document Metadata](#did-document-metadata) for further information on useful timestamps that can be used during the [DID resolution](#dfn-did-resolution) process. +- The subject is monitoring for unauthorized updates as elaborated upon in [9.5 Notification of DID Document Changes](#notification-of-did-document-changes). +- The subject has had adequate opportunity to revert malicious updates according to the authorization mechanism for the [DID method](#dfn-did-methods). + +### 9.5 Notification of DID Document Changes + +[](#notification-of-did-document-changes) + +One mitigation against unauthorized changes to a [DID document](#dfn-did-documents) is monitoring and actively notifying the [DID subject](#dfn-did-subjects) when there are changes. This is analogous to helping prevent account takeover on conventional username/password accounts by sending password reset notifications to the email addresses on file. + +In the case of a [DID](#dfn-decentralized-identifiers), there is no intermediary registrar or account provider to generate such notifications. However, if the [verifiable data registry](#dfn-verifiable-data-registry) on which the [DID](#dfn-decentralized-identifiers) is registered directly supports change notifications, a subscription service can be offered to [DID controllers](#dfn-did-controllers). Notifications could be sent directly to the relevant [service endpoints](#dfn-service-endpoints) listed in an existing [DID](#dfn-decentralized-identifiers). + +If a [DID controller](#dfn-did-controllers) chooses to rely on a third-party monitoring service (other than the [verifiable data registry](#dfn-verifiable-data-registry) itself), this introduces another vector of attack. + +### 9.6 Key and Signature Expiration + +[](#key-and-signature-expiration) + +In a [decentralized identifier](#dfn-decentralized-identifiers) architecture, there might not be centralized authorities to enforce cryptographic material or cryptographic digital signature expiration policies. Therefore, it is with supporting software such as [DID resolvers](#dfn-did-resolvers) and verification libraries that requesting parties validate that cryptographic material were not expired at the time they were used. Requesting parties might employ their own expiration policies in addition to inputs into their verification processes. For example, some requesting parties might accept authentications from five minutes in the past, while others with access to high precision time sources might require authentications to be time stamped within the last 500 milliseconds. + +There are some requesting parties that have legitimate needs to extend the use of already-expired cryptographic material, such as verifying legacy cryptographic digital signatures. In these scenarios, a requesting party might instruct their verification software to ignore cryptographic key material expiration or determine if the cryptographic key material was expired at the time it was used. + +### 9.7 Verification Method Rotation + +[](#verification-method-rotation) + +Rotation is a management process that enables the secret cryptographic material associated with an existing [verification method](#dfn-verification-method) to be deactivated or destroyed once a new [verification method](#dfn-verification-method) has been added to the [DID document](#dfn-did-documents). Going forward, any new proofs that a [controller](#dfn-controller) would have generated using the old secret cryptographic material can now instead be generated using the new cryptographic material and can be verified using the new [verification method](#dfn-verification-method). + +Rotation is a useful mechanism for protecting against verification method compromise, since frequent rotation of a verification method by the controller reduces the value of a single compromised verification method to an attacker. Performing revocation immediately after rotation is useful for verification methods that a controller designates for short-lived verifications, such as those involved in encrypting messages and authentication. + +The following considerations might be of use when contemplating the use of [verification method](#dfn-verification-method) rotation: + +- [Verification method](#dfn-verification-method) rotation is a proactive security measure. +- It is generally considered a best practice to perform [verification method](#dfn-verification-method) rotation on a regular basis. +- Higher security environments tend to employ more frequent verification method rotation. +- [Verification method](#dfn-verification-method) rotation manifests only as changes to the current or latest version of a [DID document](#dfn-did-documents). +- When a [verification method](#dfn-verification-method) has been active for a long time, or used for many operations, a controller might wish to perform a rotation. +- Frequent rotation of a [verification method](#dfn-verification-method) might be frustrating for parties that are forced to continuously renew or refresh associated credentials. +- Proofs or signatures that rely on [verification methods](#dfn-verification-method) that are not present in the latest version of a [DID document](#dfn-did-documents) are not impacted by rotation. In these cases, verification software might require additional information, such as when a particular [verification method](#dfn-verification-method) was expected to be valid as well as access to a [verifiable data registry](#dfn-verifiable-data-registry) containing a historical record, to determine the validity of the proof or signature. This option might not be available in all [DID methods](#dfn-did-methods). +- The section on [DID method operations](#method-operations) specifies the [DID](#dfn-decentralized-identifiers) operations to be supported by a [DID method](#dfn-did-methods) specification, including [update](#method-operations) which is expected to be used to perform a [verification method](#dfn-verification-method) rotation. +- A [controller](#dfn-controller) performs a rotation when they add a new [verification method](#dfn-verification-method) that is meant to replace an existing [verification method](#dfn-verification-method) after some time. +- Not all [DID methods](#dfn-did-methods) support [verification method](#dfn-verification-method) rotation. + +### 9.8 Verification Method Revocation + +[](#verification-method-revocation) + +Revocation is a management process that enables the secret cryptographic material associated with an existing [verification method](#dfn-verification-method) to be deactivated such that it ceases to be a valid form of creating new proofs of digital signatures. + +Revocation is a useful mechanism for reacting to a verification method compromise. Performing revocation immediately after rotation is useful for verification methods that a controller designates for short-lived verifications, such as those involved in encrypting messages and authentication. + +Compromise of the secrets associated with a [verification method](#dfn-verification-method) allows the attacker to use them according to the [verification relationship](#dfn-verification-relationship) expressed by [controller](#dfn-controller) in the [DID document](#dfn-did-documents), for example, for authentication. The attacker\'s use of the secrets might be indistinguishable from the legitimate [controller\'s](#did-controller) use starting from the time the [verification method](#dfn-verification-method) was registered, to the time it was revoked. + +The following considerations might be of use when contemplating the use of [verification method](#dfn-verification-method) revocation: + +- [Verification method](#dfn-verification-method) revocation is a reactive security measure. +- It is considered a best practice to support key revocation. +- A [controller](#dfn-controller) is expected to immediately revoke any [verification method](#dfn-verification-method) that is known to be compromised. +- [Verification method](#dfn-verification-method) revocation can only be embodied in changes to the latest version of a [DID Document](#dfn-did-documents); it cannot retroactively adjust previous versions. +- As described in [5.2.1 Verification Material](#verification-material), absence of a verification method is the only form of revocation that applies to all [DID Methods](#dfn-did-methods) that support revocation. +- If a [verification method](#dfn-verification-method) is no longer exclusively accessible to the [controller](#dfn-controller) or parties trusted to act on behalf of the [controller](#dfn-controller), it is expected to be revoked immediately to reduce the risk of compromises such as masquerading, theft, and fraud. +- Revocation is expected to be understood as a [controller](#dfn-controller) expressing that proofs or signatures associated with a revoked [verification method](#dfn-verification-method) created after its revocation should be treated as invalid. It could also imply a concern that existing proofs or signatures might have been created by an attacker, but this is not necessarily the case. Verifiers, however, might still choose to accept or reject any such proofs or signatures at their own discretion. +- The section on [DID method operations](#method-operations) specifies the [DID](#dfn-decentralized-identifiers) operations to be supported by a [DID method](#dfn-did-methods) specification, including [update](#method-operations) and [deactivate](#method-operations), which might be used to remove a [verification method](#dfn-verification-method) from a [DID document](#dfn-did-documents). +- Not all [DID methods](#dfn-did-methods) support [verification method](#dfn-verification-method) revocation. +- Even if a [verification method](#dfn-verification-method) is present in a [DID document](#dfn-did-documents), additional information, such as a public key revocation certificate, or an external allow or deny list, could be used to determine whether a [verification method](#dfn-verification-method) has been revoked. +- The day-to-day operation of any software relying on a compromised [verification method](#dfn-verification-method), such as an individual\'s operating system, antivirus, or endpoint protection software, could be impacted when the [verification method](#dfn-verification-method) is publicly revoked. + +#### Revocation Semantics + +[](#revocation-semantics) + +Although verifiers might choose not to accept proofs or signatures from a revoked verification method, knowing whether a verification was made with a revoked [verification method](#dfn-verification-method) is trickier than it might seem. Some [DID methods](#dfn-did-methods) provide the ability to look back at the state of a [DID](#dfn-decentralized-identifiers) at a point in time, or at a particular version of the [DID document](#dfn-did-documents). When such a feature is combined with a reliable way to determine the time or [DID](#dfn-decentralized-identifiers) version that existed when a cryptographically verifiable statement was made, then revocation does not undo that statement. This can be the basis for using [DIDs](#dfn-decentralized-identifiers) to make binding commitments; for example, to sign a mortgage. + +If these conditions are met, revocation is not retroactive; it only nullifies future use of the method. + +However, in order for such semantics to be safe, the second condition --- an ability to know what the state of the [DID document](#dfn-did-documents) was at the time the assertion was made --- is expected to apply. Without that guarantee, someone could discover a revoked key and use it to make cryptographically verifiable statements with a simulated date in the past. + +Some [DID methods](#dfn-did-methods) only allow the retrieval of the current state of a [DID](#dfn-decentralized-identifiers). When this is true, or when the state of a [DID](#dfn-decentralized-identifiers) at the time of a cryptographically verifiable statement cannot be reliably determined, then the only safe course is to disallow any consideration of DID state with respect to time, except the present moment. [DID](#dfn-decentralized-identifiers) ecosystems that take this approach essentially provide cryptographically verifiable statements as ephemeral tokens that can be invalidated at any time by the [DID controller](#dfn-did-controllers). + +#### Revocation in Trustless Systems + +[](#revocation-in-trustless-systems) + +Trustless systems are those where all trust is derived from cryptographically provable assertions, and more specifically, where no metadata outside of the cryptographic system is factored into the determination of trust in the system. To verify a signature of proof for a [verification method](#dfn-verification-method) which has been revoked in a trustless system, a [DID method](#dfn-did-methods) needs to support either or both of the `versionId` or `versionTime`, as well as both the `updated` and `nextUpdate`, [DID document](#dfn-did-documents) metadata properties. A verifier can validate a signature or proof of a revoked key if and only if all of the following are true: + +- The proof or signature includes the `versionId` or `versionTime` of the [DID document](#dfn-did-documents) that was used at the point the signature or proof was created. +- The verifier can determine the point in time at which the signature or proof was made; for example, it was anchored on a blockchain. +- For the resolved [DID document](#dfn-did-documents) metadata, the `updated` timestamp is before, and the `nextUpdate` timestamp is after, the point in time at which the signature or proof was made. + +In systems that are willing to admit metadata other than those constituting cryptographic input, similar trust may be achieved \-- but always on the same basis where a careful judgment is made about whether a [DID document](#dfn-did-documents)\'s content at the moment of a signing event contained the expected content. + +### 9.9 DID Recovery + +[](#did-recovery) + +Recovery is a reactive security measure whereby a [controller](#dfn-controller) that has lost the ability to perform DID operations, such as through the loss of a device, is able to regain the ability to perform DID operations. + +The following considerations might be of use when contemplating the use of [DID](#dfn-decentralized-identifiers) recovery: + +- Performing recovery proactively on an infrequent but regular basis, can help to ensure that control has not been lost. +- It is considered a best practice to never reuse cryptographic material associated with recovery for any other purposes. +- Recovery is commonly performed in conjunction with [verification method rotation](#verification-method-rotation) and [verification method revocation](#verification-method-revocation). +- Recovery is advised when a [controller](#dfn-controller) or services trusted to act on their behalf no longer have the exclusive ability to perform DID operations as described in [8.2 Method Operations](#method-operations). +- [DID method](#dfn-did-methods) specifications might choose to enable support for a quorum of trusted parties to facilitate recovery. Some of the facilities to do so are suggested in [5.1.2 DID Controller](#did-controller). +- Not all [DID method](#dfn-did-methods) specifications will recognize control from [DIDs](#dfn-decentralized-identifiers) registered using other [DID methods](#dfn-did-methods) and they might restrict third-party control to [DIDs](#dfn-decentralized-identifiers) that use the same method. +- Access control and recovery in a [DID method](#dfn-did-methods) specification can also include a time lock feature to protect against key compromise by maintaining a second track of control for recovery. +- There are currently no common recovery mechanisms that apply to all [DID methods](#dfn-did-methods). + +### 9.10 The Role of Human-Friendly Identifiers + +[](#the-role-of-human-friendly-identifiers) + +[DIDs](#dfn-decentralized-identifiers) achieve global uniqueness without the need for a central registration authority. This comes at the cost of human memorability. Algorithms capable of generating globally unambiguous identifiers produce random strings of characters that have no human meaning. This trade-off is often referred to as [Zooko\'s Triangle](https://en.wikipedia.org/wiki/Zooko%27s_triangle). + +There are use cases where it is desirable to discover a [DID](#dfn-decentralized-identifiers) when starting from a human-friendly identifier. For example, a natural language name, a domain name, or a conventional address for a [DID controller](#dfn-did-controllers), such as a mobile telephone number, email address, social media username, or blog URL. However, the problem of mapping human-friendly identifiers to [DIDs](#dfn-decentralized-identifiers), and doing so in a way that can be verified and trusted, is outside the scope of this specification. + +Solutions to this problem are defined in separate specifications, such as \[[DNS-DID](#bib-dns-did "The Decentralized Identifier (DID) in the DNS")\], that reference this specification. It is strongly recommended that such specifications carefully consider the: + +- Numerous security attacks based on deceiving users about the true human-friendly identifier for a target entity. +- Privacy consequences of using human-friendly identifiers that are inherently correlatable, especially if they are globally unique. + +### 9.11 DIDs as Enhanced URNs + +[](#dids-as-enhanced-urns) + +If desired by a [DID controller](#dfn-did-controllers), a [DID](#dfn-decentralized-identifiers) or a [DID URL](#dfn-did-urls) is capable of acting as persistent, location-independent resource identifier. These sorts of identifiers are classified as Uniform Resource Names (URNs) and are defined in \[[RFC8141](#bib-rfc8141 "Uniform Resource Names (URNs)")\]. [DIDs](#dfn-decentralized-identifiers) are an enhanced form of URN that provide a cryptographically secure, location-independent identifier for a digital resource, while also providing metadata that enables retrieval. Due to the indirection between the [DID document](#dfn-did-documents) and the [DID](#dfn-decentralized-identifiers) itself, the [DID controller](#dfn-did-controllers) can adjust the actual location of the resource --- or even provide the resource directly --- without adjusting the [DID](#dfn-decentralized-identifiers). [DIDs](#dfn-decentralized-identifiers) of this type can definitively verify that the resource retrieved is, in fact, the resource identified. + +A [DID controller](#dfn-did-controllers) who intends to use a [DID](#dfn-decentralized-identifiers) for this purpose is advised to follow the security considerations in \[[RFC8141](#bib-rfc8141 "Uniform Resource Names (URNs)")\]. In particular: + +- The [DID controller](#dfn-did-controllers) is expected to choose a [DID method](#dfn-did-methods) that supports the controller\'s requirements for persistence. The Decentralized Characteristics Rubric \[[DID-RUBRIC](#bib-did-rubric "Decentralized Characteristics Rubric v1.0")\] is one tool available to help implementers decide upon the most suitable [DID method](#dfn-did-methods). +- The [DID controller](#dfn-did-controllers) is expected to publish its operational policies so requesting parties can determine the degree to which they can rely on the persistence of a [DID](#dfn-decentralized-identifiers) controlled by that [DID controller](#dfn-did-controllers). In the absence of such policies, requesting parties are not expected to make any assumption about whether a [DID](#dfn-decentralized-identifiers) is a persistent identifier for the same [DID subject](#dfn-did-subjects). + +### 9.12 Immutability + +[](#immutability) + +Many cybersecurity abuses hinge on exploiting gaps between reality and the assumptions of rational, good-faith actors. Immutability of [DID documents](#dfn-did-documents) can provide some security benefits. Individual [DID methods](#dfn-did-methods) ought to consider constraints that would eliminate behaviors or semantics they do not need. The more *locked down* a [DID method](#dfn-did-methods) is, while providing the same set of features, the less it can be manipulated by malicious actors. + +As an example, consider that a single edit to a [DID document](#dfn-did-documents) can change anything except the root [`id`](#dfn-id) property of the document. But is it actually desirable for a [service](#dfn-service) to change its `type` after it is defined? Or for a key to change its value? Or would it be better to require a new [`id`](#dfn-id) when certain fundamental properties of an object change? Malicious takeovers of a website often aim for an outcome where the site keeps its host name identifier, but is subtly changed underneath. If certain properties of the site, such as the [ASN](https://en.wikipedia.org/wiki/Autonomous_system_(Internet)) associated with its IP address, were required by the specification to be immutable, anomaly detection would be easier, and attacks would be much harder and more expensive to carry out. + +For [DID methods](#dfn-did-methods) tied to a global source of truth, a direct, just-in-time lookup of the latest version of a [DID document](#dfn-did-documents) is always possible. However, it seems likely that layers of cache might eventually sit between a [DID resolver](#dfn-did-resolvers) and that source of truth. If they do, believing the attributes of an object in the [DID document](#dfn-did-documents) to have a given state when they are actually subtly different might invite exploits. This is particularly true if some lookups are of a full [DID document](#dfn-did-documents), and others are of partial data where the larger context is assumed. + +### 9.13 Encrypted Data in DID Documents + +[](#encrypted-data-in-did-documents) + +Encryption algorithms have been known to fail due to advances in cryptography and computing power. Implementers are advised to assume that any encrypted data placed in a [DID document](#dfn-did-documents) might eventually be made available in clear text to the same audience to which the encrypted data is available. This is particularly pertinent if the [DID document](#dfn-did-documents) is public. + +Encrypting all or parts of a [DID document](#dfn-did-documents) is *not* an appropriate means to protect data in the long term. Similarly, placing encrypted data in a [DID document](#dfn-did-documents) is not an appropriate means to protect personal data. + +Given the caveats above, if encrypted data is included in a [DID document](#dfn-did-documents), implementers are advised to not associate any correlatable information that could be used to infer a relationship between the encrypted data and an associated party. Examples of correlatable information include public keys of a receiving party, identifiers to digital assets known to be under the control of a receiving party, or human readable descriptions of a receiving party. + +### 9.14 Equivalence Properties + +[](#equivalence-properties) + +Given the [`equivalentId`](#dfn-equivalentid) and [`canonicalId`](#dfn-canonicalid) properties are generated by [DID methods](#dfn-did-methods) themselves, the same security and accuracy guarantees that apply to the resolved [DID](#dfn-decentralized-identifiers) present in the `id` field of a [DID document](#dfn-did-documents) also apply to these properties. The [`alsoKnownAs`](#dfn-alsoknownas) property is not guaranteed to be an accurate statement of equivalence, and should not be relied upon without performing validation steps beyond the resolution of the [DID document](#dfn-did-documents). + +The [`equivalentId`](#dfn-equivalentid) and [`canonicalId`](#dfn-canonicalid) properties express equivalence assertions to variants of a single [DID](#dfn-decentralized-identifiers) produced by the same [DID method](#dfn-did-methods) and can be trusted to the extent the requesting party trusts the [DID method](#dfn-did-methods) and a conforming producer and resolver. + +The [`alsoKnownAs`](#dfn-alsoknownas) property permits an equivalence assertion to [URIs](#dfn-uri) that are not governed by the same [DID method](#dfn-did-methods) and cannot be trusted without performing verification steps outside of the governing [DID method](#dfn-did-methods). See additional guidance in [5.1.3 Also Known As](#also-known-as). + +As with any other security-related properties in the [DID document](#dfn-did-documents), parties relying on any equivalence statement in a [DID document](#dfn-did-documents) should guard against the values of these properties being substituted by an attacker after the proper verification has been performed. Any write access to a [DID document](#dfn-did-documents) stored in memory or disk after verification has been performed is an attack vector that might circumvent verification unless the [DID document](#dfn-did-documents) is re-verified. + +### 9.15 Content Integrity Protection + +[](#content-integrity-protection) + +[DID documents](#dfn-did-documents) which include links to external machine-readable content such as images, web pages, or schemas are vulnerable to tampering. It is strongly advised that external links are integrity protected using solutions such as a hashlink \[[HASHLINK](#bib-hashlink "Cryptographic Hyperlinks")\]. External links are to be avoided if they cannot be integrity protected and the [DID document](#dfn-did-documents)\'s integrity is dependent on the external link. + +One example of an external link where the integrity of the [DID document](#dfn-did-documents) itself could be affected is the JSON-LD Context \[[JSON-LD11](#bib-json-ld11 "JSON-LD 1.1")\]. To protect against compromise, [DID document](#dfn-did-documents) consumers are advised to cache local static copies of JSON-LD contexts and/or verify the integrity of external contexts against a cryptographic hash that is known to be associated with a safe version of the external JSON-LD Context. + +### 9.16 Persistence + +[](#persistence) + +[DIDs](#dfn-decentralized-identifiers) are designed to be persistent such that a [controller](#dfn-controller) need not rely upon a single trusted third party or administrator to maintain their identifiers. In an ideal case, no administrator can take control away from the [controller](#dfn-controller), nor can an administrator prevent their identifiers\' use for any particular purpose such as authentication, authorization, and attestation. No third party can act on behalf of a [controller](#dfn-controller) to remove or render inoperable an entity\'s identifier without the [controller](#dfn-controller)\'s consent. + +However, it is important to note that in all [DID methods](#dfn-did-methods) that enable cryptographic proof-of-control, the means of proving control can always be transferred to another party by transferring the secret cryptographic material. Therefore, it is vital that systems relying on the persistence of an identifier over time regularly check to ensure that the identifier is, in fact, still under the control of the intended party. + +Unfortunately, it is impossible to determine from the cryptography alone whether or not the secret cryptographic material associated with a given [verification method](#dfn-verification-method) has been compromised. It might well be that the expected [controller](#dfn-controller) still has access to the secret cryptographic material --- and as such can execute a proof-of-control as part of a verification process --- while at the same time, a bad actor also has access to those same keys, or to a copy thereof. + +As such, cryptographic proof-of-control is expected to only be used as one factor in evaluating the level of identity assurance required for high-stakes scenarios. [DID](#dfn-decentralized-identifiers)-based authentication provides much greater assurance than a username and password, thanks to the ability to determine control over a cryptographic secret without transmitting that secret between systems. However, it is not infallible. Scenarios that involve sensitive, high value, or life-critical operations are expected to use additional factors as appropriate. + +In addition to potential ambiguity from use by different [controllers](#dfn-controller), it is impossible to guarantee, in general, that a given [DID](#dfn-decentralized-identifiers) is being used in reference to the same subject at any given point in time. It is technically possible for the controller to reuse a [DID](#dfn-decentralized-identifiers) for different subjects and, more subtly, for the precise definition of the subject to either change over time or be misunderstood. + +For example, consider a [DID](#dfn-decentralized-identifiers) used for a sole proprietorship, receiving various credentials used for financial transactions. To the [controller](#dfn-controller), that identifier referred to the business. As the business grows, it eventually gets incorporated as a Limited Liability Company. The [controller](#dfn-controller) continues using that same [DID](#dfn-decentralized-identifiers), because to **them** the [DID](#dfn-decentralized-identifiers) refers to the business. However, to the state, the tax authority, and the local municipality, the [DID](#dfn-decentralized-identifiers) no longer refers to the same entity. Whether or not the subtle shift in meaning matters to a credit provider or supplier is necessarily up to them to decide. In many cases, as long as the bills get paid and collections can be enforced, the shift is immaterial. + +Due to these potential ambiguities, [DIDs](#dfn-decentralized-identifiers) are to be considered valid *contextually* rather than absolutely. Their persistence does not imply that they refer to the exact same subject, nor that they are under the control of the same [controller](#dfn-controller). Instead, one needs to understand the context in which the [DID](#dfn-decentralized-identifiers) was created, how it is used, and consider the likely shifts in their meaning, and adopt procedures and policies to address both potential and inevitable semantic drift. + +### 9.17 Level of Assurance + +[](#level-of-assurance) + +Additional information about the security context of authentication events is often required for compliance reasons, especially in regulated areas such as the financial and public sectors. This information is often referred to as a Level of Assurance (LOA). Examples include the protection of secret cryptographic material, the identity proofing process, and the form-factor of the authenticator. + +[Payment services (PSD 2)](https://ec.europa.eu/info/law/payment-services-psd-2-directive-eu-2015-2366_en) and [eIDAS](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=uriserv:OJ.L_.2014.257.01.0073.01.ENG) introduce such requirements to the security context. Level of assurance frameworks are classified and defined by regulations and standards such as [eIDAS](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=uriserv:OJ.L_.2014.257.01.0073.01.ENG), [NIST 800-63-3](https://pages.nist.gov/800-63-3/sp800-63-3.html) and [ISO/IEC 29115:2013](https://www.iso.org/standard/45138.html), including their requirements for the security context, and making recommendations on how to achieve them. This might include strong user authentication where [FIDO2](https://fidoalliance.org/fido2/)/[WebAuthn](https://www.w3.org/TR/webauthn-2/) can fulfill the requirement. + +Some regulated scenarios require the implementation of a specific level of assurance. Since [verification relationships](#dfn-verification-relationship) such as ` `[`assertionMethod`](#dfn-assertionmethod) and [`authentication`](#dfn-authentication) might be used in some of these situations, information about the applied security context might need to be expressed and provided to a *verifier*. Whether and how to encode this information in the [DID document](#dfn-did-documents) data model is out of scope for this specification. Interested readers might note that 1) the information could be transmitted using Verifiable Credentials \[[VC-DATA-MODEL](#bib-vc-data-model "Verifiable Credentials Data Model v1.1")\], and 2) the [DID document](#dfn-did-documents) data model can be extended to incorporate this information as described in [4.1 Extensibility](#extensibility), and where [10. Privacy Considerations](#privacy-considerations) is applicable for such extensions. + +## 10. Privacy Considerations + +[](#privacy-considerations) + +*This section is non-normative.* + +Since [DIDs](#dfn-decentralized-identifiers) and [DID documents](#dfn-did-documents) are designed to be administered directly by the [DID controller(s)](#dfn-did-controllers), it is critically important to apply the principles of Privacy by Design \[[PRIVACY-BY-DESIGN](#bib-privacy-by-design "Privacy by Design")\] to all aspects of the [decentralized identifier](#dfn-decentralized-identifiers) architecture. All seven of these principles have been applied throughout the development of this specification. The design used in this specification does not assume that there is a registrar, hosting company, nor other intermediate service provider to recommend or apply additional privacy safeguards. Privacy in this specification is preventive, not remedial, and is an embedded default. The following sections cover privacy considerations that implementers might find useful when building systems that utilize [decentralized identifiers](#dfn-decentralized-identifiers). + +### 10.1 Keep Personal Data Private + +[](#keep-personal-data-private) + +If a [DID method](#dfn-did-methods) specification is written for a public-facing [verifiable data registry](#dfn-verifiable-data-registry) where corresponding [DIDs](#dfn-decentralized-identifiers) and [DID documents](#dfn-did-documents) might be made publicly available, it is *critical* that those [DID documents](#dfn-did-documents) contain no personal data. Personal data can instead be transmitted through other means such as 1) Verifiable Credentials \[[VC-DATA-MODEL](#bib-vc-data-model "Verifiable Credentials Data Model v1.1")\], or 2) [service endpoints](#dfn-service-endpoints) under control of the [DID subject](#dfn-did-subjects) or [DID controller](#dfn-did-controllers). + +Due diligence is expected to be taken around the use of URLs in [service endpoints](#dfn-service-endpoints) to prevent leakage of personal data or correlation within a URL of a [service endpoint](#dfn-service-endpoints). For example, a URL that contains a username is dangerous to include in a [DID Document](#dfn-did-documents) because the username is likely to be human-meaningful in a way that can reveal information that the [DID subject](#dfn-did-subjects) did not consent to sharing. With the privacy architecture suggested by this specification, personal data can be exchanged on a private, peer-to-peer basis using communication channels identified and secured by [verification methods](#dfn-verification-method) in [DID documents](#dfn-did-documents). This also enables [DID subjects](#dfn-did-subjects) and requesting parties to implement the [GDPR](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation) [right to be forgotten](https://en.wikipedia.org/wiki/Right_to_be_forgotten), because no personal data is written to an immutable [distributed ledger](#dfn-distributed-ledger-technology). + +### 10.2 DID Correlation Risks + +[](#did-correlation-risks) + +Like any type of globally unambiguous identifier, [DIDs](#dfn-decentralized-identifiers) might be used for correlation. [DID controllers](#dfn-did-controllers) can mitigate this privacy risk by using pairwise [DIDs](#dfn-decentralized-identifiers) that are unique to each relationship; in effect, each [DID](#dfn-decentralized-identifiers) acts as a pseudonym. A pairwise [DID](#dfn-decentralized-identifiers) need only be shared with more than one party when correlation is explicitly desired. If pairwise [DIDs](#dfn-decentralized-identifiers) are the default, then the only need to publish a [DID](#dfn-decentralized-identifiers) openly, or to share it with multiple parties, is when the [DID controller(s)](#dfn-did-controllers) and/or [DID subject](#dfn-did-subjects) explicitly desires public identification and correlation. + +### 10.3 DID Document Correlation Risks + +[](#did-document-correlation-risks) + +The anti-correlation protections of pairwise [DIDs](#dfn-decentralized-identifiers) are easily defeated if the data in the corresponding [DID documents](#dfn-did-documents) can be correlated. For example, using identical [verification methods](#dfn-verification-method) or bespoke [service endpoints](#dfn-service-endpoints) in multiple [DID documents](#dfn-did-documents) can provide as much correlation information as using the same [DID](#dfn-decentralized-identifiers). Therefore, the [DID document](#dfn-did-documents) for a pairwise [DID](#dfn-decentralized-identifiers) also needs to use pairwise unique information, such as ensuring that [verification methods](#dfn-verification-method) are unique to the pairwise relationship. + +It might seem natural to also use pairwise unique [service endpoints](#dfn-service-endpoints) in the [DID document](#dfn-did-documents) for a pairwise [DID](#dfn-decentralized-identifiers). However, unique endpoints allow all traffic between two [DIDs](#dfn-decentralized-identifiers) to be isolated perfectly into unique buckets, where timing correlation and similar analysis is easy. Therefore, a better strategy for endpoint privacy might be to share an endpoint among a large number of [DIDs](#dfn-decentralized-identifiers) controlled by many different subjects (see [10.5 Herd Privacy](#herd-privacy)). + +### 10.4 DID Subject Classification + +[](#did-subject-classification) + +It is dangerous to add properties to the [DID document](#dfn-did-documents) that can be used to indicate, explicitly or through inference, what *type* or nature of thing the [DID subject](#dfn-did-subjects) is, particularly if the [DID subject](#dfn-did-subjects) is a person. + +Not only do such properties potentially result in personal data (see [10.1 Keep Personal Data Private](#keep-personal-data-private)) or correlatable data (see [10.2 DID Correlation Risks](#did-correlation-risks) and [10.3 DID Document Correlation Risks](#did-document-correlation-risks)) being present in the [DID document](#dfn-did-documents), but they can be used for grouping particular [DIDs](#dfn-decentralized-identifiers) in such a way that they are included in or excluded from certain operations or functionalities. + +Including *type* information in a [DID Document](#dfn-did-documents) can result in personal privacy harms even for [DID Subjects](#dfn-did-subjects) that are non-person entities, such as IoT devices. The aggregation of such information around a [DID Controller](#dfn-did-controllers) could serve as a form of digital fingerprint and this is best avoided. + +To minimize these risks, all properties in a [DID document](#dfn-did-documents) ought to be for expressing cryptographic material, endpoints, or [verification methods](#dfn-verification-method) related to using the [DID](#dfn-decentralized-identifiers). + +### 10.5 Herd Privacy + +[](#herd-privacy) + +When a [DID subject](#dfn-did-subjects) is indistinguishable from others in the herd, privacy is available. When the act of engaging privately with another party is by itself a recognizable flag, privacy is greatly diminished. + +[DIDs](#dfn-decentralized-identifiers) and [DID methods](#dfn-did-methods) need to work to improve herd privacy, particularly for those who legitimately need it most. Choose technologies and human interfaces that default to preserving anonymity and pseudonymity. To reduce [digital fingerprints](https://en.wikipedia.org/wiki/Device_fingerprint), share common settings across requesting party implementations, keep negotiated options to a minimum on wire protocols, use encrypted transport layers, and pad messages to standard lengths. + +### 10.6 Service Privacy + +[](#service-privacy) + +The ability for a [controller](#dfn-controller) to optionally express at least one [service endpoint](#dfn-service-endpoints) in the [DID document](#dfn-did-documents) increases their control and agency. Each additional endpoint in the [DID document](#dfn-did-documents) adds privacy risk either due to correlation, such as across endpoint descriptions, or because the [services](#dfn-service) are not protected by an authorization mechanism, or both. + +[DID documents](#dfn-did-documents) are often public and, since they are standardized, will be stored and indexed efficiently by their very standards-based nature. This risk is worse if [DID documents](#dfn-did-documents) are published to immutable [verifiable data registries](#dfn-verifiable-data-registry). Access to a history of the [DID documents](#dfn-did-documents) referenced by a [DID](#dfn-decentralized-identifiers) represents a form of traffic analysis made more efficient through the use of standards. + +The degree of additional privacy risk caused by using multiple [service endpoints](#dfn-service-endpoints) in one [DID document](#dfn-did-documents) can be difficult to estimate. Privacy harms are typically unintended consequences. [DIDs](#dfn-decentralized-identifiers) can refer to documents, [services](#dfn-service), schemas, and other things that might be associated with individual people, households, clubs, and employers --- and correlation of their [service endpoints](#dfn-service-endpoints) could become a powerful surveillance and inference tool. An example of this potential harm can be seen when multiple common country-level top level domains such as `https://example.co.uk` might be used to infer the approximate location of the [DID subject](#dfn-did-subjects) with a greater degree of probability. + +#### Maintaining Herd Privacy + +[](#maintaining-herd-privacy) + +The variety of possible endpoints makes it particularly challenging to maintain herd privacy, in which no information about the [DID subject](#dfn-did-subjects) is leaked (see [10.5 Herd Privacy](#herd-privacy)). + +First, because service endpoints might be specified as [URIs](#dfn-uri), they could unintentionally leak personal information because of the architecture of the service. For example, a service endpoint of `http://example.com/MyFirstName` is leaking the term `MyFirstName` to everyone who can access the [DID document](#dfn-did-documents). When linking to legacy systems, this is an unavoidable risk, and care is expected to be taken in such cases. This specification encourages new, [DID](#dfn-decentralized-identifiers)-aware endpoints to use nothing more than the [DID](#dfn-decentralized-identifiers) itself for any identification necessary. For example, if a service description were to include `http://example.com/did%3Aexample%3Aabc123`, no harm would be done because `did:example:abc123` is already exposed in the DID Document; it leaks no additional information. + +Second, because a [DID document](#dfn-did-documents) can list multiple service endpoints, it is possible to irreversibly associate services that are not associated in any other context. This correlation on its own may lead to privacy harms by revealing information about the [DID subject](#dfn-did-subjects), even if the [URIs](#dfn-uri) used did not contain any sensitive information. + +Third, because some types of [DID subjects](#dfn-did-subjects) might be more or less likely to list specific endpoints, the listing of a given service could, by itself, leak information that can be used to infer something about the [DID subject](#dfn-did-subjects). For example, a [DID](#dfn-decentralized-identifiers) for an automobile might include a pointer to a public title record at the Department of Motor Vehicles, while a [DID](#dfn-decentralized-identifiers) for an individual would not include that information. + +It is the goal of herd privacy to ensure that the nature of specific [DID subjects](#dfn-did-subjects) is obscured by the population of the whole. To maximize herd privacy, implementers need to rely on one --- and only one --- service endpoint, with that endpoint providing a proxy or mediator service that the controller is willing to depend on, to protect such associations and to blind requests to the ultimate service. + +#### Service Endpoint Alternatives + +[](#service-endpoint-alternatives) + +Given the concerns in the previous section, implementers are urged to consider any of the following service endpoint approaches: + +- **Negotiator Endpoint** --- Service for negotiating mutually agreeable communications channels, preferably using private set intersection. The output of negotiation is a communication channel and whatever credentials might be needed to access it. +- **Tor Endpoint** ([Tor Onion Router](https://www.torproject.org/about/history/)) --- Provide a privacy-respecting address for reaching service endpoints. Any service that can be provided online can be provided through TOR for additional privacy. +- **Mediator Endpoint** --- [Mediators](https://github.com/hyperledger/aries-rfcs/blob/720bdab50e2d0437fda03028c1b17c69781bdd69/concepts/0046-mediators-and-relays/README.md) provide a generic endpoint, for multiple parties, receive encrypted messages on behalf of those parties, and forward them to the intended recipient. This avoids the need to have a specific endpoint per subject, which could create a correlation risk. This approach is also called a proxy. +- **Confidential Storage** --- Proprietary or confidential personal information might need to be kept off of a [verifiable data registry](#dfn-verifiable-data-registry) to provide additional privacy and/or security guarantees, especially for those [DID methods](#dfn-did-methods) where [DID documents](#dfn-did-documents) are published on a public ledger. Pointing to external resource services provides a means for authorization checks and deletion. +- **Polymorphic Proxy** --- A proxy endpoint that can act as any number of services, depending on how it is called. For example, the same URL could be used for both negotiator and mediator functions, depending on a mechanism for re-routing. + +These service endpoint types continue to be an area of innovation and exploration. + +## A. Examples + +[](#examples) + +### A.1 DID Documents + +[](#did-documents) + +*This section is non-normative.* + +See [Verification Method Types](https://www.w3.org/TR/did-spec-registries/#verification-method-types) \[[DID-SPEC-REGISTRIES](#bib-did-spec-registries "DID Specification Registries")\] for optional extensions and other verification method types. + +Note + +These examples are for information purposes only, it is considered a best practice to avoid using the same [verification method](#dfn-verification-method) for multiple purposes. + +[Example 30](#example-did-document-with-1-verification-method-type): DID Document with 1 verification method type + +``` {aria-busy="false"} + { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ], + "id": "did:example:123", + "authentication": [ + { + "id": "did:example:123#z6MkecaLyHuYWkayBDLw5ihndj3T1m6zKTGqau3A51G7RBf3", + "type": "Ed25519VerificationKey2020", // external (property value) + "controller": "did:example:123", + "publicKeyMultibase": "zAKJP3f7BD6W4iWEQ9jwndVTCBq8ua2Utt8EEjJ6Vxsf" + } + ], + "capabilityInvocation": [ + { + "id": "did:example:123#z6MkhdmzFu659ZJ4XKj31vtEDmjvsi5yDZG5L7Caz63oP39k", + "type": "Ed25519VerificationKey2020", // external (property value) + "controller": "did:example:123", + "publicKeyMultibase": "z4BWwfeqdp1obQptLLMvPNgBw48p7og1ie6Hf9p5nTpNN" + } + ], + "capabilityDelegation": [ + { + "id": "did:example:123#z6Mkw94ByR26zMSkNdCUi6FNRsWnc2DFEeDXyBGJ5KTzSWyi", + "type": "Ed25519VerificationKey2020", // external (property value) + "controller": "did:example:123", + "publicKeyMultibase": "zHgo9PAmfeoxHG8Mn2XHXamxnnSwPpkyBHAMNF3VyXJCL" + } + ], + "assertionMethod": [ + { + "id": "did:example:123#z6MkiukuAuQAE8ozxvmahnQGzApvtW7KT5XXKfojjwbdEomY", + "type": "Ed25519VerificationKey2020", // external (property value) + "controller": "did:example:123", + "publicKeyMultibase": "z5TVraf9itbKXrRvt2DSS95Gw4vqU3CHAdetoufdcKazA" + } + ] +} +``` + +[Example 31](#example-did-document-with-many-different-key-types): DID Document with many different key types + +``` {aria-busy="false"} +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "verificationMethod": [ + { + "id": "did:example:123#key-0", + "type": "JsonWebKey2020", + "controller": "did:example:123", + "publicKeyJwk": { + "kty": "OKP", // external (property name) + "crv": "Ed25519", // external (property name) + "x": "VCpo2LMLhn6iWku8MKvSLg2ZAoC-nlOyPVQaO3FxVeQ" // external (property name) + } + }, + { + "id": "did:example:123#key-1", + "type": "JsonWebKey2020", + "controller": "did:example:123", + "publicKeyJwk": { + "kty": "OKP", // external (property name) + "crv": "X25519", // external (property name) + "x": "pE_mG098rdQjY3MKK2D5SUQ6ZOEW3a6Z6T7Z4SgnzCE" // external (property name) + } + }, + { + "id": "did:example:123#key-2", + "type": "JsonWebKey2020", + "controller": "did:example:123", + "publicKeyJwk": { + "kty": "EC", // external (property name) + "crv": "secp256k1", // external (property name) + "x": "Z4Y3NNOxv0J6tCgqOBFnHnaZhJF6LdulT7z8A-2D5_8", // external (property name) + "y": "i5a2NtJoUKXkLm6q8nOEu9WOkso1Ag6FTUT6k_LMnGk" // external (property name) + } + }, + { + "id": "did:example:123#key-3", + "type": "JsonWebKey2020", + "controller": "did:example:123", + "publicKeyJwk": { + "kty": "EC", // external (property name) + "crv": "secp256k1", // external (property name) + "x": "U1V4TVZVMUpUa0ZVU1NBcU9CRm5IbmFaaEpGNkxkdWx", // external (property name) + "y": "i5a2NtJoUKXkLm6q8nOEu9WOkso1Ag6FTUT6k_LMnGk" // external (property name) + } + }, + { + "id": "did:example:123#key-4", + "type": "JsonWebKey2020", + "controller": "did:example:123", + "publicKeyJwk": { + "kty": "EC", // external (property name) + "crv": "P-256", // external (property name) + "x": "Ums5WVgwRkRTVVFnU3k5c2xvZllMbEcwM3NPRW91ZzN", // external (property name) + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4" // external (property name) + } + }, + { + "id": "did:example:123#key-5", + "type": "JsonWebKey2020", + "controller": "did:example:123", + "publicKeyJwk": { + "kty": "EC", // external (property name) + "crv": "P-384", // external (property name) + "x": "VUZKSlUwMGdpSXplekRwODhzX2N4U1BYdHVYWUZsaXVDR25kZ1U0UXA4bDkxeHpE", // external (property name) + "y": "jq4QoAHKiIzezDp88s_cxSPXtuXYFliuCGndgU4Qp8l91xzD1spCmFIzQgVjqvcP" // external (property name) + } + }, + { + "id": "did:example:123#key-6", + "type": "JsonWebKey2020", + "controller": "did:example:123", + "publicKeyJwk": { + "kty": "EC", // external (property name) + "crv": "P-521", // external (property name) + "x": "VTI5c1lYSmZWMmx1WkhNZ0dQTXhaYkhtSnBEU3UtSXZwdUtpZ0VOMnB6Z1d0U28tLVJ3ZC1uNzhuclduWnplRGMx", // external (property name) + "y": "UW5WNVgwSnBkR052YVc0Z1VqY1B6LVpoZWNaRnliT3FMSUpqVk9sTEVUSDd1UGx5RzBnRW9NV25JWlhoUVZ5cFB5" // external (property name) + } + }, + { + "id": "did:example:123#key-7", + "type": "JsonWebKey2020", + "controller": "did:example:123", + "publicKeyJwk": { + "kty": "RSA", // external (property name) + "e": "AQAB", // external (property name) + "n": "UkhWaGJGOUZRMTlFVWtKSElBdENGV2hlU1F2djFNRXh1NVJMQ01UNGpWazlraEpLdjhKZU1YV2UzYldIYXRqUHNrZGYyZGxhR2tXNVFqdE9uVUtMNzQybXZyNHRDbGRLUzNVTElhVDFoSkluTUhIeGoyZ2N1Yk82ZUVlZ0FDUTRRU3U5TE8wSC1MTV9MM0RzUkFCQjdRamE4SGVjcHl1c3BXMVR1X0RicXhjU253ZW5kYW13TDUyVjE3ZUtobE80dVh3djJIRmx4dWZGSE0wS21DSnVqSUt5QXhqRF9tM3FfX0lpSFVWSEQxdERJRXZMUGhHOUF6c24zajk1ZC1zYU" // external (property name) + } + } + ] +} +``` + +[Example 32](#example-did-document-with-different-verification-method-types): DID Document with different verification method types + +``` {aria-busy="false"} +{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2018/v1", + "https://w3id.org/security/suites/x25519-2019/v1", + "https://w3id.org/security/suites/secp256k1-2019/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "verificationMethod": [ + { + "id": "did:example:123#key-0", + "type": "Ed25519VerificationKey2018", + "controller": "did:example:123", + "publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J" // external (property name) + }, + { + "id": "did:example:123#key-1", + "type": "X25519KeyAgreementKey2019", + "controller": "did:example:123", + "publicKeyBase58": "FbQWLPRhTH95MCkQUeFYdiSoQt8zMwetqfWoxqPgaq7x" // external (property name) + }, + { + "id": "did:example:123#key-2", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:example:123", + "publicKeyBase58": "ns2aFDq25fEV1NUd3wZ65sgj5QjFW8JCAHdUJfLwfodt" // external (property name) + }, + { + "id": "did:example:123#key-3", + "type": "JsonWebKey2020", + "controller": "did:example:123", + "publicKeyJwk": { + "kty": "EC", // external (property name) + "crv": "P-256", // external (property name) + "x": "Er6KSSnAjI70ObRWhlaMgqyIOQYrDJTE94ej5hybQ2M", // external (property name) + "y": "pPVzCOTJwgikPjuUE6UebfZySqEJ0ZtsWFpj7YSPGEk" // external (property name) + } + } + ] +} +``` + +### A.2 Proving + +[](#proving) + +*This section is non-normative.* + +Note + +These examples are for information purposes only. See [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) for additional examples. + +[Example 33](#example-verifiable-credential-linked-to-a-verification-method-of-type-ed25519verificationkey2020): Verifiable Credential linked to a verification method of type Ed25519VerificationKey2020 + +``` {aria-busy="false"} +{ // external (all terms in this example) + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/citizenship/v1" + ], + "type": [ + "VerifiableCredential", + "PermanentResidentCard" + ], + "credentialSubject": { + "id": "did:example:123", + "type": [ + "PermanentResident", + "Person" + ], + "givenName": "JOHN", + "familyName": "SMITH", + "gender": "Male", + "image": "data:image/png;base64,iVBORw0KGgo...kJggg==", + "residentSince": "2015-01-01", + "lprCategory": "C09", + "lprNumber": "000-000-204", + "commuterClassification": "C1", + "birthCountry": "Bahamas", + "birthDate": "1958-08-17" + }, + "issuer": "did:example:456", + "issuanceDate": "2020-04-22T10:37:22Z", + "identifier": "83627465", + "name": "Permanent Resident Card", + "description": "Government of Example Permanent Resident Card.", + "proof": { + "type": "Ed25519Signature2018", + "created": "2020-04-22T10:37:22Z", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:example:456#key-1", + "jws": "eyJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlLCJhbGciOiJFZERTQSJ9..BhWew0x-txcroGjgdtK-yBCqoetg9DD9SgV4245TmXJi-PmqFzux6Cwaph0r-mbqzlE17yLebjfqbRT275U1AA" + } +} +``` + +[Example 34](#example-verifiable-credential-linked-to-a-verification-method-of-type-jsonwebkey2020): Verifiable Credential linked to a verification method of type JsonWebKey2020 + +``` {aria-busy="false"} +{ // external (all terms in this example) + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1" + ], + "id": "http://example.gov/credentials/3732", + "type": ["VerifiableCredential", "UniversityDegreeCredential"], + "issuer": { "id": "did:example:123" }, + "issuanceDate": "2020-03-10T04:24:12.164Z", + "credentialSubject": { + "id": "did:example:456", + "degree": { + "type": "BachelorDegree", + "name": "Bachelor of Science and Arts" + } + }, + "proof": { + "type": "JsonWebSignature2020", + "created": "2020-02-15T17:13:18Z", + "verificationMethod": "did:example:123#_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A", + "proofPurpose": "assertionMethod", + "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..Y0KqovWCPAeeFhkJxfQ22pbVl43Z7UI-X-1JX32CA9MkFHkmNprcNj9Da4Q4QOl0cY3obF8cdDRdnKr0IwNrAw" + } +} +``` + +[Example 35](#example-verifiable-credential-linked-to-a-bls12381-verification-method): Verifiable Credential linked to a bls12381 verification method + +``` {aria-busy="false"} +{ // external (all terms in this example) + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/security/bbs/v1", + { + "name": "https://schema.org/name", + "birthDate": "https://schema.org/birthDate" + } + ], + "id": "urn:uuid:c499e122-3ba9-4e95-8d4d-c0ebfcf8c51a", + "type": ["VerifiableCredential"], + "issuanceDate": "2021-02-07T16:02:08.571Z", + "issuer": { + "id": "did:example:123" + }, + "credentialSubject": { + "id": "did:example:456", + "name": "John Smith", + "birthDate": "2021-02-07" + }, + "proof": { + "type": "BbsBlsSignature2020", + "created": "2021-02-07T16:02:10Z", + "proofPurpose": "assertionMethod", + "proofValue": "o7zD2eNTp657YzkJLub+IO4Zqy/R3Lv/AWmtSA/kUlEAOa73BNyP1vOeoow35jkABolx4kYMKkp/ZsFDweuKwe/p9vxv9wrMJ9GpiOZjHcpjelDRRJLBiccg9Yv7608mHgH0N1Qrj14PZ2saUlfhpQ==", + "verificationMethod": "did:example:123#bls12381-g2-key" + } +} +``` + +[Example 36](#example-verifiable-credential-selective-disclosure-zero-knowledge-proof-linked-to-a-bls12381-verification-method): Verifiable Credential selective disclosure zero knowledge proof linked to a bls12381 verification method + +``` {aria-busy="false"} +{ // external (all terms in this example) + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/security/bbs/v1", + { + "name": "https://schema.org/name", + "birthDate": "https://schema.org/birthDate" + } + ], + "id": "urn:uuid:c499e122-3ba9-4e95-8d4d-c0ebfcf8c51a", + "type": "VerifiableCredential", + "issuanceDate": "2021-02-07T16:02:08.571Z", + "issuer": { + "id": "did:example:123" + }, + "credentialSubject": { + "id": "did:example:456", + "birthDate": "2021-02-07" + }, + "proof": { + "type": "BbsBlsSignatureProof2020", + "created": "2021-02-07T16:02:10Z", + "nonce": "OqZHsV/aunS34BhLaSoxiHWK+SUaG4iozM3V+1jO06zRRNcDWID+I0uwtPJJ767Yo8Q=", + "proofPurpose": "assertionMethod", + "proofValue": "AAsH34lcKsqaqPaLQWcnLMe3mDM+K7fZM0t4Iesfj7BhD//HBtuWCmZE946BqW7OHYU106MP8mLntutqB8FyGwS7AOyK+5/7iW6JwLNVCvh4Nt3IaF3AN47fqVs2VikD9DiCsaFAUU6ISj5pbad8O+6jiT9Yw6ug8t8vJn3XHvMUhCPnDZJeBEdKD1qo4Z0LOq3L8QAAAHSEgtC9BoZL2MLjz4QuPxpwbhTTRC08MIUjdJnP4JUtz6163Lsl3rpadGu2d3Te7loAAAACZBD4YWOgV0xpPoYZ5vywNA5/NTeDHDbX36gvoV5RDJtY1SLU2LN/IDPZGrfhEiASbD1/QXqj8dod6FbjBs9m/LchBcy7z4yDBv/8DnBzDJ9dEaM4bDjpwmqtgJqha2kwtlyNog67xG9tNjnp5rrbIgAAAANMVanwWmlkg5I/f1M2QJ5GRvQiBL4lyL5sttxwIOalbTZP8VqWtFJI54xMNjTiK71aFWWN8SlNEwfVIX34HO5zBIb6fvc+Or21ubYllT9eXv1epl2o2CojuieCZyxE8/Q=", + "verificationMethod": "did:example:123#bls12381-g2-key" + } +} +``` + +[Example 37](#example-verifiable-credential-as-decoded-jwt): Verifiable Credential as Decoded JWT + +``` {aria-busy="false"} +{ // external (all terms in this example) + "protected": { + "kid": "did:example:123#_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A", + "alg": "EdDSA" + }, + "payload": { + "iss": "did:example:123", + "sub": "did:example:456", + "vc": { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1" + ], + "id": "http://example.gov/credentials/3732", + "type": [ + "VerifiableCredential", + "UniversityDegreeCredential" + ], + "issuer": { + "id": "did:example:123" + }, + "issuanceDate": "2020-03-10T04:24:12.164Z", + "credentialSubject": { + "id": "did:example:456", + "degree": { + "type": "BachelorDegree", + "name": "Bachelor of Science and Arts" + } + } + }, + "jti": "http://example.gov/credentials/3732", + "nbf": 1583814252 + }, + "signature": "qSv6dpZJGFybtcifLwGf4ujzlEu-fam_M7HPxinCbVhz9iIJCg70UMeQbPa1ex6BmQ2tnSS7F11FHnMB2bJRAw" +} +``` + +### A.3 Encrypting + +[](#encrypting) + +*This section is non-normative.* + +Note + +These examples are for information purposes only, it is considered a best practice to avoid dislosing unnecessary information in JWE headers. + +[Example 38](#example-jwe-linked-to-a-verification-method-via-kid): JWE linked to a verification method via kid + +``` {aria-busy="false"} +{ // external (all terms in this example) + "ciphertext": "3SHQQJajNH6q0fyAHmw...", + "iv": "QldSPLVnFf2-VXcNLza6mbylYwphW57Q", + "protected": "eyJlbmMiOiJYQzIwUCJ9", + "recipients": [ + { + "encrypted_key": "BMJ19zK12YHftJ4sr6Pz1rX1HtYni_L9DZvO1cEZfRWDN2vXeOYlwA", + "header": { + "alg": "ECDH-ES+A256KW", + "apu": "Tx9qG69ZfodhRos-8qfhTPc6ZFnNUcgNDVdHqX1UR3s", + "apv": "ZGlkOmVsZW06cm9wc3RlbjpFa...", + "epk": { + "crv": "X25519", + "kty": "OKP", + "x": "Tx9qG69ZfodhRos-8qfhTPc6ZFnNUcgNDVdHqX1UR3s" + }, + "kid": "did:example:123#zC1Rnuvw9rVa6E5TKF4uQVRuQuaCpVgB81Um2u17Fu7UK" + } + } + ], + "tag": "xbfwwDkzOAJfSVem0jr1bA" +} +``` + +## B. Architectural Considerations + +[](#architectural-considerations) + +### B.1 Detailed Architecture Diagram + +[](#detailed-architecture-diagram) + +Following is a diagram showing the relationships among [4. Data Model](#data-model), [5. Core Properties](#core-properties), and [8. Methods](#methods), and [7. Resolution](#resolution). + +![ DIDs and DID documents are recorded on a Verifiable Data Registry; DIDs resolve to DID documents; DIDs refer to DID subjects; a DID controller controls a DID document; DID URLs contains a DID; DID URLs dereferenced to DID document fragments or external resources; DID resolver implements resolve function; DID URL dereferencer implements dereferencing function; DID method operates a Verfiable Data Registry; DID resolver and DID URL dereferencer instruct a DID method. ](diagrams/did_detailed_architecture_overview.svg) + +Figure 7 Detailed overview of DID architecture and the relationship of the basic components. + +### B.2 Creation of a DID + +[](#creation-of-a-did) + +The creation of a [DID](#dfn-decentralized-identifiers) is a process that is defined by each [DID Method](#dfn-did-methods). Some [DID Methods](#dfn-did-methods), such as `did:key`, are purely generative, such that a [DID](#dfn-decentralized-identifiers) and a [DID document](#dfn-did-documents) are generated by transforming a single piece of cryptographic material into a conformant [representation](#dfn-representations). Other [DID methods](#dfn-did-methods) might require the use of a [verifiable data registry](#dfn-verifiable-data-registry), where the [DID](#dfn-decentralized-identifiers) and [DID document](#dfn-did-documents) are recognized to exist by third parties only when the registration has been completed, as defined by the respective [DID method](#dfn-did-methods). Other processes might be defined by the respective [DID method](#dfn-did-methods). + +### B.3 Determining the DID subject + +[](#determining-the-did-subject) + +A [DID](#dfn-decentralized-identifiers) is a specific type of URI (Uniform Resource Identifier), so a [DID](#dfn-decentralized-identifiers) can refer to any resource. Per \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]: + +> the term \"resource\" is used in a general sense for whatever might be identified by a URI. \[\...\] A resource is not necessarily accessible via the Internet. + +Resources can be digital or physical, abstract or concrete. Any resource that can be assigned a URI can be assigned a [DID](#dfn-decentralized-identifiers). The resource referred to by the [DID](#dfn-decentralized-identifiers) is the [DID subject](#dfn-did-subjects). + +The [DID controller](#dfn-did-controllers) determines the [DID subject](#dfn-did-subjects). It is not expected to be possible to determine the [DID subject](#dfn-did-subjects) from looking at the [DID](#dfn-decentralized-identifiers) itself, as [DIDs](#dfn-decentralized-identifiers) are generally only meaningful to machines, not human. A [DID](#dfn-decentralized-identifiers) is unlikely to contain any information about the [DID subject](#dfn-did-subjects), so further information about the [DID subject](#dfn-did-subjects) is only discoverable by resolving the [DID](#dfn-decentralized-identifiers) to the [DID document](#dfn-did-documents), obtaining a verifiable credential about the [DID](#dfn-decentralized-identifiers), or via some other description of the [DID](#dfn-decentralized-identifiers). + +While the value of the [`id`](#dfn-id) property in the retrieved [DID document](#dfn-did-documents) must always match the [DID](#dfn-decentralized-identifiers) being resolved, whether or not the actual resource to which the [DID](#dfn-decentralized-identifiers) refers can change over time is dependent upon the [DID method](#dfn-did-methods). For example, a [DID method](#dfn-did-methods) that permits the [DID subject](#dfn-did-subjects) to change could be used to generate a [DID](#dfn-decentralized-identifiers) for the current occupant of a particular role---such as the CEO of a company---where the actual person occupying the role can be different depending on when the [DID](#dfn-decentralized-identifiers) is resolved. + +### B.4 Referring to the DID document + +[](#referring-to-the-did-document) + +The [DID](#dfn-decentralized-identifiers) refers to the [DID subject](#dfn-did-subjects) and *resolves to* the [DID document](#dfn-did-documents) (by following the protocol specified by the [DID method](#dfn-did-methods)). The [DID document](#dfn-did-documents) is not a separate resource from the [DID subject](#dfn-did-subjects) and does not have a [URI](#dfn-uri) separate from the [DID](#dfn-decentralized-identifiers). Rather the [DID document](#dfn-did-documents) is an artifact of [DID resolution](#dfn-did-resolution) controlled by the [DID controller](#dfn-did-controllers) for the purpose of describing the [DID subject](#dfn-did-subjects). + +This distinction is illustrated by the graph model shown below. + +![ Diagram showing a graph model for how DID controllers assign DIDs to refer to DID subjects and resolve to DID documents that describe the DID subjects. ](diagrams/figure-a.1-did-and-did-document-graph.svg) + +Figure 8 A [DID](#dfn-decentralized-identifiers) is an identifier assigned by a [DID controller](#dfn-did-controllers) to refer to a [DID subject](#dfn-did-subjects) and resolve to a [DID document](#dfn-did-documents) that describes the [DID subject](#dfn-did-subjects). The [DID document](#dfn-did-documents) is an artifact of [DID resolution](#dfn-did-resolution) and not a separate resource distinct from the [DID subject](#dfn-did-subjects). See also: [narrative description](#did-and-did-document-graph-longdesc). + +Two filled black circles appear at the top of the diagram, one on the left, labeled \"DID Controller\", and one on the right, labeled \"DID Subject\". A rectangle, with lower right corner bent inwards to form a small triangle, appears below, containing the label \"DID Document\". Arrows extend between these three items, as follows. A solid red arrow points directly from the DID Controller circle, rightwards to the DID Subject circle, labeled \"DID\" above it in large font, and \"Identifies\" below it in small italic font. The other arrow labels are also in small italic font. A dotted red arrow, labeled \"Resolves to\", extends from DID Controller, starting in the same line as the first arrow, then curving downward to point to the DID Document rectangle. A green arrow, labeled \"Controls\", points directly from DID Controller to DID Document. A green arrow labeled \"Controller\" points in the opposite direction, from DID Document to DID Controller, making an arc outward to the left of the diagram. A blue arrow, labeled, \"Describes\" points directly from DID Document to DID Subject. + +### B.5 Statements in the DID document + +[](#statements-in-the-did-document) + +Each property in a [DID document](#dfn-did-documents) is a statement by the [DID controller](#dfn-did-controllers) that describes: + +- The string of characters defining identifiers for the [DID subject](#dfn-did-subjects) (e.g., the [`id`](#dfn-id) and [`alsoKnownAs`](#dfn-alsoknownas) properties) +- How to interact with the [DID subject](#dfn-did-subjects) (e.g., the [`verificationMethod`](#dfn-verificationmethod) and [`service`](#dfn-service) properties). +- How to interpret the specific representation of the [DID document](#dfn-did-documents) (e.g., the `@context` property for a JSON-LD representation). + +The only required property in a [DID document](#dfn-did-documents) is [`id`](#dfn-id), so that is the only statement guaranteed to be in a [DID document](#dfn-did-documents). That statement is illustrated in [Figure 8](#did-and-did-document-graph "A DID is an identifier assigned by a DID controller to refer to a DID subject and resolve to a DID document that describes the DID subject. The DID document is an artifact of DID resolution and not a separate resource distinct from the DID subject. See also: narrative description.") with a direct link between the [DID](#dfn-decentralized-identifiers) and the [DID subject](#dfn-did-subjects). + +### B.6 Discovering more information about the DID subject + +[](#discovering-more-information-about-the-did-subject) + +Options for discovering more information about the [DID subject](#dfn-did-subjects) depend on the properties present in the [DID document](#dfn-did-documents). If the [`service`](#dfn-service) property is present, more information can be requested from a [service endpoint](#dfn-service-endpoints). For example, by querying a [service endpoint](#dfn-service-endpoints) that supports verifiable credentials for one or more claims (attributes) describing the [DID subject](#dfn-did-subjects). + +Another option is to use the [`alsoKnownAs`](#dfn-alsoknownas) property if it is present in the [DID document](#dfn-did-documents). The [DID controller](#dfn-did-controllers) can use it to provide a list of other URIs (including other [DIDs](#dfn-decentralized-identifiers)) that refer to the same [DID subject](#dfn-did-subjects). Resolving or dereferencing these URIs might yield other descriptions or representations of the [DID subject](#dfn-did-subjects) as illustrated in the figure below. + +![ Diagram showing a graph model, with an alsoKnownAs property with an arc to another node representing a different resource that dereferences to another description of the DID subject. ](diagrams/figure-a.2-also-known-as-graph.svg) + +Figure 9 A [DID document](#dfn-did-documents) can use the alsoKnownAs property to assert that another [URI](#dfn-uri) (including, but not necessarily, another [DID](#dfn-decentralized-identifiers)) refers to the same [DID subject](#dfn-did-subjects). See also: [narrative description](#alsoKnownAs-graph-longdesc). + +The diagram contains three small black filled circles, two rectangles with bent corners, arrows between them, and labels, as follows. On the upper left is a circle labeled \"DID Controller\". On the upper right is a circle labeled \"DID Subject\". On the lower-middle right is a circle without a label. On the lower right is a rectangle labeled \"Description\". In the center of the diagram is a rectangle labeled \"DID Document\". Inside the DID Document rectangle, beneath its label, is two lines of code: \"alsoKnownAs: \[\", and \"URI\]\". A black arrow extends from the second line, to the right, crossing the rectangle border, pointing to the unlabeled circle at the right of the diagram. This arrow is labeled above it in large font, \"URI\", and below it in italic, \"Identifies\". A black arrow points from the unlabeled circle downwards to the Description rectangle, labeled \"Dereferences to\". A blue arrow, labeled \"Describes\", extends from Description, arcing on the right, pointing up to DID Subject. A blue arrow, also labeled \"Describes\", points directly from the rectangle, labeled \"DID Document\", in the center of the diagram, up and to the right to the DID Subject circle. A red arrow, labeled \"alsoKnownAs\", points from DID Subject down to the unlabeled circle. A red arrow, labeled \"DID\" above it in large font, and \"Identifies\" below it in italic font, lies at the top of the image, pointing from DID Controller to DID Subject. A dotted red line starts in the same place but branches off and curves downward to point to the DID Document rectangle at the center of the image. A green arrow, labeled \"Controls\", points directly from DID Controller to DID Document. Another green arrow points in the opposite direction, labeled \"Controller\", curving outwards on the left of the image, from DID Document to DID Controller. + +### B.7 Serving a representation of the DID subject + +[](#serving-a-representation-of-the-did-subject) + +If the [DID subject](#dfn-did-subjects) is a digital resource that can be retrieved from the internet, a [DID method](#dfn-did-methods) can choose to construct a [DID URL](#dfn-did-urls) which returns a representation of the [DID subject](#dfn-did-subjects) itself. For example, a data schema that needs a persistent, cryptographically verifiable identifier could be assigned a [DID](#dfn-decentralized-identifiers), and passing a specified DID parameter (see [3.2.1 DID Parameters](#did-parameters)) could be used as a standard way to retrieve a representation of that schema. + +Similarly, a [DID](#dfn-decentralized-identifiers) can be used to refer to a digital resource (such as an image) that can be returned directly from a [verifiable data registry](#dfn-verifiable-data-registry) if that functionality is supported by the applicable [DID method](#dfn-did-methods). + +### B.8 Assigning DIDs to existing web resources + +[](#assigning-dids-to-existing-web-resources) + +If the controller of a web page or any other web resource wants to assign it a persistent, cryptographically verifiable identifier, the controller can give it a [DID](#dfn-decentralized-identifiers). For example, the author of a blog hosted by a blog hosting company (under that hosting company\'s domain) could create a [DID](#dfn-decentralized-identifiers) for the blog. In the [DID document](#dfn-did-documents), the author can include the [`alsoKnownAs`](#dfn-alsoknownas) property pointing to the current URL of the blog, e.g.: + +` "alsoKnownAs": ["https://myblog.blogging-host.example/home"] ` + +If the author subsequently moves the blog to a different hosting company (or to the author\'s own domain), the author can update the [DID document](#dfn-did-documents) to point to the new URL for the blog, e.g.: + +` "alsoKnownAs": ["https://myblog.example/"] ` + +The [DID](#dfn-decentralized-identifiers) effectively adds a layer of indirection for the blog URL. This layer of indirection is under the control of the author instead of under the control of an external administrative authority such as the blog hosting company. This is how a [DID](#dfn-decentralized-identifiers) can effectively function as an enhanced [URN (Uniform Resource Name)](https://tools.ietf.org/html/rfc8141)---a persistent identifier for an information resource whose network location might change over time. + +### B.9 The relationship between DID controllers and DID subjects + +[](#the-relationship-between-did-controllers-and-did-subjects) + +To avoid confusion, it is helpful to classify [DID subject](#dfn-did-subjects)s into two disjoint sets based on their relationship to the [DID controller](#dfn-did-controllers). + +#### B.9.1 Set #1: The DID subject *is* the DID controller + +[](#set-1-the-did-subject-is-the-did-controller) + +The first case, shown in [Figure 10](#controller-subject-equivalence "The DID subject is the same entity as the DID controller. See also: narrative description."), is the common scenario where the [DID subject](#dfn-did-subjects) is also the [DID controller](#dfn-did-controllers). This is the case when an individual or organization creates a [DID](#dfn-decentralized-identifiers) to self-identify. + +![ Diagram showing a graph model with an equivalence arc from the DID subject to the DID controller. ](diagrams/figure-b.1-controller-and-subject-equivalence.svg) + +Figure 10 The [DID subject](#dfn-did-subjects) is the same entity as the [DID controller](#dfn-did-controllers). See also: [narrative description](#controller-subject-equivalence-longdesc). + +Two small black circles appear in the diagram, one on the upper left, labeled, \"DID Controller\", and one on the upper right, labeled \"DID Subject\". A solid red arrow extends from the DID Controller circle to the DID Subject circle, labeled \"DID\" in large bold text above the arrow, and \"Identifies\" in small italic text beneath the arrow. A dotted red double-ended arrow, labeled \"Equivalence\", extends between the two circles, forming an arc in the space between and above them. In the lower part of the diagram is a rectangle with bent corner, outlined in black, containing the label \"DID Document\". Arrows point between this DID Document rectangle and the small black circles for DID Controller and DID Subject, with italic labels, as follows. A blue arrow points from the DID Document to the DID Subject, labeled, \"Describes\". A green arrow points from the DID Controller to the DID Document, labeled \"Controls\". A green arrow points from the DID Document to the DID Controller, in an outward arc, labeled, \"Controller\". A dotted red arrow, labeled \"Resolves to\", extends from the DID controller starting to the right, branching off from the arrow to the DID Subject, then curving downward to point to the DID Document. + +From a graph model perspective, even though the nodes identified as the [DID controller](#dfn-did-controllers) and [DID subject](#dfn-did-subjects) in [Figure 10](#controller-subject-equivalence "The DID subject is the same entity as the DID controller. See also: narrative description.") are distinct, there is a logical arc connecting them to express a semantic equivalence relationship. + +#### B.9.2 Set #2: The DID subject is *not* the DID controller + +[](#set-2-the-did-subject-is-not-the-did-controller) + +The second case is when the [DID subject](#dfn-did-subjects) is a separate entity from the [DID controller](#dfn-did-controllers). This is the case when, for example, a parent creates and maintains control of a [DID](#dfn-decentralized-identifiers) for a child; a corporation creates and maintains control of a [DID](#dfn-decentralized-identifiers) for a subsidiary; or a manufacturer creates and maintains control of a [DID](#dfn-decentralized-identifiers) for a product, an IoT device, or a digital file. + +From a graph model perspective, the only difference from Set 1 that there is no equivalence arc relationship between the [DID subject](#dfn-did-subjects) and [DID controller](#dfn-did-controllers) nodes. + +### B.10 Multiple DID controllers + +[](#multiple-did-controllers) + +A [DID document](#dfn-did-documents) might have more than one [DID controller](#dfn-did-controllers). This can happen in one of two ways. + +#### B.10.1 Independent Control + +[](#independent-control) + +In this case, each of the [DID controllers](#dfn-did-controllers) might act on its own, i.e., each one has full power to update the [DID document](#dfn-did-documents) independently. From a graph model perspective, in this configuration: + +- Each additional [DID controller](#dfn-did-controllers) is another distinct graph node (which might be identified by its own [DID](#dfn-decentralized-identifiers)). +- The same arcs (\"controls\" and \"controller\") exist between each [DID controller](#dfn-did-controllers) and the [DID document](#dfn-did-documents). + +![ Diagram showing three DID controllers each with an independent control relationship with the DID document ](diagrams/figure-c.1-independent-did-controllers.svg) + +Figure 11 Multiple independent [DID controllers](#dfn-did-controllers) that can each act independently. See also: [Text Description](#independent-did-controllers-longdesc) + +Three black circles appear on the left, vertically, each labeled \"DID Controller\". From each of these circles, a pair of green arrows extends towards the center of the diagram, to a single rectangle, labeled \"DID Document\". The rectangle has the lower right corner cut and bent inward to form a small triangle, as if to represent a physical piece of paper with curled corner. Each pair of green arrows consists of one arrow pointing from the black circle to the rectangle, labeled \"Controls\", and one pointing in the opposite direction, from the rectangle to the black circle, labeled \"Controller\". From the right of the rectangle extends a blue arrow, labeled, \"Describes\", pointing to a black circle labeled, \"DID Subject\". + +#### B.10.2 Group Control + +[](#group-control) + +In the case of group control, the [DID controllers](#dfn-did-controllers) are expected to act together in some fashion, such as when using a cryptographic algorithm that requires multiple digital signatures (\"multi-sig\") or a threshold number of digital signatures (\"m-of-n\"). From a functional standpoint, this option is similar to a single [DID controller](#dfn-did-controllers) because, although each of the [DID controllers](#dfn-did-controllers) in the [DID controller](#dfn-did-controllers) group has its own graph node, the actual control collapses into a single logical graph node representing the [DID controller](#dfn-did-controllers) group as shown in [Figure 12](#group-did-controllers "Multiple DID controllers who are expected to act together as a DID controller group. See also: narrative description."). + +![ Diagram showing three DID controllers together as a single DID controller group to control a DID document ](diagrams/figure-c.2-group-did-controllers.svg) + +Figure 12 Multiple [DID controllers](#dfn-did-controllers) who are expected to act together as a [DID controller](#dfn-did-controllers) group. See also: [narrative description](#group-did-controllers-longdesc). + +On the left are three black filled circles, labeled \"DID Controller Group\" by a brace on the left. From each of these three circles, a green arrow extends to the center right. These three arrows converge towards a single filled white circle. A pair of horizontal green arrows connects this white circle on its right to a rectangle shaped like a page with a curled corner, labeled \"DID Document\". The upper arrow points right, from the white circle to the rectangle, and is labeled \"Controls\". The lower arrow points left, from the rectangle to the white circle, and is labeled \"Controller\". From the right of the rectangle extends a blue arrow, labeled \"Describes\", pointing to a black circle, labeled \"DID Subject\". + +This configuration will often apply when the [DID subject](#dfn-did-subjects) is an organization, corporation, government agency, community, or other group that is not controlled by a single individual. + +### B.11 Changing the DID subject + +[](#changing-the-did-subject) + +A [DID document](#dfn-did-documents) has exactly one [DID](#dfn-decentralized-identifiers) which refers to the [DID subject](#dfn-did-subjects). The [DID](#dfn-decentralized-identifiers) is expressed as the value of the [`id`](#dfn-id) property. This property value is immutable for the lifetime of the [DID document](#dfn-did-documents). + +However, it is possible that the resource *identified* by the [DID](#dfn-decentralized-identifiers), the [DID subject](#dfn-did-subjects), may change over time. This is under the exclusive authority of the [DID controller](#dfn-did-controllers). For more details, see section [9.16 Persistence](#persistence). + +### B.12 Changing the DID controller + +[](#changing-the-did-controller) + +The [DID controller](#dfn-did-controllers) for a [DID document](#dfn-did-documents) might change over time. However, depending on how it is implemented, a change in the [DID controller](#dfn-did-controllers) might not be made apparent by changes to the [DID document](#dfn-did-documents) itself. For example, if the change is implemented through a shift in ownership of the underlying cryptographic keys or other controls used for one or more of the [verification methods](#dfn-verification-method) in the [DID document](#dfn-did-documents), it might be indistinguishable from a standard key rotation. + +On the other hand, if the change is implemented by changing the value of the [`controller`](#dfn-controller) property, it will be transparent. + +If it is important to verify a change of [DID controller](#dfn-did-controllers), implementers are advised to [authenticate](#dfn-authenticated) the new [DID controller](#dfn-did-controllers) against the [verification methods](#dfn-verification-method) in the revised [DID document](#dfn-did-documents). + +## C. Revision History + +[](#revision-history) + +This section contains the changes that have been made since the publication of this specification as a W3C First Public Working Draft. + +Changes since the [Second Candidate Recommendation](https://www.w3.org/TR/2021/CR-did-core-20210615/) include: + +- Non-normatively refer to the DID Resolution specification to guide implementers toward common DID URL implementation patterns. +- Elaborate upon when DID Documents are understood to start existing. +- Convert PNG diagrams to SVG diagrams. +- Rearrange order of Appendices to improve readability. +- Update the IANA guidance as a result of the IETF Media Type Maintenance Working Group efforts. +- Add links to use cases document. +- Add warning related to \[[MULTIBASE](#bib-multibase "The Multibase Encoding Scheme")\] and `publicKeyMultibase`. +- Remove at risk issue markers for features that gained enough implementation experience. +- Finalize the Editors, Authors, and Acknowledgements information. + +Changes since the [First Candidate Recommendation](https://www.w3.org/TR/2021/CR-did-core-20210318/) include: + +- Addition of at risk markers to most of the DID Parameters, the data model datatypes that are expected to not be implemented, and the application/did+ld+json media type. This change resulted in the DID WG\'s decision to perform a second Candidate Recommendation phase. All other changes were either editorial or predicted in \"at risk\" issue markers. +- Removal of the at risk issue marker for the `method-specific-id` ABNF rule and for `nextUpdate` and `nextVersionId`. +- Clarification that `equivalentId` and `canonicalId` are optional. +- Addition of a definitions for \"amplification attack\" and \"cryptographic suite\". +- Replacement of `publicKeyBase58` with `publicKeyMultibase`. +- Updates to the DID Document examples section. +- A large number of editorial clean ups to the Security Considerations section. + +Changes since the [First Public Working Draft](https://www.w3.org/TR/2019/WD-did-core-20191107/) include: + +- The introduction of an abstract data model that can be serialized to multiple representations including JSON and JSON-LD. +- The introduction of a DID Specifications Registry for the purposes of registering extension properties, representations, DID Resolution input metadata and output metadata, DID Document metadata, DID parameters, and DID Methods. +- Separation of DID Document metadata, such as created and updated values, from DID Document properties. +- The removal of embedded proofs in the DID Document. +- The addition of verification relationships for the purposes of authentication, assertion, key agreement, capability invocation and capability delegation. +- The ability to support relating multiple identifiers with the DID Document, such as the DID controller, also known as, equivalent IDs, and canonical IDs. +- Enhancing privacy by reducing information that could contain personally identifiable information in the DID Document. +- The addition of a large section on security considerations and privacy considerations. +- A Representations section that details how the abstract data model can be produced and consumed in a variety of different formats along with general rules for all representations, producers, and consumers. +- A section detailing the DID Resolution and DID URL Dereferencing interface definition that all DID resolvers are expected to expose as well as inputs and outputs to those processes. +- DID Document examples in an appendix that provide more complex examples of DID Document serializations. +- IANA Considerations for multiple representations specified in DID Core. +- Removal of the Future Work section as much of the work has now been accomplished. +- An acknowledgements section. + +## D. Acknowledgements + +[](#acknowledgements) + +The Working Group extends deep appreciation and heartfelt thanks to our Chairs Brent Zundel and Dan Burnett, as well as our W3C Staff Contact, Ivan Herman, for their tireless work in keeping the Working Group headed in a productive direction and navigating the deep and dangerous waters of the standards process. + +The Working Group gratefully acknowledges the work that led to the creation of this specification, and extends sincere appreciation to those individuals that worked on technologies and specifications that deeply influenced our work. In particular, this includes the work of Phil Zimmerman, Jon Callas, Lutz Donnerhacke, Hal Finney, David Shaw, and Rodney Thayer on [Pretty Good Privacy (PGP)](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) in the 1990s and 2000s. + +In the mid-2010s, preliminary implementations of what would become Decentralized Identifiers were [built](https://web-payments.org/minutes/2014-05-07/#topic-1) in collaboration with Jeremie Miller\'s Telehash project and the W3C Web Payments Community Group\'s work led by Dave Longley and Manu Sporny. Around a year later, the XDI.org Registry Working Group [began exploring](https://docs.google.com/document/d/1EP-KhH60y-nl4xkEzoeSf3DjmjLomfboF4p2umF51FA/) decentralized technologies for replacing its existing identifier registry. Some of the first [written](https://github.com/WebOfTrustInfo/rwot1-sf/blob/master/final-documents/dpki.pdf) [papers](https://github.com/WebOfTrustInfo/rwot2-id2020/blob/master/final-documents/requirements-for-dids.pdf) exploring the concept of Decentralized Identifiers can be traced back to the first several Rebooting the Web of Trust workshops convened by Christopher Allen. That work led to a key collaboration between Christopher Allen, Drummond Reed, Les Chasen, Manu Sporny, and Anil John. Anil saw promise in the technology and allocated the initial set of government funding to explore the space. Without the support of Anil John and his guidance through the years, it is unlikely that Decentralized Identifiers would be where they are today. Further refinement at the Rebooting the Web of Trust workshops led to the [first implementers documentation](https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/final-documents/did-implementer-draft-10.pdf), edited by Drummond Reed, Les Chasen, Christopher Allen, and Ryan Grant. Contributors included Manu Sporny, Dave Longley, Jason Law, Daniel Hardman, Markus Sabadello, Christian Lundkvist, and Jonathan Endersby. This initial work was then merged into the W3C Credentials Community Group, incubated further, and then transitioned to the W3C Decentralized Identifiers Working Group for global standardization. + +Portions of the work on this specification have been funded by the United States Department of Homeland Security\'s (US DHS) Science and Technology Directorate under contracts HSHQDC-16-R00012-H-SB2016-1-002, and HSHQDC-17-C-00019, as well as the US DHS Silicon Valley Innovation Program under contracts 70RSAT20T00000010, 70RSAT20T00000029, 70RSAT20T00000030, 70RSAT20T00000045, 70RSAT20T00000003, and 70RSAT20T00000033. The content of this specification does not necessarily reflect the position or the policy of the U.S. Government and no official endorsement should be inferred. + +Portions of the work on this specification have also been funded by the European Union\'s StandICT.eu program under sub-grantee contract number CALL05/19. The content of this specification does not necessarily reflect the position or the policy of the European Union and no official endorsement should be inferred. + +Work on this specification has also been supported by the [Rebooting the Web of Trust](https://www.weboftrust.info/) community facilitated by Christopher Allen, Shannon Appelcline, Kiara Robles, Brian Weller, Betty Dhamers, Kaliya Young, Kim Hamilton Duffy, Manu Sporny, Drummond Reed, Joe Andrieu, and Heather Vescent. Development of this specification has also been supported by the [W3C Credentials Community Group](https://w3c-ccg.github.io/), which has been Chaired by Kim Hamilton Duffy, Joe Andrieu, Christopher Allen, Heather Vescent, and Wayne Chang. The participants in the Internet Identity Workshop, facilitated by Phil Windley, Kaliya Young, Doc Searls, and Heidi Nobantu Saul, also supported this work through numerous working sessions designed to debate, improve, and educate participants about this specification. + +The Working Group thanks the following individuals for their contributions to this specification (in alphabetical order, Github handles start with `@` and are sorted as last names): Denis Ah-Kang, Nacho Alamillo, Christopher Allen, Joe Andrieu, Antonio, Phil Archer, George Aristy, Baha, Juan Benet, BigBlueHat, Dan Bolser, Chris Boscolo, Pelle Braendgaard, Daniel Buchner, Daniel Burnett, Juan Caballero, \@cabo, Tim Cappalli, Melvin Carvalho, David Chadwick, Wayne Chang, Sam Curren, Hai Dang, Tim Daubenschütz, Oskar van Deventer, Kim Hamilton Duffy, Arnaud Durand, Ken Ebert, Veikko Eeva, \@ewagner70, Carson Farmer, Nikos Fotiou, Gabe, Gayan, \@gimly-jack, \@gjgd, Ryan Grant, Peter Grassberger, Adrian Gropper, Amy Guy, Daniel Hardman, Kyle Den Hartog, Philippe Le Hegaret, Ivan Herman, Michael Herman, Alen Horvat, Dave Huseby, Marcel Jackisch, Mike Jones, Andrew Jones, Tom Jones, jonnycrunch, Gregg Kellogg, Michael Klein, \@kdenhartog-sybil1, Paul Knowles, \@ktobich, David I. Lehn, Charles E. Lehner, Michael Lodder, \@mooreT1881, Dave Longley, Tobias Looker, Wolf McNally, Robert Mitwicki, Mircea Nistor, Grant Noble, Mark Nottingham, \@oare, Darrell O\'Donnell, Vinod Panicker, Dirk Porsche, Praveen, Mike Prorock, \@pukkamustard, Drummond Reed, Julian Reschke, Yancy Ribbens, Justin Richer, Rieks, \@rknobloch, Mikeal Rogers, Evstifeev Roman, Troy Ronda, Leonard Rosenthol, Michael Ruminer, Markus Sabadello, Cihan Saglam, Samu, Rob Sanderson, Wendy Seltzer, Mehran Shakeri, Jaehoon (Ace) Shim, Samuel Smith, James M Snell, SondreB, Manu Sporny, \@ssstolk, Orie Steele, Shigeya Suzuki, Sammotic Switchyarn, \@tahpot, Oliver Terbu, Ted Thibodeau Jr., Joel Thorstensson, Tralcan, Henry Tsai, Rod Vagg, Mike Varley, Kaliya \"Identity Woman\" Young, Eric Welton, Fuqiao Xue, \@Yue, Dmitri Zagidulin, \@zhanb, and Brent Zundel. + +## E. IANA Considerations + +[](#iana-considerations) + +This section will be submitted to the Internet Engineering Steering Group (IESG) for review, approval, and registration with IANA when this specification becomes a W3C Proposed Recommendation. + +### E.1 application/did+json + +[](#application-did-json) + +Type name: +: application + +Subtype name: +: did+json + +Required parameters: +: None + +Optional parameters: +: None + +Encoding considerations: +: See [RFC 8259, section 11](https://www.rfc-editor.org/rfc/rfc8259#section-11). + +Security considerations: +: See [RFC 8259, section 12](https://www.rfc-editor.org/rfc/rfc8259#section-12) \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\]. + +Interoperability considerations: +: Not Applicable + +Published specification: +: https://www.w3.org/TR/did-core/ + +Applications that use this media type: +: Any application that requires an identifier that is decentralized, persistent, cryptographically verifiable, and resolvable. Applications typically consist of cryptographic identity systems, decentralized networks of devices, and websites that issue or verify W3C Verifiable Credentials. + +Additional information: + +: + + Magic number(s): + : Not Applicable + + File extension(s): + : .didjson + + Macintosh file type code(s): + : TEXT + +Person & email address to contact for further information: +: Ivan Herman \ + +Intended usage: +: Common + +Restrictions on usage: +: None + +Author(s): +: Drummond Reed, Manu Sporny, Markus Sabadello, Dave Longley, Christopher Allen + +Change controller: +: W3C + +Fragment identifiers used with [application/did+json](#application-did-json) are treated according to the rules defined in [Fragment](#fragment). + +### E.2 application/did+ld+json + +[](#application-did-ld-json) + +Note: IETF Structured Media Types + +The Candidate Recommendation phase for this specification received a significant number of implementations for the `application/did+ld+json` media type. Registration of the media type `application/did+ld+json` at IANA is pending resolution of the [Media Types with Multiple Suffixes](https://datatracker.ietf.org/doc/html/draft-w3cdidwg-media-types-with-multiple-suffixes) issue. Work is expected to continue in the [IETF Media Type Maintenance Working Group](https://datatracker.ietf.org/wg/mediaman/about/) with a registration of the `application/did+ld+json` media type by W3C following shortly after the publication of the [Media Types with Multiple Suffixes](https://datatracker.ietf.org/doc/html/draft-w3cdidwg-media-types-with-multiple-suffixes) RFC. + +Type name: +: application + +Subtype name: +: did+ld+json + +Required parameters: +: None + +Optional parameters: +: None + +Encoding considerations: +: See [RFC 8259, section 11](https://www.rfc-editor.org/rfc/rfc8259#section-11). + +Security considerations: +: See [JSON-LD 1.1, Security Considerations](https://www.w3.org/TR/json-ld11/#security) \[[JSON-LD11](#bib-json-ld11 "JSON-LD 1.1")\]. + +Interoperability considerations: +: Not Applicable + +Published specification: +: https://www.w3.org/TR/did-core/ + +Applications that use this media type: +: Any application that requires an identifier that is decentralized, persistent, cryptographically verifiable, and resolvable. Applications typically consist of cryptographic identity systems, decentralized networks of devices, and websites that issue or verify W3C Verifiable Credentials. + +Additional information: + +: + + Magic number(s): + : Not Applicable + + File extension(s): + : .didjsonld + + Macintosh file type code(s): + : TEXT + +Person & email address to contact for further information: +: Ivan Herman \ + +Intended usage: +: Common + +Restrictions on usage: +: None + +Author(s): +: Drummond Reed, Manu Sporny, Markus Sabadello, Dave Longley, Christopher Allen + +Change controller: +: W3C + +Fragment identifiers used with [application/did+ld+json](#application-did-ld-json) are treated according to the rules associated with the [JSON-LD 1.1: application/ld+json media type](https://www.w3.org/TR/json-ld11/#iana-considerations) \[[JSON-LD11](#bib-json-ld11 "JSON-LD 1.1")\]. + +## F. References + +[](#references) + +### F.1 Normative references + +[](#normative-references) + +\[INFRA\] +: [Infra Standard](https://infra.spec.whatwg.org/). Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: + +\[JSON-LD11\] +: [JSON-LD 1.1](https://www.w3.org/TR/json-ld11/). Gregg Kellogg; Pierre-Antoine Champin; Dave Longley. W3C. 16 July 2020. W3C Recommendation. URL: + +\[RFC2119\] +: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119). S. Bradner. IETF. March 1997. Best Current Practice. URL: + +\[RFC3552\] +: [Guidelines for Writing RFC Text on Security Considerations](https://www.rfc-editor.org/rfc/rfc3552). E. Rescorla; B. Korver. IETF. July 2003. Best Current Practice. URL: + +\[RFC3986\] +: [Uniform Resource Identifier (URI): Generic Syntax](https://www.rfc-editor.org/rfc/rfc3986). T. Berners-Lee; R. Fielding; L. Masinter. IETF. January 2005. Internet Standard. URL: + +\[RFC5234\] +: [Augmented BNF for Syntax Specifications: ABNF](https://www.rfc-editor.org/rfc/rfc5234). D. Crocker, Ed.; P. Overell. IETF. January 2008. Internet Standard. URL: + +\[RFC7517\] +: [JSON Web Key (JWK)](https://www.rfc-editor.org/rfc/rfc7517). M. Jones. IETF. May 2015. Proposed Standard. URL: + +\[RFC7638\] +: [JSON Web Key (JWK) Thumbprint](https://www.rfc-editor.org/rfc/rfc7638). M. Jones; N. Sakimura. IETF. September 2015. Proposed Standard. URL: + +\[RFC8174\] +: [Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words](https://www.rfc-editor.org/rfc/rfc8174). B. Leiba. IETF. May 2017. Best Current Practice. URL: + +\[RFC8259\] +: [The JavaScript Object Notation (JSON) Data Interchange Format](https://www.rfc-editor.org/rfc/rfc8259). T. Bray, Ed.. IETF. December 2017. Internet Standard. URL: + +\[url\] +: [URL Standard](https://url.spec.whatwg.org/). Anne van Kesteren. WHATWG. Living Standard. URL: + +\[XMLSCHEMA11-2\] +: [W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes](https://www.w3.org/TR/xmlschema11-2/). David Peterson; Sandy Gao; Ashok Malhotra; Michael Sperberg-McQueen; Henry Thompson; Paul V. Biron et al. W3C. 5 April 2012. W3C Recommendation. URL: + +### F.2 Informative references + +[](#informative-references) + +\[DID-RESOLUTION\] +: [Decentralized Identifier Resolution](https://w3c-ccg.github.io/did-resolution/). Markus Sabadello; Dmitri Zagidulin. Credentials Community Group. Draft Community Group Report. URL: + +\[DID-RUBRIC\] +: [Decentralized Characteristics Rubric v1.0](https://w3c.github.io/did-rubric/). Joe Andrieu. Credentials Community Group. Draft Community Group Report. URL: + +\[DID-SPEC-REGISTRIES\] +: [DID Specification Registries](https://www.w3.org/TR/did-spec-registries/). Orie Steele; Manu Sporny; Michael Prorock. W3C. 28 June 2022. W3C Working Group Note. URL: + +\[DID-USE-CASES\] +: [Use Cases and Requirements for Decentralized Identifiers](https://www.w3.org/TR/did-use-cases/). Joe Andrieu; Phil Archer; Kim Duffy; Ryan Grant; Adrian Gropper. W3C. 17 March 2021. W3C Working Group Note. URL: + +\[DNS-DID\] +: [The Decentralized Identifier (DID) in the DNS](https://datatracker.ietf.org/doc/draft-mayrhofer-did-dns/). Alexander Mayrhofer; Dimitrij Klesev; Markus Sabadello. February 2019. Internet-Draft. URL: + +\[HASHLINK\] +: [Cryptographic Hyperlinks](https://tools.ietf.org/html/draft-sporny-hashlink-05). Manu Sporny. IETF. December 2018. Internet-Draft. URL: + +\[IANA-URI-SCHEMES\] +: [Uniform Resource Identifier (URI) Schemes](https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml). IANA. URL: + +\[MATRIX-URIS\] +: [Matrix URIs - Ideas about Web Architecture](https://www.w3.org/DesignIssues/MatrixURIs.html). Tim Berners-Lee. December 1996. Personal View. URL: + +\[MULTIBASE\] +: [The Multibase Encoding Scheme](https://datatracker.ietf.org/doc/html/draft-multiformats-multibase-03). Juan Benet; Manu Sporny. IETF. February 2021. Internet-Draft. URL: + +\[PRIVACY-BY-DESIGN\] +: [Privacy by Design](https://iapp.org/media/pdf/resource_center/pbd_implement_7found_principles.pdf). Ann Cavoukian. Information and Privacy Commissioner. 2011. URL: + +\[RFC4122\] +: [A Universally Unique IDentifier (UUID) URN Namespace](https://www.rfc-editor.org/rfc/rfc4122). P. Leach; M. Mealling; R. Salz. IETF. July 2005. Proposed Standard. URL: + +\[RFC6901\] +: [JavaScript Object Notation (JSON) Pointer](https://www.rfc-editor.org/rfc/rfc6901). P. Bryan, Ed.; K. Zyp; M. Nottingham, Ed.. IETF. April 2013. Proposed Standard. URL: + +\[RFC6973\] +: [Privacy Considerations for Internet Protocols](https://www.rfc-editor.org/rfc/rfc6973). A. Cooper; H. Tschofenig; B. Aboba; J. Peterson; J. Morris; M. Hansen; R. Smith. IETF. July 2013. Informational. URL: + +\[RFC7230\] +: [Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing](https://httpwg.org/specs/rfc7230.html). R. Fielding, Ed.; J. Reschke, Ed.. IETF. June 2014. Proposed Standard. URL: + +\[RFC7231\] +: [Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content](https://httpwg.org/specs/rfc7231.html). R. Fielding, Ed.; J. Reschke, Ed.. IETF. June 2014. Proposed Standard. URL: + +\[RFC8141\] +: [Uniform Resource Names (URNs)](https://www.rfc-editor.org/rfc/rfc8141). P. Saint-Andre; J. Klensin. IETF. April 2017. Proposed Standard. URL: + +\[VC-DATA-MODEL\] +: [Verifiable Credentials Data Model v1.1](https://www.w3.org/TR/vc-data-model/). Manu Sporny; Grant Noble; Dave Longley; Daniel Burnett; Brent Zundel; Kyle Den Hartog. W3C. 3 March 2022. W3C Recommendation. URL: + +[↑](#title) + +[Permalink](#dfn-conforming-did) + +**Referenced in:** + +- [§ 1.4 Conformance](#ref-for-dfn-conforming-did-1 "§ 1.4 Conformance") [(2)](#ref-for-dfn-conforming-did-2 "Reference 2") + +[Permalink](#dfn-conforming-did-document) + +**Referenced in:** + +- [§ 1.4 Conformance](#ref-for-dfn-conforming-did-document-1 "§ 1.4 Conformance") [(2)](#ref-for-dfn-conforming-did-document-2 "Reference 2") +- [§ 7.1 DID Resolution](#ref-for-dfn-conforming-did-document-3 "§ 7.1 DID Resolution") + +[Permalink](#dfn-conforming-producer) + +**Referenced in:** + +- [§ 5.4 Services](#ref-for-dfn-conforming-producer-1 "§ 5.4 Services") +- [§ 6.1 Production and Consumption](#ref-for-dfn-conforming-producer-2 "§ 6.1 Production and Consumption") [(2)](#ref-for-dfn-conforming-producer-3 "Reference 2") [(3)](#ref-for-dfn-conforming-producer-4 "Reference 3") [(4)](#ref-for-dfn-conforming-producer-5 "Reference 4") [(5)](#ref-for-dfn-conforming-producer-6 "Reference 5") +- [§ 6.2.1 Production](#ref-for-dfn-conforming-producer-7 "§ 6.2.1 Production") [(2)](#ref-for-dfn-conforming-producer-8 "Reference 2") +- [§ 6.3.1 Production](#ref-for-dfn-conforming-producer-9 "§ 6.3.1 Production") [(2)](#ref-for-dfn-conforming-producer-10 "Reference 2") [(3)](#ref-for-dfn-conforming-producer-11 "Reference 3") + +[Permalink](#dfn-conforming-consumer) + +**Referenced in:** + +- [§ 5.4 Services](#ref-for-dfn-conforming-consumer-1 "§ 5.4 Services") +- [§ 6.1 Production and Consumption](#ref-for-dfn-conforming-consumer-2 "§ 6.1 Production and Consumption") [(2)](#ref-for-dfn-conforming-consumer-3 "Reference 2") [(3)](#ref-for-dfn-conforming-consumer-4 "Reference 3") [(4)](#ref-for-dfn-conforming-consumer-5 "Reference 4") [(5)](#ref-for-dfn-conforming-consumer-6 "Reference 5") [(6)](#ref-for-dfn-conforming-consumer-7 "Reference 6") +- [§ 6.2.2 Consumption](#ref-for-dfn-conforming-consumer-8 "§ 6.2.2 Consumption") [(2)](#ref-for-dfn-conforming-consumer-9 "Reference 2") [(3)](#ref-for-dfn-conforming-consumer-10 "Reference 3") +- [§ 6.3.1 Production](#ref-for-dfn-conforming-consumer-11 "§ 6.3.1 Production") +- [§ 6.3.2 Consumption](#ref-for-dfn-conforming-consumer-12 "§ 6.3.2 Consumption") [(2)](#ref-for-dfn-conforming-consumer-13 "Reference 2") + +[Permalink](#dfn-amplification) + +**Referenced in:** + +- [§ 8.3 Security Requirements](#ref-for-dfn-amplification-1 "§ 8.3 Security Requirements") + +[Permalink](#dfn-authenticated) + +**Referenced in:** + +- [§ 1.1 A Simple Example](#ref-for-dfn-authenticated-1 "§ 1.1 A Simple Example") +- [§ 2. Terminology](#ref-for-dfn-authenticated-2 "§ 2. Terminology") [(2)](#ref-for-dfn-authenticated-3 "Reference 2") [(3)](#ref-for-dfn-authenticated-4 "Reference 3") +- [§ 5.2 Verification Methods](#ref-for-dfn-authenticated-5 "§ 5.2 Verification Methods") +- [§ 5.3.1 Authentication](#ref-for-dfn-authenticated-6 "§ 5.3.1 Authentication") [(2)](#ref-for-dfn-authenticated-7 "Reference 2") [(3)](#ref-for-dfn-authenticated-8 "Reference 3") [(4)](#ref-for-dfn-authenticated-9 "Reference 4") [(5)](#ref-for-dfn-authenticated-10 "Reference 5") [(6)](#ref-for-dfn-authenticated-11 "Reference 6") +- [§ B.12 Changing the DID controller](#ref-for-dfn-authenticated-12 "§ B.12 Changing the DID controller") + +[Permalink](#dfn-cryptosuite) + +**Referenced in:** + +- [§ 5.2.1 Verification Material](#ref-for-dfn-cryptosuite-1 "§ 5.2.1 Verification Material") + +[Permalink](#dfn-decentralized-identifiers) + +**Referenced in:** + +- [§ Abstract](#ref-for-dfn-decentralized-identifiers-1 "§ Abstract") [(2)](#ref-for-dfn-decentralized-identifiers-2 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-3 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-4 "Reference 4") [(5)](#ref-for-dfn-decentralized-identifiers-5 "Reference 5") [(6)](#ref-for-dfn-decentralized-identifiers-6 "Reference 6") [(7)](#ref-for-dfn-decentralized-identifiers-7 "Reference 7") [(8)](#ref-for-dfn-decentralized-identifiers-8 "Reference 8") [(9)](#ref-for-dfn-decentralized-identifiers-9 "Reference 9") +- [§ 1.1 A Simple Example](#ref-for-dfn-decentralized-identifiers-10 "§ 1.1 A Simple Example") [(2)](#ref-for-dfn-decentralized-identifiers-11 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-12 "Reference 3") +- [§ 1.2 Design Goals](#ref-for-dfn-decentralized-identifiers-13 "§ 1.2 Design Goals") [(2)](#ref-for-dfn-decentralized-identifiers-14 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-15 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-16 "Reference 4") +- [§ 1.3 Architecture Overview](#ref-for-dfn-decentralized-identifiers-17 "§ 1.3 Architecture Overview") [(2)](#ref-for-dfn-decentralized-identifiers-18 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-19 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-20 "Reference 4") [(5)](#ref-for-dfn-decentralized-identifiers-21 "Reference 5") [(6)](#ref-for-dfn-decentralized-identifiers-22 "Reference 6") [(7)](#ref-for-dfn-decentralized-identifiers-23 "Reference 7") [(8)](#ref-for-dfn-decentralized-identifiers-24 "Reference 8") [(9)](#ref-for-dfn-decentralized-identifiers-25 "Reference 9") [(10)](#ref-for-dfn-decentralized-identifiers-26 "Reference 10") [(11)](#ref-for-dfn-decentralized-identifiers-27 "Reference 11") [(12)](#ref-for-dfn-decentralized-identifiers-28 "Reference 12") [(13)](#ref-for-dfn-decentralized-identifiers-29 "Reference 13") [(14)](#ref-for-dfn-decentralized-identifiers-30 "Reference 14") +- [§ 1.4 Conformance](#ref-for-dfn-decentralized-identifiers-31 "§ 1.4 Conformance") [(2)](#ref-for-dfn-decentralized-identifiers-32 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-33 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-34 "Reference 4") [(5)](#ref-for-dfn-decentralized-identifiers-35 "Reference 5") +- [§ 2. Terminology](#ref-for-dfn-decentralized-identifiers-36 "§ 2. Terminology") [(2)](#ref-for-dfn-decentralized-identifiers-37 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-38 "Reference 3") [(5)](#ref-for-dfn-decentralized-identifiers-40 "Reference 5") [(6)](#ref-for-dfn-decentralized-identifiers-41 "Reference 6") [(7)](#ref-for-dfn-decentralized-identifiers-42 "Reference 7") [(8)](#ref-for-dfn-decentralized-identifiers-43 "Reference 8") [(9)](#ref-for-dfn-decentralized-identifiers-44 "Reference 9") [(10)](#ref-for-dfn-decentralized-identifiers-45 "Reference 10") [(11)](#ref-for-dfn-decentralized-identifiers-46 "Reference 11") [(12)](#ref-for-dfn-decentralized-identifiers-47 "Reference 12") [(13)](#ref-for-dfn-decentralized-identifiers-48 "Reference 13") [(14)](#ref-for-dfn-decentralized-identifiers-49 "Reference 14") [(15)](#ref-for-dfn-decentralized-identifiers-50 "Reference 15") [(16)](#ref-for-dfn-decentralized-identifiers-51 "Reference 16") [(17)](#ref-for-dfn-decentralized-identifiers-52 "Reference 17") [(18)](#ref-for-dfn-decentralized-identifiers-53 "Reference 18") +- [§ 3. Identifier](#ref-for-dfn-decentralized-identifiers-54 "§ 3. Identifier") [(2)](#ref-for-dfn-decentralized-identifiers-55 "Reference 2") +- [§ 3.1 DID Syntax](#ref-for-dfn-decentralized-identifiers-56 "§ 3.1 DID Syntax") [(2)](#ref-for-dfn-decentralized-identifiers-57 "Reference 2") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-decentralized-identifiers-58 "§ 3.2.1 DID Parameters") [(2)](#ref-for-dfn-decentralized-identifiers-59 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-60 "Reference 3") +- [§ 3.2.2 Relative DID URLs](#ref-for-dfn-decentralized-identifiers-61 "§ 3.2.2 Relative DID URLs") +- [§ 5. Core Properties](#ref-for-dfn-decentralized-identifiers-62 "§ 5. Core Properties") +- [§ 5.1.1 DID Subject](#ref-for-dfn-decentralized-identifiers-63 "§ 5.1.1 DID Subject") [(2)](#ref-for-dfn-decentralized-identifiers-64 "Reference 2") +- [§ 5.1.2 DID Controller](#ref-for-dfn-decentralized-identifiers-65 "§ 5.1.2 DID Controller") [(2)](#ref-for-dfn-decentralized-identifiers-66 "Reference 2") +- [§ 5.1.3 Also Known As](#ref-for-dfn-decentralized-identifiers-67 "§ 5.1.3 Also Known As") +- [§ 5.2.1 Verification Material](#ref-for-dfn-decentralized-identifiers-68 "§ 5.2.1 Verification Material") +- [§ 5.3.1 Authentication](#ref-for-dfn-decentralized-identifiers-69 "§ 5.3.1 Authentication") +- [§ 6.1 Production and Consumption](#ref-for-dfn-decentralized-identifiers-70 "§ 6.1 Production and Consumption") [(2)](#ref-for-dfn-decentralized-identifiers-71 "Reference 2") +- [§ 7.1 DID Resolution](#ref-for-dfn-decentralized-identifiers-72 "§ 7.1 DID Resolution") [(2)](#ref-for-dfn-decentralized-identifiers-73 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-74 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-75 "Reference 4") +- [§ 7.1.2 DID Resolution Metadata](#ref-for-dfn-decentralized-identifiers-76 "§ 7.1.2 DID Resolution Metadata") +- [§ 7.1.3 DID Document Metadata](#ref-for-dfn-decentralized-identifiers-77 "§ 7.1.3 DID Document Metadata") [(2)](#ref-for-dfn-decentralized-identifiers-78 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-79 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-80 "Reference 4") [(5)](#ref-for-dfn-decentralized-identifiers-81 "Reference 5") [(6)](#ref-for-dfn-decentralized-identifiers-82 "Reference 6") [(7)](#ref-for-dfn-decentralized-identifiers-83 "Reference 7") [(8)](#ref-for-dfn-decentralized-identifiers-84 "Reference 8") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-decentralized-identifiers-85 "§ 7.2 DID URL Dereferencing") +- [§ 7.3 Metadata Structure](#ref-for-dfn-decentralized-identifiers-86 "§ 7.3 Metadata Structure") +- [§ 8. Methods](#ref-for-dfn-decentralized-identifiers-87 "§ 8. Methods") [(2)](#ref-for-dfn-decentralized-identifiers-88 "Reference 2") +- [§ 8.1 Method Syntax](#ref-for-dfn-decentralized-identifiers-89 "§ 8.1 Method Syntax") [(2)](#ref-for-dfn-decentralized-identifiers-90 "Reference 2") +- [§ 8.2 Method Operations](#ref-for-dfn-decentralized-identifiers-91 "§ 8.2 Method Operations") [(2)](#ref-for-dfn-decentralized-identifiers-92 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-93 "Reference 3") +- [§ 8.3 Security Requirements](#ref-for-dfn-decentralized-identifiers-94 "§ 8.3 Security Requirements") [(2)](#ref-for-dfn-decentralized-identifiers-95 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-96 "Reference 3") +- [§ 9. Security Considerations](#ref-for-dfn-decentralized-identifiers-97 "§ 9. Security Considerations") [(2)](#ref-for-dfn-decentralized-identifiers-98 "Reference 2") +- [§ 9.2 Proving Control and Binding](#ref-for-dfn-decentralized-identifiers-99 "§ 9.2 Proving Control and Binding") [(2)](#ref-for-dfn-decentralized-identifiers-100 "Reference 2") +- [§ Proving Control of a DID and/or DID Document](#ref-for-dfn-decentralized-identifiers-101 "§ Proving Control of a DID and/or DID Document") [(2)](#ref-for-dfn-decentralized-identifiers-102 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-103 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-104 "Reference 4") +- [§ Binding to Physical Identity](#ref-for-dfn-decentralized-identifiers-105 "§ Binding to Physical Identity") [(2)](#ref-for-dfn-decentralized-identifiers-106 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-107 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-108 "Reference 4") +- [§ 9.4 Non-Repudiation](#ref-for-dfn-decentralized-identifiers-109 "§ 9.4 Non-Repudiation") +- [§ 9.5 Notification of DID Document Changes](#ref-for-dfn-decentralized-identifiers-110 "§ 9.5 Notification of DID Document Changes") [(2)](#ref-for-dfn-decentralized-identifiers-111 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-112 "Reference 3") +- [§ 9.6 Key and Signature Expiration](#ref-for-dfn-decentralized-identifiers-113 "§ 9.6 Key and Signature Expiration") +- [§ 9.7 Verification Method Rotation](#ref-for-dfn-decentralized-identifiers-114 "§ 9.7 Verification Method Rotation") +- [§ 9.8 Verification Method Revocation](#ref-for-dfn-decentralized-identifiers-115 "§ 9.8 Verification Method Revocation") +- [§ Revocation Semantics](#ref-for-dfn-decentralized-identifiers-116 "§ Revocation Semantics") [(2)](#ref-for-dfn-decentralized-identifiers-117 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-118 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-119 "Reference 4") [(5)](#ref-for-dfn-decentralized-identifiers-120 "Reference 5") [(6)](#ref-for-dfn-decentralized-identifiers-121 "Reference 6") +- [§ 9.9 DID Recovery](#ref-for-dfn-decentralized-identifiers-122 "§ 9.9 DID Recovery") [(2)](#ref-for-dfn-decentralized-identifiers-123 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-124 "Reference 3") +- [§ 9.10 The Role of Human-Friendly Identifiers](#ref-for-dfn-decentralized-identifiers-125 "§ 9.10 The Role of Human-Friendly Identifiers") [(2)](#ref-for-dfn-decentralized-identifiers-126 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-127 "Reference 3") +- [§ 9.11 DIDs as Enhanced URNs](#ref-for-dfn-decentralized-identifiers-128 "§ 9.11 DIDs as Enhanced URNs") [(2)](#ref-for-dfn-decentralized-identifiers-129 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-130 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-131 "Reference 4") [(5)](#ref-for-dfn-decentralized-identifiers-132 "Reference 5") [(6)](#ref-for-dfn-decentralized-identifiers-133 "Reference 6") [(7)](#ref-for-dfn-decentralized-identifiers-134 "Reference 7") [(8)](#ref-for-dfn-decentralized-identifiers-135 "Reference 8") +- [§ 9.14 Equivalence Properties](#ref-for-dfn-decentralized-identifiers-136 "§ 9.14 Equivalence Properties") [(2)](#ref-for-dfn-decentralized-identifiers-137 "Reference 2") +- [§ 9.16 Persistence](#ref-for-dfn-decentralized-identifiers-138 "§ 9.16 Persistence") [(2)](#ref-for-dfn-decentralized-identifiers-139 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-140 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-141 "Reference 4") [(5)](#ref-for-dfn-decentralized-identifiers-142 "Reference 5") [(6)](#ref-for-dfn-decentralized-identifiers-143 "Reference 6") [(7)](#ref-for-dfn-decentralized-identifiers-144 "Reference 7") [(8)](#ref-for-dfn-decentralized-identifiers-145 "Reference 8") [(9)](#ref-for-dfn-decentralized-identifiers-146 "Reference 9") [(10)](#ref-for-dfn-decentralized-identifiers-147 "Reference 10") +- [§ 10. Privacy Considerations](#ref-for-dfn-decentralized-identifiers-148 "§ 10. Privacy Considerations") [(2)](#ref-for-dfn-decentralized-identifiers-149 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-150 "Reference 3") +- [§ 10.1 Keep Personal Data Private](#ref-for-dfn-decentralized-identifiers-151 "§ 10.1 Keep Personal Data Private") +- [§ 10.2 DID Correlation Risks](#ref-for-dfn-decentralized-identifiers-152 "§ 10.2 DID Correlation Risks") [(2)](#ref-for-dfn-decentralized-identifiers-153 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-154 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-155 "Reference 4") [(5)](#ref-for-dfn-decentralized-identifiers-156 "Reference 5") [(6)](#ref-for-dfn-decentralized-identifiers-157 "Reference 6") +- [§ 10.3 DID Document Correlation Risks](#ref-for-dfn-decentralized-identifiers-158 "§ 10.3 DID Document Correlation Risks") [(2)](#ref-for-dfn-decentralized-identifiers-159 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-160 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-161 "Reference 4") [(5)](#ref-for-dfn-decentralized-identifiers-162 "Reference 5") [(6)](#ref-for-dfn-decentralized-identifiers-163 "Reference 6") +- [§ 10.4 DID Subject Classification](#ref-for-dfn-decentralized-identifiers-164 "§ 10.4 DID Subject Classification") [(2)](#ref-for-dfn-decentralized-identifiers-165 "Reference 2") +- [§ 10.5 Herd Privacy](#ref-for-dfn-decentralized-identifiers-166 "§ 10.5 Herd Privacy") +- [§ 10.6 Service Privacy](#ref-for-dfn-decentralized-identifiers-167 "§ 10.6 Service Privacy") [(2)](#ref-for-dfn-decentralized-identifiers-168 "Reference 2") +- [§ Maintaining Herd Privacy](#ref-for-dfn-decentralized-identifiers-169 "§ Maintaining Herd Privacy") [(2)](#ref-for-dfn-decentralized-identifiers-170 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-171 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-172 "Reference 4") +- [§ B.2 Creation of a DID](#ref-for-dfn-decentralized-identifiers-173 "§ B.2 Creation of a DID") [(2)](#ref-for-dfn-decentralized-identifiers-174 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-175 "Reference 3") +- [§ B.3 Determining the DID subject](#ref-for-dfn-decentralized-identifiers-176 "§ B.3 Determining the DID subject") [(2)](#ref-for-dfn-decentralized-identifiers-177 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-178 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-179 "Reference 4") [(5)](#ref-for-dfn-decentralized-identifiers-180 "Reference 5") [(6)](#ref-for-dfn-decentralized-identifiers-181 "Reference 6") [(7)](#ref-for-dfn-decentralized-identifiers-182 "Reference 7") [(8)](#ref-for-dfn-decentralized-identifiers-183 "Reference 8") [(9)](#ref-for-dfn-decentralized-identifiers-184 "Reference 9") [(10)](#ref-for-dfn-decentralized-identifiers-185 "Reference 10") [(11)](#ref-for-dfn-decentralized-identifiers-186 "Reference 11") [(12)](#ref-for-dfn-decentralized-identifiers-187 "Reference 12") [(13)](#ref-for-dfn-decentralized-identifiers-188 "Reference 13") [(14)](#ref-for-dfn-decentralized-identifiers-189 "Reference 14") +- [§ B.4 Referring to the DID document](#ref-for-dfn-decentralized-identifiers-190 "§ B.4 Referring to the DID document") [(2)](#ref-for-dfn-decentralized-identifiers-191 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-192 "Reference 3") +- [§ B.5 Statements in the DID document](#ref-for-dfn-decentralized-identifiers-193 "§ B.5 Statements in the DID document") +- [§ B.6 Discovering more information about the DID subject](#ref-for-dfn-decentralized-identifiers-194 "§ B.6 Discovering more information about the DID subject") [(2)](#ref-for-dfn-decentralized-identifiers-195 "Reference 2") +- [§ B.7 Serving a representation of the DID subject](#ref-for-dfn-decentralized-identifiers-196 "§ B.7 Serving a representation of the DID subject") [(2)](#ref-for-dfn-decentralized-identifiers-197 "Reference 2") +- [§ B.8 Assigning DIDs to existing web resources](#ref-for-dfn-decentralized-identifiers-198 "§ B.8 Assigning DIDs to existing web resources") [(2)](#ref-for-dfn-decentralized-identifiers-199 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-200 "Reference 3") [(4)](#ref-for-dfn-decentralized-identifiers-201 "Reference 4") +- [§ B.9.1 Set #1: The DID subject is the DID controller](#ref-for-dfn-decentralized-identifiers-202 "§ B.9.1 Set #1: The DID subject is the DID controller") +- [§ B.9.2 Set #2: The DID subject is not the DID controller](#ref-for-dfn-decentralized-identifiers-203 "§ B.9.2 Set #2: The DID subject is not the DID controller") [(2)](#ref-for-dfn-decentralized-identifiers-204 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-205 "Reference 3") +- [§ B.10.1 Independent Control](#ref-for-dfn-decentralized-identifiers-206 "§ B.10.1 Independent Control") +- [§ B.11 Changing the DID subject](#ref-for-dfn-decentralized-identifiers-207 "§ B.11 Changing the DID subject") [(2)](#ref-for-dfn-decentralized-identifiers-208 "Reference 2") [(3)](#ref-for-dfn-decentralized-identifiers-209 "Reference 3") + +[Permalink](#dfn-decentralized-identity-management) + +**Referenced in:** + +- [§ 5.4 Services](#ref-for-dfn-decentralized-identity-management-1 "§ 5.4 Services") + +[Permalink](#dfn-did-controllers) + +**Referenced in:** + +- [§ Abstract](#ref-for-dfn-did-controllers-1 "§ Abstract") +- [§ 1.1 A Simple Example](#ref-for-dfn-did-controllers-2 "§ 1.1 A Simple Example") +- [§ 1.2 Design Goals](#ref-for-dfn-did-controllers-3 "§ 1.2 Design Goals") +- [§ 1.3 Architecture Overview](#ref-for-dfn-did-controllers-4 "§ 1.3 Architecture Overview") [(2)](#ref-for-dfn-did-controllers-5 "Reference 2") +- [§ 2. Terminology](#ref-for-dfn-did-controllers-6 "§ 2. Terminology") +- [§ Path](#ref-for-dfn-did-controllers-7 "§ Path") +- [§ 5.1 Identifiers](#ref-for-dfn-did-controllers-8 "§ 5.1 Identifiers") +- [§ 5.1.2 DID Controller](#ref-for-dfn-did-controllers-9 "§ 5.1.2 DID Controller") [(2)](#ref-for-dfn-did-controllers-10 "Reference 2") [(3)](#ref-for-dfn-did-controllers-11 "Reference 3") +- [§ 5.2 Verification Methods](#ref-for-dfn-did-controllers-12 "§ 5.2 Verification Methods") [(2)](#ref-for-dfn-did-controllers-13 "Reference 2") +- [§ 5.3.1 Authentication](#ref-for-dfn-did-controllers-14 "§ 5.3.1 Authentication") [(2)](#ref-for-dfn-did-controllers-15 "Reference 2") +- [§ 5.3.5 Capability Delegation](#ref-for-dfn-did-controllers-16 "§ 5.3.5 Capability Delegation") +- [§ 8.2 Method Operations](#ref-for-dfn-did-controllers-17 "§ 8.2 Method Operations") [(2)](#ref-for-dfn-did-controllers-18 "Reference 2") [(3)](#ref-for-dfn-did-controllers-19 "Reference 3") +- [§ 9.5 Notification of DID Document Changes](#ref-for-dfn-did-controllers-20 "§ 9.5 Notification of DID Document Changes") [(2)](#ref-for-dfn-did-controllers-21 "Reference 2") +- [§ Revocation Semantics](#ref-for-dfn-did-controllers-22 "§ Revocation Semantics") +- [§ 9.10 The Role of Human-Friendly Identifiers](#ref-for-dfn-did-controllers-23 "§ 9.10 The Role of Human-Friendly Identifiers") +- [§ 9.11 DIDs as Enhanced URNs](#ref-for-dfn-did-controllers-24 "§ 9.11 DIDs as Enhanced URNs") [(2)](#ref-for-dfn-did-controllers-25 "Reference 2") [(3)](#ref-for-dfn-did-controllers-26 "Reference 3") [(4)](#ref-for-dfn-did-controllers-27 "Reference 4") [(5)](#ref-for-dfn-did-controllers-28 "Reference 5") [(6)](#ref-for-dfn-did-controllers-29 "Reference 6") +- [§ 10. Privacy Considerations](#ref-for-dfn-did-controllers-30 "§ 10. Privacy Considerations") +- [§ 10.1 Keep Personal Data Private](#ref-for-dfn-did-controllers-31 "§ 10.1 Keep Personal Data Private") +- [§ 10.2 DID Correlation Risks](#ref-for-dfn-did-controllers-32 "§ 10.2 DID Correlation Risks") [(2)](#ref-for-dfn-did-controllers-33 "Reference 2") +- [§ 10.4 DID Subject Classification](#ref-for-dfn-did-controllers-34 "§ 10.4 DID Subject Classification") +- [§ B.3 Determining the DID subject](#ref-for-dfn-did-controllers-35 "§ B.3 Determining the DID subject") +- [§ B.4 Referring to the DID document](#ref-for-dfn-did-controllers-36 "§ B.4 Referring to the DID document") [(2)](#ref-for-dfn-did-controllers-37 "Reference 2") +- [§ B.5 Statements in the DID document](#ref-for-dfn-did-controllers-38 "§ B.5 Statements in the DID document") +- [§ B.6 Discovering more information about the DID subject](#ref-for-dfn-did-controllers-39 "§ B.6 Discovering more information about the DID subject") +- [§ B.9 The relationship between DID controllers and DID subjects](#ref-for-dfn-did-controllers-40 "§ B.9 The relationship between DID controllers and DID subjects") +- [§ B.9.1 Set #1: The DID subject is the DID controller](#ref-for-dfn-did-controllers-41 "§ B.9.1 Set #1: The DID subject is the DID controller") [(2)](#ref-for-dfn-did-controllers-42 "Reference 2") [(3)](#ref-for-dfn-did-controllers-43 "Reference 3") +- [§ B.9.2 Set #2: The DID subject is not the DID controller](#ref-for-dfn-did-controllers-44 "§ B.9.2 Set #2: The DID subject is not the DID controller") [(2)](#ref-for-dfn-did-controllers-45 "Reference 2") +- [§ B.10 Multiple DID controllers](#ref-for-dfn-did-controllers-46 "§ B.10 Multiple DID controllers") +- [§ B.10.1 Independent Control](#ref-for-dfn-did-controllers-47 "§ B.10.1 Independent Control") [(2)](#ref-for-dfn-did-controllers-48 "Reference 2") [(3)](#ref-for-dfn-did-controllers-49 "Reference 3") [(4)](#ref-for-dfn-did-controllers-50 "Reference 4") +- [§ B.10.2 Group Control](#ref-for-dfn-did-controllers-51 "§ B.10.2 Group Control") [(2)](#ref-for-dfn-did-controllers-52 "Reference 2") [(3)](#ref-for-dfn-did-controllers-53 "Reference 3") [(4)](#ref-for-dfn-did-controllers-54 "Reference 4") [(5)](#ref-for-dfn-did-controllers-55 "Reference 5") [(6)](#ref-for-dfn-did-controllers-56 "Reference 6") [(7)](#ref-for-dfn-did-controllers-57 "Reference 7") +- [§ B.11 Changing the DID subject](#ref-for-dfn-did-controllers-58 "§ B.11 Changing the DID subject") +- [§ B.12 Changing the DID controller](#ref-for-dfn-did-controllers-59 "§ B.12 Changing the DID controller") [(2)](#ref-for-dfn-did-controllers-60 "Reference 2") [(3)](#ref-for-dfn-did-controllers-61 "Reference 3") [(4)](#ref-for-dfn-did-controllers-62 "Reference 4") + +[Permalink](#dfn-did-delegate) + +**Referenced in:** + +- [§ 2. Terminology](#ref-for-dfn-did-delegate-1 "§ 2. Terminology") [(2)](#ref-for-dfn-did-delegate-2 "Reference 2") + +[Permalink](#dfn-did-documents) + +**Referenced in:** + +- [§ Abstract](#ref-for-dfn-did-documents-1 "§ Abstract") [(2)](#ref-for-dfn-did-documents-2 "Reference 2") +- [§ 1.1 A Simple Example](#ref-for-dfn-did-documents-3 "§ 1.1 A Simple Example") [(2)](#ref-for-dfn-did-documents-4 "Reference 2") +- [§ 1.2 Design Goals](#ref-for-dfn-did-documents-5 "§ 1.2 Design Goals") +- [§ 1.3 Architecture Overview](#ref-for-dfn-did-documents-6 "§ 1.3 Architecture Overview") [(2)](#ref-for-dfn-did-documents-7 "Reference 2") [(3)](#ref-for-dfn-did-documents-8 "Reference 3") [(4)](#ref-for-dfn-did-documents-9 "Reference 4") [(5)](#ref-for-dfn-did-documents-10 "Reference 5") [(6)](#ref-for-dfn-did-documents-11 "Reference 6") [(7)](#ref-for-dfn-did-documents-12 "Reference 7") [(8)](#ref-for-dfn-did-documents-13 "Reference 8") [(9)](#ref-for-dfn-did-documents-14 "Reference 9") [(10)](#ref-for-dfn-did-documents-15 "Reference 10") [(11)](#ref-for-dfn-did-documents-16 "Reference 11") [(12)](#ref-for-dfn-did-documents-17 "Reference 12") +- [§ 1.4 Conformance](#ref-for-dfn-did-documents-18 "§ 1.4 Conformance") [(2)](#ref-for-dfn-did-documents-19 "Reference 2") [(3)](#ref-for-dfn-did-documents-20 "Reference 3") [(4)](#ref-for-dfn-did-documents-21 "Reference 4") [(5)](#ref-for-dfn-did-documents-22 "Reference 5") +- [§ 2. Terminology](#ref-for-dfn-did-documents-23 "§ 2. Terminology") [(3)](#ref-for-dfn-did-documents-25 "Reference 3") [(4)](#ref-for-dfn-did-documents-26 "Reference 4") [(5)](#ref-for-dfn-did-documents-27 "Reference 5") [(6)](#ref-for-dfn-did-documents-28 "Reference 6") [(7)](#ref-for-dfn-did-documents-29 "Reference 7") [(8)](#ref-for-dfn-did-documents-30 "Reference 8") [(9)](#ref-for-dfn-did-documents-31 "Reference 9") [(10)](#ref-for-dfn-did-documents-32 "Reference 10") [(11)](#ref-for-dfn-did-documents-33 "Reference 11") [(12)](#ref-for-dfn-did-documents-34 "Reference 12") [(13)](#ref-for-dfn-did-documents-35 "Reference 13") [(14)](#ref-for-dfn-did-documents-36 "Reference 14") [(15)](#ref-for-dfn-did-documents-37 "Reference 15") [(16)](#ref-for-dfn-did-documents-38 "Reference 16") [(17)](#ref-for-dfn-did-documents-39 "Reference 17") [(18)](#ref-for-dfn-did-documents-40 "Reference 18") [(19)](#ref-for-dfn-did-documents-41 "Reference 19") [(20)](#ref-for-dfn-did-documents-42 "Reference 20") +- [§ 3.2 DID URL Syntax](#ref-for-dfn-did-documents-43 "§ 3.2 DID URL Syntax") +- [§ Fragment](#ref-for-dfn-did-documents-44 "§ Fragment") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-did-documents-45 "§ 3.2.1 DID Parameters") [(2)](#ref-for-dfn-did-documents-46 "Reference 2") [(3)](#ref-for-dfn-did-documents-47 "Reference 3") [(4)](#ref-for-dfn-did-documents-48 "Reference 4") [(5)](#ref-for-dfn-did-documents-49 "Reference 5") [(6)](#ref-for-dfn-did-documents-50 "Reference 6") +- [§ 3.2.2 Relative DID URLs](#ref-for-dfn-did-documents-51 "§ 3.2.2 Relative DID URLs") [(2)](#ref-for-dfn-did-documents-52 "Reference 2") [(3)](#ref-for-dfn-did-documents-53 "Reference 3") [(4)](#ref-for-dfn-did-documents-54 "Reference 4") +- [§ 4. Data Model](#ref-for-dfn-did-documents-55 "§ 4. Data Model") [(2)](#ref-for-dfn-did-documents-56 "Reference 2") [(3)](#ref-for-dfn-did-documents-57 "Reference 3") [(4)](#ref-for-dfn-did-documents-58 "Reference 4") +- [§ 5. Core Properties](#ref-for-dfn-did-documents-59 "§ 5. Core Properties") [(2)](#ref-for-dfn-did-documents-60 "Reference 2") [(3)](#ref-for-dfn-did-documents-61 "Reference 3") +- [§ 5.1 Identifiers](#ref-for-dfn-did-documents-62 "§ 5.1 Identifiers") +- [§ 5.1.1 DID Subject](#ref-for-dfn-did-documents-63 "§ 5.1.1 DID Subject") [(2)](#ref-for-dfn-did-documents-64 "Reference 2") [(3)](#ref-for-dfn-did-documents-65 "Reference 3") [(4)](#ref-for-dfn-did-documents-66 "Reference 4") [(5)](#ref-for-dfn-did-documents-67 "Reference 5") +- [§ 5.1.2 DID Controller](#ref-for-dfn-did-documents-68 "§ 5.1.2 DID Controller") [(2)](#ref-for-dfn-did-documents-69 "Reference 2") [(3)](#ref-for-dfn-did-documents-70 "Reference 3") [(4)](#ref-for-dfn-did-documents-71 "Reference 4") +- [§ 5.1.3 Also Known As](#ref-for-dfn-did-documents-72 "§ 5.1.3 Also Known As") +- [§ 5.2 Verification Methods](#ref-for-dfn-did-documents-73 "§ 5.2 Verification Methods") [(2)](#ref-for-dfn-did-documents-74 "Reference 2") [(3)](#ref-for-dfn-did-documents-75 "Reference 3") [(4)](#ref-for-dfn-did-documents-76 "Reference 4") +- [§ 5.2.1 Verification Material](#ref-for-dfn-did-documents-77 "§ 5.2.1 Verification Material") [(2)](#ref-for-dfn-did-documents-78 "Reference 2") +- [§ 5.2.2 Referring to Verification Methods](#ref-for-dfn-did-documents-79 "§ 5.2.2 Referring to Verification Methods") [(2)](#ref-for-dfn-did-documents-80 "Reference 2") +- [§ 5.3 Verification Relationships](#ref-for-dfn-did-documents-81 "§ 5.3 Verification Relationships") [(2)](#ref-for-dfn-did-documents-82 "Reference 2") [(3)](#ref-for-dfn-did-documents-83 "Reference 3") [(4)](#ref-for-dfn-did-documents-84 "Reference 4") [(5)](#ref-for-dfn-did-documents-85 "Reference 5") +- [§ 5.3.1 Authentication](#ref-for-dfn-did-documents-86 "§ 5.3.1 Authentication") [(2)](#ref-for-dfn-did-documents-87 "Reference 2") [(3)](#ref-for-dfn-did-documents-88 "Reference 3") [(4)](#ref-for-dfn-did-documents-89 "Reference 4") [(5)](#ref-for-dfn-did-documents-90 "Reference 5") +- [§ 5.3.2 Assertion](#ref-for-dfn-did-documents-91 "§ 5.3.2 Assertion") +- [§ 5.3.4 Capability Invocation](#ref-for-dfn-did-documents-92 "§ 5.3.4 Capability Invocation") [(2)](#ref-for-dfn-did-documents-93 "Reference 2") +- [§ 5.4 Services](#ref-for-dfn-did-documents-94 "§ 5.4 Services") +- [§ 6. Representations](#ref-for-dfn-did-documents-95 "§ 6. Representations") +- [§ 6.1 Production and Consumption](#ref-for-dfn-did-documents-96 "§ 6.1 Production and Consumption") [(2)](#ref-for-dfn-did-documents-97 "Reference 2") [(3)](#ref-for-dfn-did-documents-98 "Reference 3") [(4)](#ref-for-dfn-did-documents-99 "Reference 4") [(5)](#ref-for-dfn-did-documents-100 "Reference 5") [(6)](#ref-for-dfn-did-documents-101 "Reference 6") [(7)](#ref-for-dfn-did-documents-102 "Reference 7") +- [§ 6.2.1 Production](#ref-for-dfn-did-documents-103 "§ 6.2.1 Production") [(2)](#ref-for-dfn-did-documents-104 "Reference 2") [(3)](#ref-for-dfn-did-documents-105 "Reference 3") +- [§ 6.2.2 Consumption](#ref-for-dfn-did-documents-106 "§ 6.2.2 Consumption") [(2)](#ref-for-dfn-did-documents-107 "Reference 2") [(3)](#ref-for-dfn-did-documents-108 "Reference 3") [(4)](#ref-for-dfn-did-documents-109 "Reference 4") +- [§ 6.3.1 Production](#ref-for-dfn-did-documents-110 "§ 6.3.1 Production") [(2)](#ref-for-dfn-did-documents-111 "Reference 2") [(3)](#ref-for-dfn-did-documents-112 "Reference 3") +- [§ 6.3.2 Consumption](#ref-for-dfn-did-documents-113 "§ 6.3.2 Consumption") [(2)](#ref-for-dfn-did-documents-114 "Reference 2") +- [§ 7. Resolution](#ref-for-dfn-did-documents-115 "§ 7. Resolution") +- [§ 7.1 DID Resolution](#ref-for-dfn-did-documents-116 "§ 7.1 DID Resolution") [(2)](#ref-for-dfn-did-documents-117 "Reference 2") [(3)](#ref-for-dfn-did-documents-118 "Reference 3") [(4)](#ref-for-dfn-did-documents-119 "Reference 4") [(5)](#ref-for-dfn-did-documents-120 "Reference 5") [(6)](#ref-for-dfn-did-documents-121 "Reference 6") [(7)](#ref-for-dfn-did-documents-122 "Reference 7") [(8)](#ref-for-dfn-did-documents-123 "Reference 8") [(9)](#ref-for-dfn-did-documents-124 "Reference 9") +- [§ 7.1.1 DID Resolution Options](#ref-for-dfn-did-documents-125 "§ 7.1.1 DID Resolution Options") +- [§ 7.1.2 DID Resolution Metadata](#ref-for-dfn-did-documents-126 "§ 7.1.2 DID Resolution Metadata") +- [§ 7.1.3 DID Document Metadata](#ref-for-dfn-did-documents-127 "§ 7.1.3 DID Document Metadata") [(2)](#ref-for-dfn-did-documents-128 "Reference 2") [(3)](#ref-for-dfn-did-documents-129 "Reference 3") [(4)](#ref-for-dfn-did-documents-130 "Reference 4") [(5)](#ref-for-dfn-did-documents-131 "Reference 5") [(6)](#ref-for-dfn-did-documents-132 "Reference 6") [(7)](#ref-for-dfn-did-documents-133 "Reference 7") [(8)](#ref-for-dfn-did-documents-134 "Reference 8") [(9)](#ref-for-dfn-did-documents-135 "Reference 9") [(10)](#ref-for-dfn-did-documents-136 "Reference 10") [(11)](#ref-for-dfn-did-documents-137 "Reference 11") [(12)](#ref-for-dfn-did-documents-138 "Reference 12") [(13)](#ref-for-dfn-did-documents-139 "Reference 13") [(14)](#ref-for-dfn-did-documents-140 "Reference 14") [(15)](#ref-for-dfn-did-documents-141 "Reference 15") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-did-documents-142 "§ 7.2 DID URL Dereferencing") [(2)](#ref-for-dfn-did-documents-143 "Reference 2") +- [§ 7.3 Metadata Structure](#ref-for-dfn-did-documents-144 "§ 7.3 Metadata Structure") +- [§ 8. Methods](#ref-for-dfn-did-documents-145 "§ 8. Methods") +- [§ 8.2 Method Operations](#ref-for-dfn-did-documents-146 "§ 8.2 Method Operations") [(2)](#ref-for-dfn-did-documents-147 "Reference 2") [(3)](#ref-for-dfn-did-documents-148 "Reference 3") [(4)](#ref-for-dfn-did-documents-149 "Reference 4") [(5)](#ref-for-dfn-did-documents-150 "Reference 5") [(6)](#ref-for-dfn-did-documents-151 "Reference 6") +- [§ 8.3 Security Requirements](#ref-for-dfn-did-documents-152 "§ 8.3 Security Requirements") +- [§ 9.2 Proving Control and Binding](#ref-for-dfn-did-documents-153 "§ 9.2 Proving Control and Binding") [(2)](#ref-for-dfn-did-documents-154 "Reference 2") +- [§ Proving Control of a DID and/or DID Document](#ref-for-dfn-did-documents-155 "§ Proving Control of a DID and/or DID Document") [(2)](#ref-for-dfn-did-documents-156 "Reference 2") [(3)](#ref-for-dfn-did-documents-157 "Reference 3") [(4)](#ref-for-dfn-did-documents-158 "Reference 4") [(5)](#ref-for-dfn-did-documents-159 "Reference 5") +- [§ Binding to Physical Identity](#ref-for-dfn-did-documents-160 "§ Binding to Physical Identity") [(2)](#ref-for-dfn-did-documents-161 "Reference 2") +- [§ 9.3 Authentication Service Endpoints](#ref-for-dfn-did-documents-162 "§ 9.3 Authentication Service Endpoints") +- [§ 9.4 Non-Repudiation](#ref-for-dfn-did-documents-163 "§ 9.4 Non-Repudiation") +- [§ 9.5 Notification of DID Document Changes](#ref-for-dfn-did-documents-164 "§ 9.5 Notification of DID Document Changes") +- [§ 9.7 Verification Method Rotation](#ref-for-dfn-did-documents-165 "§ 9.7 Verification Method Rotation") [(2)](#ref-for-dfn-did-documents-166 "Reference 2") [(3)](#ref-for-dfn-did-documents-167 "Reference 3") +- [§ 9.8 Verification Method Revocation](#ref-for-dfn-did-documents-168 "§ 9.8 Verification Method Revocation") [(2)](#ref-for-dfn-did-documents-169 "Reference 2") [(3)](#ref-for-dfn-did-documents-170 "Reference 3") [(4)](#ref-for-dfn-did-documents-171 "Reference 4") +- [§ Revocation Semantics](#ref-for-dfn-did-documents-172 "§ Revocation Semantics") [(2)](#ref-for-dfn-did-documents-173 "Reference 2") +- [§ Revocation in Trustless Systems](#ref-for-dfn-did-documents-174 "§ Revocation in Trustless Systems") [(2)](#ref-for-dfn-did-documents-175 "Reference 2") [(3)](#ref-for-dfn-did-documents-176 "Reference 3") [(4)](#ref-for-dfn-did-documents-177 "Reference 4") +- [§ 9.11 DIDs as Enhanced URNs](#ref-for-dfn-did-documents-178 "§ 9.11 DIDs as Enhanced URNs") +- [§ 9.12 Immutability](#ref-for-dfn-did-documents-179 "§ 9.12 Immutability") [(2)](#ref-for-dfn-did-documents-180 "Reference 2") [(3)](#ref-for-dfn-did-documents-181 "Reference 3") [(4)](#ref-for-dfn-did-documents-182 "Reference 4") [(5)](#ref-for-dfn-did-documents-183 "Reference 5") +- [§ 9.13 Encrypted Data in DID Documents](#ref-for-dfn-did-documents-184 "§ 9.13 Encrypted Data in DID Documents") [(2)](#ref-for-dfn-did-documents-185 "Reference 2") [(3)](#ref-for-dfn-did-documents-186 "Reference 3") [(4)](#ref-for-dfn-did-documents-187 "Reference 4") [(5)](#ref-for-dfn-did-documents-188 "Reference 5") +- [§ 9.14 Equivalence Properties](#ref-for-dfn-did-documents-189 "§ 9.14 Equivalence Properties") [(2)](#ref-for-dfn-did-documents-190 "Reference 2") [(3)](#ref-for-dfn-did-documents-191 "Reference 3") [(4)](#ref-for-dfn-did-documents-192 "Reference 4") [(5)](#ref-for-dfn-did-documents-193 "Reference 5") [(6)](#ref-for-dfn-did-documents-194 "Reference 6") +- [§ 9.15 Content Integrity Protection](#ref-for-dfn-did-documents-195 "§ 9.15 Content Integrity Protection") [(2)](#ref-for-dfn-did-documents-196 "Reference 2") [(3)](#ref-for-dfn-did-documents-197 "Reference 3") [(4)](#ref-for-dfn-did-documents-198 "Reference 4") +- [§ 9.17 Level of Assurance](#ref-for-dfn-did-documents-199 "§ 9.17 Level of Assurance") [(2)](#ref-for-dfn-did-documents-200 "Reference 2") +- [§ 10. Privacy Considerations](#ref-for-dfn-did-documents-201 "§ 10. Privacy Considerations") +- [§ 10.1 Keep Personal Data Private](#ref-for-dfn-did-documents-202 "§ 10.1 Keep Personal Data Private") [(2)](#ref-for-dfn-did-documents-203 "Reference 2") [(3)](#ref-for-dfn-did-documents-204 "Reference 3") [(4)](#ref-for-dfn-did-documents-205 "Reference 4") +- [§ 10.3 DID Document Correlation Risks](#ref-for-dfn-did-documents-206 "§ 10.3 DID Document Correlation Risks") [(2)](#ref-for-dfn-did-documents-207 "Reference 2") [(3)](#ref-for-dfn-did-documents-208 "Reference 3") [(4)](#ref-for-dfn-did-documents-209 "Reference 4") +- [§ 10.4 DID Subject Classification](#ref-for-dfn-did-documents-210 "§ 10.4 DID Subject Classification") [(2)](#ref-for-dfn-did-documents-211 "Reference 2") [(3)](#ref-for-dfn-did-documents-212 "Reference 3") [(4)](#ref-for-dfn-did-documents-213 "Reference 4") +- [§ 10.6 Service Privacy](#ref-for-dfn-did-documents-214 "§ 10.6 Service Privacy") [(2)](#ref-for-dfn-did-documents-215 "Reference 2") [(3)](#ref-for-dfn-did-documents-216 "Reference 3") [(4)](#ref-for-dfn-did-documents-217 "Reference 4") [(5)](#ref-for-dfn-did-documents-218 "Reference 5") [(6)](#ref-for-dfn-did-documents-219 "Reference 6") +- [§ Maintaining Herd Privacy](#ref-for-dfn-did-documents-220 "§ Maintaining Herd Privacy") [(2)](#ref-for-dfn-did-documents-221 "Reference 2") +- [§ Service Endpoint Alternatives](#ref-for-dfn-did-documents-222 "§ Service Endpoint Alternatives") +- [§ B.2 Creation of a DID](#ref-for-dfn-did-documents-223 "§ B.2 Creation of a DID") [(2)](#ref-for-dfn-did-documents-224 "Reference 2") +- [§ B.3 Determining the DID subject](#ref-for-dfn-did-documents-225 "§ B.3 Determining the DID subject") [(2)](#ref-for-dfn-did-documents-226 "Reference 2") +- [§ B.4 Referring to the DID document](#ref-for-dfn-did-documents-227 "§ B.4 Referring to the DID document") [(2)](#ref-for-dfn-did-documents-228 "Reference 2") [(3)](#ref-for-dfn-did-documents-229 "Reference 3") [(4)](#ref-for-dfn-did-documents-230 "Reference 4") [(5)](#ref-for-dfn-did-documents-231 "Reference 5") +- [§ B.5 Statements in the DID document](#ref-for-dfn-did-documents-232 "§ B.5 Statements in the DID document") [(2)](#ref-for-dfn-did-documents-233 "Reference 2") [(3)](#ref-for-dfn-did-documents-234 "Reference 3") [(4)](#ref-for-dfn-did-documents-235 "Reference 4") +- [§ B.6 Discovering more information about the DID subject](#ref-for-dfn-did-documents-236 "§ B.6 Discovering more information about the DID subject") [(2)](#ref-for-dfn-did-documents-237 "Reference 2") [(3)](#ref-for-dfn-did-documents-238 "Reference 3") +- [§ B.8 Assigning DIDs to existing web resources](#ref-for-dfn-did-documents-239 "§ B.8 Assigning DIDs to existing web resources") [(2)](#ref-for-dfn-did-documents-240 "Reference 2") +- [§ B.10 Multiple DID controllers](#ref-for-dfn-did-documents-241 "§ B.10 Multiple DID controllers") +- [§ B.10.1 Independent Control](#ref-for-dfn-did-documents-242 "§ B.10.1 Independent Control") [(2)](#ref-for-dfn-did-documents-243 "Reference 2") +- [§ B.11 Changing the DID subject](#ref-for-dfn-did-documents-244 "§ B.11 Changing the DID subject") [(2)](#ref-for-dfn-did-documents-245 "Reference 2") +- [§ B.12 Changing the DID controller](#ref-for-dfn-did-documents-246 "§ B.12 Changing the DID controller") [(2)](#ref-for-dfn-did-documents-247 "Reference 2") [(3)](#ref-for-dfn-did-documents-248 "Reference 3") [(4)](#ref-for-dfn-did-documents-249 "Reference 4") + +[Permalink](#dfn-did-fragments) + +**Referenced in:** + +- [§ 2. Terminology](#ref-for-dfn-did-fragments-1 "§ 2. Terminology") +- [§ Fragment](#ref-for-dfn-did-fragments-2 "§ Fragment") [(2)](#ref-for-dfn-did-fragments-3 "Reference 2") [(3)](#ref-for-dfn-did-fragments-4 "Reference 3") [(4)](#ref-for-dfn-did-fragments-5 "Reference 4") [(5)](#ref-for-dfn-did-fragments-6 "Reference 5") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-did-fragments-7 "§ 7.2 DID URL Dereferencing") [(2)](#ref-for-dfn-did-fragments-8 "Reference 2") +- [§ 8.1 Method Syntax](#ref-for-dfn-did-fragments-9 "§ 8.1 Method Syntax") + +[Permalink](#dfn-did-methods) + +**Referenced in:** + +- [§ 1.1 A Simple Example](#ref-for-dfn-did-methods-1 "§ 1.1 A Simple Example") +- [§ 1.2 Design Goals](#ref-for-dfn-did-methods-2 "§ 1.2 Design Goals") +- [§ 1.3 Architecture Overview](#ref-for-dfn-did-methods-3 "§ 1.3 Architecture Overview") [(2)](#ref-for-dfn-did-methods-4 "Reference 2") [(3)](#ref-for-dfn-did-methods-5 "Reference 3") [(4)](#ref-for-dfn-did-methods-6 "Reference 4") [(5)](#ref-for-dfn-did-methods-7 "Reference 5") +- [§ 1.4 Conformance](#ref-for-dfn-did-methods-8 "§ 1.4 Conformance") [(2)](#ref-for-dfn-did-methods-9 "Reference 2") [(3)](#ref-for-dfn-did-methods-10 "Reference 3") [(4)](#ref-for-dfn-did-methods-11 "Reference 4") +- [§ 2. Terminology](#ref-for-dfn-did-methods-12 "§ 2. Terminology") [(2)](#ref-for-dfn-did-methods-13 "Reference 2") [(3)](#ref-for-dfn-did-methods-14 "Reference 3") [(4)](#ref-for-dfn-did-methods-15 "Reference 4") +- [§ 3. Identifier](#ref-for-dfn-did-methods-16 "§ 3. Identifier") +- [§ 3.1 DID Syntax](#ref-for-dfn-did-methods-17 "§ 3.1 DID Syntax") +- [§ 3.2 DID URL Syntax](#ref-for-dfn-did-methods-18 "§ 3.2 DID URL Syntax") +- [§ Path](#ref-for-dfn-did-methods-19 "§ Path") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-did-methods-20 "§ 3.2.1 DID Parameters") [(2)](#ref-for-dfn-did-methods-21 "Reference 2") [(3)](#ref-for-dfn-did-methods-22 "Reference 3") [(4)](#ref-for-dfn-did-methods-23 "Reference 4") [(5)](#ref-for-dfn-did-methods-24 "Reference 5") +- [§ 3.2.2 Relative DID URLs](#ref-for-dfn-did-methods-25 "§ 3.2.2 Relative DID URLs") +- [§ 5.1.1 DID Subject](#ref-for-dfn-did-methods-26 "§ 5.1.1 DID Subject") +- [§ 5.1.2 DID Controller](#ref-for-dfn-did-methods-27 "§ 5.1.2 DID Controller") +- [§ 5.3 Verification Relationships](#ref-for-dfn-did-methods-28 "§ 5.3 Verification Relationships") +- [§ 5.3.1 Authentication](#ref-for-dfn-did-methods-29 "§ 5.3.1 Authentication") [(2)](#ref-for-dfn-did-methods-30 "Reference 2") [(3)](#ref-for-dfn-did-methods-31 "Reference 3") [(4)](#ref-for-dfn-did-methods-32 "Reference 4") +- [§ 7. Resolution](#ref-for-dfn-did-methods-33 "§ 7. Resolution") +- [§ 7.1 DID Resolution](#ref-for-dfn-did-methods-34 "§ 7.1 DID Resolution") +- [§ 7.1.2 DID Resolution Metadata](#ref-for-dfn-did-methods-35 "§ 7.1.2 DID Resolution Metadata") +- [§ 7.1.3 DID Document Metadata](#ref-for-dfn-did-methods-36 "§ 7.1.3 DID Document Metadata") [(2)](#ref-for-dfn-did-methods-37 "Reference 2") [(3)](#ref-for-dfn-did-methods-38 "Reference 3") [(4)](#ref-for-dfn-did-methods-39 "Reference 4") [(5)](#ref-for-dfn-did-methods-40 "Reference 5") [(6)](#ref-for-dfn-did-methods-41 "Reference 6") [(7)](#ref-for-dfn-did-methods-42 "Reference 7") [(8)](#ref-for-dfn-did-methods-43 "Reference 8") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-did-methods-44 "§ 7.2 DID URL Dereferencing") +- [§ 8. Methods](#ref-for-dfn-did-methods-45 "§ 8. Methods") [(2)](#ref-for-dfn-did-methods-46 "Reference 2") [(3)](#ref-for-dfn-did-methods-47 "Reference 3") [(4)](#ref-for-dfn-did-methods-48 "Reference 4") [(5)](#ref-for-dfn-did-methods-49 "Reference 5") [(6)](#ref-for-dfn-did-methods-50 "Reference 6") [(7)](#ref-for-dfn-did-methods-51 "Reference 7") +- [§ 8.1 Method Syntax](#ref-for-dfn-did-methods-52 "§ 8.1 Method Syntax") [(2)](#ref-for-dfn-did-methods-53 "Reference 2") [(3)](#ref-for-dfn-did-methods-54 "Reference 3") [(4)](#ref-for-dfn-did-methods-55 "Reference 4") [(5)](#ref-for-dfn-did-methods-56 "Reference 5") [(6)](#ref-for-dfn-did-methods-57 "Reference 6") [(7)](#ref-for-dfn-did-methods-58 "Reference 7") [(8)](#ref-for-dfn-did-methods-59 "Reference 8") [(9)](#ref-for-dfn-did-methods-60 "Reference 9") [(10)](#ref-for-dfn-did-methods-61 "Reference 10") [(11)](#ref-for-dfn-did-methods-62 "Reference 11") [(12)](#ref-for-dfn-did-methods-63 "Reference 12") [(13)](#ref-for-dfn-did-methods-64 "Reference 13") +- [§ 8.2 Method Operations](#ref-for-dfn-did-methods-65 "§ 8.2 Method Operations") [(2)](#ref-for-dfn-did-methods-66 "Reference 2") [(3)](#ref-for-dfn-did-methods-67 "Reference 3") [(4)](#ref-for-dfn-did-methods-68 "Reference 4") [(5)](#ref-for-dfn-did-methods-69 "Reference 5") [(6)](#ref-for-dfn-did-methods-70 "Reference 6") [(7)](#ref-for-dfn-did-methods-71 "Reference 7") [(8)](#ref-for-dfn-did-methods-72 "Reference 8") +- [§ 8.3 Security Requirements](#ref-for-dfn-did-methods-73 "§ 8.3 Security Requirements") [(2)](#ref-for-dfn-did-methods-74 "Reference 2") [(3)](#ref-for-dfn-did-methods-75 "Reference 3") [(4)](#ref-for-dfn-did-methods-76 "Reference 4") [(5)](#ref-for-dfn-did-methods-77 "Reference 5") [(6)](#ref-for-dfn-did-methods-78 "Reference 6") [(7)](#ref-for-dfn-did-methods-79 "Reference 7") [(8)](#ref-for-dfn-did-methods-80 "Reference 8") [(9)](#ref-for-dfn-did-methods-81 "Reference 9") [(10)](#ref-for-dfn-did-methods-82 "Reference 10") +- [§ 8.4 Privacy Requirements](#ref-for-dfn-did-methods-83 "§ 8.4 Privacy Requirements") [(2)](#ref-for-dfn-did-methods-84 "Reference 2") +- [§ 9.1 Choosing DID Resolvers](#ref-for-dfn-did-methods-85 "§ 9.1 Choosing DID Resolvers") [(2)](#ref-for-dfn-did-methods-86 "Reference 2") [(3)](#ref-for-dfn-did-methods-87 "Reference 3") [(4)](#ref-for-dfn-did-methods-88 "Reference 4") [(5)](#ref-for-dfn-did-methods-89 "Reference 5") +- [§ Proving Control of a DID and/or DID Document](#ref-for-dfn-did-methods-90 "§ Proving Control of a DID and/or DID Document") [(2)](#ref-for-dfn-did-methods-91 "Reference 2") +- [§ 9.4 Non-Repudiation](#ref-for-dfn-did-methods-92 "§ 9.4 Non-Repudiation") +- [§ 9.7 Verification Method Rotation](#ref-for-dfn-did-methods-93 "§ 9.7 Verification Method Rotation") [(2)](#ref-for-dfn-did-methods-94 "Reference 2") [(3)](#ref-for-dfn-did-methods-95 "Reference 3") +- [§ 9.8 Verification Method Revocation](#ref-for-dfn-did-methods-96 "§ 9.8 Verification Method Revocation") [(2)](#ref-for-dfn-did-methods-97 "Reference 2") [(3)](#ref-for-dfn-did-methods-98 "Reference 3") +- [§ Revocation Semantics](#ref-for-dfn-did-methods-99 "§ Revocation Semantics") [(2)](#ref-for-dfn-did-methods-100 "Reference 2") +- [§ Revocation in Trustless Systems](#ref-for-dfn-did-methods-101 "§ Revocation in Trustless Systems") +- [§ 9.9 DID Recovery](#ref-for-dfn-did-methods-102 "§ 9.9 DID Recovery") [(2)](#ref-for-dfn-did-methods-103 "Reference 2") [(3)](#ref-for-dfn-did-methods-104 "Reference 3") [(4)](#ref-for-dfn-did-methods-105 "Reference 4") [(5)](#ref-for-dfn-did-methods-106 "Reference 5") +- [§ 9.11 DIDs as Enhanced URNs](#ref-for-dfn-did-methods-107 "§ 9.11 DIDs as Enhanced URNs") [(2)](#ref-for-dfn-did-methods-108 "Reference 2") +- [§ 9.12 Immutability](#ref-for-dfn-did-methods-109 "§ 9.12 Immutability") [(2)](#ref-for-dfn-did-methods-110 "Reference 2") [(3)](#ref-for-dfn-did-methods-111 "Reference 3") +- [§ 9.14 Equivalence Properties](#ref-for-dfn-did-methods-112 "§ 9.14 Equivalence Properties") [(2)](#ref-for-dfn-did-methods-113 "Reference 2") [(3)](#ref-for-dfn-did-methods-114 "Reference 3") [(4)](#ref-for-dfn-did-methods-115 "Reference 4") [(5)](#ref-for-dfn-did-methods-116 "Reference 5") +- [§ 9.16 Persistence](#ref-for-dfn-did-methods-117 "§ 9.16 Persistence") +- [§ 10.1 Keep Personal Data Private](#ref-for-dfn-did-methods-118 "§ 10.1 Keep Personal Data Private") +- [§ 10.5 Herd Privacy](#ref-for-dfn-did-methods-119 "§ 10.5 Herd Privacy") +- [§ Service Endpoint Alternatives](#ref-for-dfn-did-methods-120 "§ Service Endpoint Alternatives") +- [§ B.2 Creation of a DID](#ref-for-dfn-did-methods-121 "§ B.2 Creation of a DID") [(2)](#ref-for-dfn-did-methods-122 "Reference 2") [(3)](#ref-for-dfn-did-methods-123 "Reference 3") [(4)](#ref-for-dfn-did-methods-124 "Reference 4") [(5)](#ref-for-dfn-did-methods-125 "Reference 5") +- [§ B.3 Determining the DID subject](#ref-for-dfn-did-methods-126 "§ B.3 Determining the DID subject") [(2)](#ref-for-dfn-did-methods-127 "Reference 2") +- [§ B.4 Referring to the DID document](#ref-for-dfn-did-methods-128 "§ B.4 Referring to the DID document") +- [§ B.7 Serving a representation of the DID subject](#ref-for-dfn-did-methods-129 "§ B.7 Serving a representation of the DID subject") [(2)](#ref-for-dfn-did-methods-130 "Reference 2") + +[Permalink](#dfn-did-paths) + +**Referenced in:** + +- [§ 2. Terminology](#ref-for-dfn-did-paths-1 "§ 2. Terminology") +- [§ Path](#ref-for-dfn-did-paths-2 "§ Path") +- [§ 8.1 Method Syntax](#ref-for-dfn-did-paths-3 "§ 8.1 Method Syntax") + +[Permalink](#dfn-did-queries) + +**Referenced in:** + +- [§ 2. Terminology](#ref-for-dfn-did-queries-1 "§ 2. Terminology") +- [§ Query](#ref-for-dfn-did-queries-2 "§ Query") +- [§ 8.1 Method Syntax](#ref-for-dfn-did-queries-3 "§ 8.1 Method Syntax") + +[Permalink](#dfn-did-resolution) + +**Referenced in:** + +- [§ 1.3 Architecture Overview](#ref-for-dfn-did-resolution-1 "§ 1.3 Architecture Overview") [(2)](#ref-for-dfn-did-resolution-2 "Reference 2") +- [§ 2. Terminology](#ref-for-dfn-did-resolution-3 "§ 2. Terminology") [(2)](#ref-for-dfn-did-resolution-4 "Reference 2") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-did-resolution-5 "§ 3.2.1 DID Parameters") +- [§ 5.1.1 DID Subject](#ref-for-dfn-did-resolution-6 "§ 5.1.1 DID Subject") +- [§ 7. Resolution](#ref-for-dfn-did-resolution-7 "§ 7. Resolution") [(2)](#ref-for-dfn-did-resolution-8 "Reference 2") +- [§ 7.1 DID Resolution](#ref-for-dfn-did-resolution-9 "§ 7.1 DID Resolution") [(2)](#ref-for-dfn-did-resolution-10 "Reference 2") [(3)](#ref-for-dfn-did-resolution-11 "Reference 3") +- [§ 7.1.2 DID Resolution Metadata](#ref-for-dfn-did-resolution-12 "§ 7.1.2 DID Resolution Metadata") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-did-resolution-13 "§ 7.2 DID URL Dereferencing") [(2)](#ref-for-dfn-did-resolution-14 "Reference 2") +- [§ 7.3 Metadata Structure](#ref-for-dfn-did-resolution-15 "§ 7.3 Metadata Structure") +- [§ Proving Control of a DID and/or DID Document](#ref-for-dfn-did-resolution-16 "§ Proving Control of a DID and/or DID Document") +- [§ 9.4 Non-Repudiation](#ref-for-dfn-did-resolution-17 "§ 9.4 Non-Repudiation") +- [§ B.4 Referring to the DID document](#ref-for-dfn-did-resolution-18 "§ B.4 Referring to the DID document") [(2)](#ref-for-dfn-did-resolution-19 "Reference 2") + +[Permalink](#dfn-did-resolvers) + +**Referenced in:** + +- [§ 1.3 Architecture Overview](#ref-for-dfn-did-resolvers-1 "§ 1.3 Architecture Overview") +- [(2)](#ref-for-dfn-did-resolvers-3 "Reference 2") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-did-resolvers-4 "§ 3.2.1 DID Parameters") [(2)](#ref-for-dfn-did-resolvers-5 "Reference 2") +- [§ 5.1.1 DID Subject](#ref-for-dfn-did-resolvers-6 "§ 5.1.1 DID Subject") +- [§ 7. Resolution](#ref-for-dfn-did-resolvers-7 "§ 7. Resolution") +- [§ 7.1 DID Resolution](#ref-for-dfn-did-resolvers-8 "§ 7.1 DID Resolution") [(2)](#ref-for-dfn-did-resolvers-9 "Reference 2") [(3)](#ref-for-dfn-did-resolvers-10 "Reference 3") [(4)](#ref-for-dfn-did-resolvers-11 "Reference 4") +- [§ 7.1.1 DID Resolution Options](#ref-for-dfn-did-resolvers-12 "§ 7.1.1 DID Resolution Options") +- [§ 7.1.2 DID Resolution Metadata](#ref-for-dfn-did-resolvers-13 "§ 7.1.2 DID Resolution Metadata") [(2)](#ref-for-dfn-did-resolvers-14 "Reference 2") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-did-resolvers-15 "§ 7.2 DID URL Dereferencing") +- [§ 8.2 Method Operations](#ref-for-dfn-did-resolvers-16 "§ 8.2 Method Operations") [(2)](#ref-for-dfn-did-resolvers-17 "Reference 2") +- [§ 9.1 Choosing DID Resolvers](#ref-for-dfn-did-resolvers-18 "§ 9.1 Choosing DID Resolvers") [(2)](#ref-for-dfn-did-resolvers-19 "Reference 2") +- [§ 9.6 Key and Signature Expiration](#ref-for-dfn-did-resolvers-20 "§ 9.6 Key and Signature Expiration") +- [§ 9.12 Immutability](#ref-for-dfn-did-resolvers-21 "§ 9.12 Immutability") + +[Permalink](#dfn-did-schemes) + +**Referenced in:** + +- [§ 2. Terminology](#ref-for-dfn-did-schemes-1 "§ 2. Terminology") [(2)](#ref-for-dfn-did-schemes-2 "Reference 2") +- [§ 3.1 DID Syntax](#ref-for-dfn-did-schemes-3 "§ 3.1 DID Syntax") +- [§ 8. Methods](#ref-for-dfn-did-schemes-4 "§ 8. Methods") +- [§ 8.1 Method Syntax](#ref-for-dfn-did-schemes-5 "§ 8.1 Method Syntax") + +[Permalink](#dfn-did-subjects) + +**Referenced in:** + +- [§ Abstract](#ref-for-dfn-did-subjects-1 "§ Abstract") [(2)](#ref-for-dfn-did-subjects-2 "Reference 2") [(3)](#ref-for-dfn-did-subjects-3 "Reference 3") [(4)](#ref-for-dfn-did-subjects-4 "Reference 4") +- [§ 1.3 Architecture Overview](#ref-for-dfn-did-subjects-5 "§ 1.3 Architecture Overview") [(2)](#ref-for-dfn-did-subjects-6 "Reference 2") [(3)](#ref-for-dfn-did-subjects-7 "Reference 3") +- [§ 2. Terminology](#ref-for-dfn-did-subjects-8 "§ 2. Terminology") [(2)](#ref-for-dfn-did-subjects-9 "Reference 2") [(3)](#ref-for-dfn-did-subjects-10 "Reference 3") [(4)](#ref-for-dfn-did-subjects-11 "Reference 4") [(5)](#ref-for-dfn-did-subjects-12 "Reference 5") [(6)](#ref-for-dfn-did-subjects-13 "Reference 6") [(7)](#ref-for-dfn-did-subjects-14 "Reference 7") [(8)](#ref-for-dfn-did-subjects-15 "Reference 8") +- [§ 3.2 DID URL Syntax](#ref-for-dfn-did-subjects-16 "§ 3.2 DID URL Syntax") +- [§ 3.2.2 Relative DID URLs](#ref-for-dfn-did-subjects-17 "§ 3.2.2 Relative DID URLs") +- [§ 5. Core Properties](#ref-for-dfn-did-subjects-18 "§ 5. Core Properties") +- [§ 5.1 Identifiers](#ref-for-dfn-did-subjects-19 "§ 5.1 Identifiers") +- [§ 5.1.1 DID Subject](#ref-for-dfn-did-subjects-20 "§ 5.1.1 DID Subject") [(2)](#ref-for-dfn-did-subjects-21 "Reference 2") +- [§ 5.1.2 DID Controller](#ref-for-dfn-did-subjects-22 "§ 5.1.2 DID Controller") [(2)](#ref-for-dfn-did-subjects-23 "Reference 2") +- [§ 5.1.3 Also Known As](#ref-for-dfn-did-subjects-24 "§ 5.1.3 Also Known As") [(2)](#ref-for-dfn-did-subjects-25 "Reference 2") [(3)](#ref-for-dfn-did-subjects-26 "Reference 3") +- [§ 5.2 Verification Methods](#ref-for-dfn-did-subjects-27 "§ 5.2 Verification Methods") +- [§ 5.3 Verification Relationships](#ref-for-dfn-did-subjects-28 "§ 5.3 Verification Relationships") [(2)](#ref-for-dfn-did-subjects-29 "Reference 2") [(3)](#ref-for-dfn-did-subjects-30 "Reference 3") +- [§ 5.3.1 Authentication](#ref-for-dfn-did-subjects-31 "§ 5.3.1 Authentication") [(2)](#ref-for-dfn-did-subjects-32 "Reference 2") +- [§ 5.3.2 Assertion](#ref-for-dfn-did-subjects-33 "§ 5.3.2 Assertion") [(2)](#ref-for-dfn-did-subjects-34 "Reference 2") +- [§ 5.3.3 Key Agreement](#ref-for-dfn-did-subjects-35 "§ 5.3.3 Key Agreement") [(2)](#ref-for-dfn-did-subjects-36 "Reference 2") +- [§ 5.3.4 Capability Invocation](#ref-for-dfn-did-subjects-37 "§ 5.3.4 Capability Invocation") [(2)](#ref-for-dfn-did-subjects-38 "Reference 2") [(3)](#ref-for-dfn-did-subjects-39 "Reference 3") +- [§ 5.3.5 Capability Delegation](#ref-for-dfn-did-subjects-40 "§ 5.3.5 Capability Delegation") [(2)](#ref-for-dfn-did-subjects-41 "Reference 2") [(3)](#ref-for-dfn-did-subjects-42 "Reference 3") +- [§ 5.4 Services](#ref-for-dfn-did-subjects-43 "§ 5.4 Services") [(2)](#ref-for-dfn-did-subjects-44 "Reference 2") +- [§ 7.1.3 DID Document Metadata](#ref-for-dfn-did-subjects-45 "§ 7.1.3 DID Document Metadata") [(2)](#ref-for-dfn-did-subjects-46 "Reference 2") [(3)](#ref-for-dfn-did-subjects-47 "Reference 3") [(4)](#ref-for-dfn-did-subjects-48 "Reference 4") [(5)](#ref-for-dfn-did-subjects-49 "Reference 5") +- [§ 9.3 Authentication Service Endpoints](#ref-for-dfn-did-subjects-50 "§ 9.3 Authentication Service Endpoints") +- [§ 9.5 Notification of DID Document Changes](#ref-for-dfn-did-subjects-51 "§ 9.5 Notification of DID Document Changes") +- [§ 9.11 DIDs as Enhanced URNs](#ref-for-dfn-did-subjects-52 "§ 9.11 DIDs as Enhanced URNs") +- [§ 10.1 Keep Personal Data Private](#ref-for-dfn-did-subjects-53 "§ 10.1 Keep Personal Data Private") [(2)](#ref-for-dfn-did-subjects-54 "Reference 2") [(3)](#ref-for-dfn-did-subjects-55 "Reference 3") +- [§ 10.2 DID Correlation Risks](#ref-for-dfn-did-subjects-56 "§ 10.2 DID Correlation Risks") +- [§ 10.4 DID Subject Classification](#ref-for-dfn-did-subjects-57 "§ 10.4 DID Subject Classification") [(2)](#ref-for-dfn-did-subjects-58 "Reference 2") [(3)](#ref-for-dfn-did-subjects-59 "Reference 3") +- [§ 10.5 Herd Privacy](#ref-for-dfn-did-subjects-60 "§ 10.5 Herd Privacy") +- [§ 10.6 Service Privacy](#ref-for-dfn-did-subjects-61 "§ 10.6 Service Privacy") +- [§ Maintaining Herd Privacy](#ref-for-dfn-did-subjects-62 "§ Maintaining Herd Privacy") [(2)](#ref-for-dfn-did-subjects-63 "Reference 2") [(3)](#ref-for-dfn-did-subjects-64 "Reference 3") [(4)](#ref-for-dfn-did-subjects-65 "Reference 4") [(5)](#ref-for-dfn-did-subjects-66 "Reference 5") +- [§ B.3 Determining the DID subject](#ref-for-dfn-did-subjects-67 "§ B.3 Determining the DID subject") [(2)](#ref-for-dfn-did-subjects-68 "Reference 2") [(3)](#ref-for-dfn-did-subjects-69 "Reference 3") [(4)](#ref-for-dfn-did-subjects-70 "Reference 4") [(5)](#ref-for-dfn-did-subjects-71 "Reference 5") [(6)](#ref-for-dfn-did-subjects-72 "Reference 6") +- [§ B.4 Referring to the DID document](#ref-for-dfn-did-subjects-73 "§ B.4 Referring to the DID document") [(2)](#ref-for-dfn-did-subjects-74 "Reference 2") [(3)](#ref-for-dfn-did-subjects-75 "Reference 3") [(4)](#ref-for-dfn-did-subjects-76 "Reference 4") [(5)](#ref-for-dfn-did-subjects-77 "Reference 5") [(6)](#ref-for-dfn-did-subjects-78 "Reference 6") +- [§ B.5 Statements in the DID document](#ref-for-dfn-did-subjects-79 "§ B.5 Statements in the DID document") [(2)](#ref-for-dfn-did-subjects-80 "Reference 2") [(3)](#ref-for-dfn-did-subjects-81 "Reference 3") +- [§ B.6 Discovering more information about the DID subject](#ref-for-dfn-did-subjects-82 "§ B.6 Discovering more information about the DID subject") [(2)](#ref-for-dfn-did-subjects-83 "Reference 2") [(3)](#ref-for-dfn-did-subjects-84 "Reference 3") [(4)](#ref-for-dfn-did-subjects-85 "Reference 4") [(5)](#ref-for-dfn-did-subjects-86 "Reference 5") +- [§ B.7 Serving a representation of the DID subject](#ref-for-dfn-did-subjects-87 "§ B.7 Serving a representation of the DID subject") [(2)](#ref-for-dfn-did-subjects-88 "Reference 2") +- [§ B.9 The relationship between DID controllers and DID subjects](#ref-for-dfn-did-subjects-89 "§ B.9 The relationship between DID controllers and DID subjects") +- [§ B.9.1 Set #1: The DID subject is the DID controller](#ref-for-dfn-did-subjects-90 "§ B.9.1 Set #1: The DID subject is the DID controller") [(2)](#ref-for-dfn-did-subjects-91 "Reference 2") [(3)](#ref-for-dfn-did-subjects-92 "Reference 3") +- [§ B.9.2 Set #2: The DID subject is not the DID controller](#ref-for-dfn-did-subjects-93 "§ B.9.2 Set #2: The DID subject is not the DID controller") [(2)](#ref-for-dfn-did-subjects-94 "Reference 2") +- [§ B.10.2 Group Control](#ref-for-dfn-did-subjects-95 "§ B.10.2 Group Control") +- [§ B.11 Changing the DID subject](#ref-for-dfn-did-subjects-96 "§ B.11 Changing the DID subject") [(2)](#ref-for-dfn-did-subjects-97 "Reference 2") + +[Permalink](#dfn-did-urls) + +**Referenced in:** + +- [§ 1.3 Architecture Overview](#ref-for-dfn-did-urls-1 "§ 1.3 Architecture Overview") [(2)](#ref-for-dfn-did-urls-2 "Reference 2") +- [§ 2. Terminology](#ref-for-dfn-did-urls-3 "§ 2. Terminology") [(2)](#ref-for-dfn-did-urls-4 "Reference 2") [(3)](#ref-for-dfn-did-urls-5 "Reference 3") [(4)](#ref-for-dfn-did-urls-6 "Reference 4") [(5)](#ref-for-dfn-did-urls-7 "Reference 5") [(6)](#ref-for-dfn-did-urls-8 "Reference 6") [(7)](#ref-for-dfn-did-urls-9 "Reference 7") [(8)](#ref-for-dfn-did-urls-10 "Reference 8") +- [§ 3. Identifier](#ref-for-dfn-did-urls-11 "§ 3. Identifier") [(2)](#ref-for-dfn-did-urls-12 "Reference 2") +- [§ 3.2 DID URL Syntax](#ref-for-dfn-did-urls-13 "§ 3.2 DID URL Syntax") [(2)](#ref-for-dfn-did-urls-14 "Reference 2") [(3)](#ref-for-dfn-did-urls-15 "Reference 3") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-did-urls-16 "§ 3.2.1 DID Parameters") [(2)](#ref-for-dfn-did-urls-17 "Reference 2") [(3)](#ref-for-dfn-did-urls-18 "Reference 3") [(4)](#ref-for-dfn-did-urls-19 "Reference 4") [(5)](#ref-for-dfn-did-urls-20 "Reference 5") +- [§ 3.2.2 Relative DID URLs](#ref-for-dfn-did-urls-21 "§ 3.2.2 Relative DID URLs") [(2)](#ref-for-dfn-did-urls-22 "Reference 2") [(3)](#ref-for-dfn-did-urls-23 "Reference 3") [(4)](#ref-for-dfn-did-urls-24 "Reference 4") [(5)](#ref-for-dfn-did-urls-25 "Reference 5") [(6)](#ref-for-dfn-did-urls-26 "Reference 6") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-did-urls-27 "§ 7.2 DID URL Dereferencing") [(2)](#ref-for-dfn-did-urls-28 "Reference 2") [(3)](#ref-for-dfn-did-urls-29 "Reference 3") [(4)](#ref-for-dfn-did-urls-30 "Reference 4") [(5)](#ref-for-dfn-did-urls-31 "Reference 5") [(6)](#ref-for-dfn-did-urls-32 "Reference 6") [(7)](#ref-for-dfn-did-urls-33 "Reference 7") [(8)](#ref-for-dfn-did-urls-34 "Reference 8") +- [§ 7.2.2 DID URL Dereferencing Metadata](#ref-for-dfn-did-urls-35 "§ 7.2.2 DID URL Dereferencing Metadata") +- [§ 9.11 DIDs as Enhanced URNs](#ref-for-dfn-did-urls-36 "§ 9.11 DIDs as Enhanced URNs") +- [§ B.7 Serving a representation of the DID subject](#ref-for-dfn-did-urls-37 "§ B.7 Serving a representation of the DID subject") + +[Permalink](#dfn-did-url-dereferencing) + +**Referenced in:** + +- [§ 1.3 Architecture Overview](#ref-for-dfn-did-url-dereferencing-1 "§ 1.3 Architecture Overview") [(2)](#ref-for-dfn-did-url-dereferencing-2 "Reference 2") +- [§ 2. Terminology](#ref-for-dfn-did-url-dereferencing-3 "§ 2. Terminology") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-did-url-dereferencing-4 "§ 3.2.1 DID Parameters") +- [§ 7. Resolution](#ref-for-dfn-did-url-dereferencing-5 "§ 7. Resolution") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-did-url-dereferencing-6 "§ 7.2 DID URL Dereferencing") [(2)](#ref-for-dfn-did-url-dereferencing-7 "Reference 2") [(3)](#ref-for-dfn-did-url-dereferencing-8 "Reference 3") [(4)](#ref-for-dfn-did-url-dereferencing-9 "Reference 4") [(5)](#ref-for-dfn-did-url-dereferencing-10 "Reference 5") [(6)](#ref-for-dfn-did-url-dereferencing-11 "Reference 6") [(7)](#ref-for-dfn-did-url-dereferencing-12 "Reference 7") +- [§ 7.2.1 DID URL Dereferencing Options](#ref-for-dfn-did-url-dereferencing-13 "§ 7.2.1 DID URL Dereferencing Options") +- [§ 7.2.2 DID URL Dereferencing Metadata](#ref-for-dfn-did-url-dereferencing-14 "§ 7.2.2 DID URL Dereferencing Metadata") +- [§ 7.3 Metadata Structure](#ref-for-dfn-did-url-dereferencing-15 "§ 7.3 Metadata Structure") + +[Permalink](#dfn-did-url-dereferencers) + +**Referenced in:** + +- [§ 1.3 Architecture Overview](#ref-for-dfn-did-url-dereferencers-1 "§ 1.3 Architecture Overview") +- +- [§ 7.2.2 DID URL Dereferencing Metadata](#ref-for-dfn-did-url-dereferencers-3 "§ 7.2.2 DID URL Dereferencing Metadata") + +[Permalink](#dfn-distributed-ledger-technology) + +**Referenced in:** + +- [§ 1.3 Architecture Overview](#ref-for-dfn-distributed-ledger-technology-1 "§ 1.3 Architecture Overview") +- [§ 2. Terminology](#ref-for-dfn-distributed-ledger-technology-2 "§ 2. Terminology") +- [§ 8.3 Security Requirements](#ref-for-dfn-distributed-ledger-technology-3 "§ 8.3 Security Requirements") [(2)](#ref-for-dfn-distributed-ledger-technology-4 "Reference 2") +- [§ 10.1 Keep Personal Data Private](#ref-for-dfn-distributed-ledger-technology-5 "§ 10.1 Keep Personal Data Private") + +[Permalink](#dfn-public-key-description) + +**Referenced in:** + +- + +[Permalink](#dfn-resources) + +**Referenced in:** + +- [§ 1.3 Architecture Overview](#ref-for-dfn-resources-1 "§ 1.3 Architecture Overview") [(2)](#ref-for-dfn-resources-2 "Reference 2") [(3)](#ref-for-dfn-resources-3 "Reference 3") +- [§ 2. Terminology](#ref-for-dfn-resources-4 "§ 2. Terminology") +- [§ 3.2 DID URL Syntax](#ref-for-dfn-resources-5 "§ 3.2 DID URL Syntax") +- [§ Fragment](#ref-for-dfn-resources-6 "§ Fragment") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-resources-7 "§ 3.2.1 DID Parameters") [(2)](#ref-for-dfn-resources-8 "Reference 2") [(3)](#ref-for-dfn-resources-9 "Reference 3") [(4)](#ref-for-dfn-resources-10 "Reference 4") [(5)](#ref-for-dfn-resources-11 "Reference 5") +- [§ 3.2.2 Relative DID URLs](#ref-for-dfn-resources-12 "§ 3.2.2 Relative DID URLs") +- [§ 5.2.2 Referring to Verification Methods](#ref-for-dfn-resources-13 "§ 5.2.2 Referring to Verification Methods") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-resources-14 "§ 7.2 DID URL Dereferencing") [(2)](#ref-for-dfn-resources-15 "Reference 2") [(3)](#ref-for-dfn-resources-16 "Reference 3") + +[Permalink](#dfn-representations) + +**Referenced in:** + +- [§ 2. Terminology](#ref-for-dfn-representations-1 "§ 2. Terminology") [(2)](#ref-for-dfn-representations-2 "Reference 2") [(3)](#ref-for-dfn-representations-3 "Reference 3") +- [§ Fragment](#ref-for-dfn-representations-4 "§ Fragment") [(2)](#ref-for-dfn-representations-5 "Reference 2") +- [§ 4. Data Model](#ref-for-dfn-representations-6 "§ 4. Data Model") [(2)](#ref-for-dfn-representations-7 "Reference 2") +- [§ 4.1 Extensibility](#ref-for-dfn-representations-8 "§ 4.1 Extensibility") [(2)](#ref-for-dfn-representations-9 "Reference 2") [(3)](#ref-for-dfn-representations-10 "Reference 3") [(4)](#ref-for-dfn-representations-11 "Reference 4") [(5)](#ref-for-dfn-representations-12 "Reference 5") [(6)](#ref-for-dfn-representations-13 "Reference 6") +- [§ 6. Representations](#ref-for-dfn-representations-14 "§ 6. Representations") [(2)](#ref-for-dfn-representations-15 "Reference 2") [(3)](#ref-for-dfn-representations-16 "Reference 3") [(4)](#ref-for-dfn-representations-17 "Reference 4") [(5)](#ref-for-dfn-representations-18 "Reference 5") [(6)](#ref-for-dfn-representations-19 "Reference 6") [(7)](#ref-for-dfn-representations-20 "Reference 7") +- [§ 6.1 Production and Consumption](#ref-for-dfn-representations-21 "§ 6.1 Production and Consumption") [(2)](#ref-for-dfn-representations-22 "Reference 2") [(3)](#ref-for-dfn-representations-23 "Reference 3") [(4)](#ref-for-dfn-representations-24 "Reference 4") [(5)](#ref-for-dfn-representations-25 "Reference 5") [(6)](#ref-for-dfn-representations-26 "Reference 6") [(7)](#ref-for-dfn-representations-27 "Reference 7") [(8)](#ref-for-dfn-representations-28 "Reference 8") [(9)](#ref-for-dfn-representations-29 "Reference 9") [(10)](#ref-for-dfn-representations-30 "Reference 10") [(11)](#ref-for-dfn-representations-31 "Reference 11") [(12)](#ref-for-dfn-representations-32 "Reference 12") [(13)](#ref-for-dfn-representations-33 "Reference 13") [(14)](#ref-for-dfn-representations-34 "Reference 14") [(15)](#ref-for-dfn-representations-35 "Reference 15") [(16)](#ref-for-dfn-representations-36 "Reference 16") [(17)](#ref-for-dfn-representations-37 "Reference 17") [(18)](#ref-for-dfn-representations-38 "Reference 18") [(19)](#ref-for-dfn-representations-39 "Reference 19") [(20)](#ref-for-dfn-representations-40 "Reference 20") [(21)](#ref-for-dfn-representations-41 "Reference 21") [(22)](#ref-for-dfn-representations-42 "Reference 22") +- [§ 6.2 JSON](#ref-for-dfn-representations-43 "§ 6.2 JSON") +- [§ 6.2.1 Production](#ref-for-dfn-representations-44 "§ 6.2.1 Production") [(2)](#ref-for-dfn-representations-45 "Reference 2") +- [§ 6.2.2 Consumption](#ref-for-dfn-representations-46 "§ 6.2.2 Consumption") [(2)](#ref-for-dfn-representations-47 "Reference 2") [(3)](#ref-for-dfn-representations-48 "Reference 3") +- [§ 6.3 JSON-LD](#ref-for-dfn-representations-49 "§ 6.3 JSON-LD") [(2)](#ref-for-dfn-representations-50 "Reference 2") +- [§ 6.3.1 Production](#ref-for-dfn-representations-51 "§ 6.3.1 Production") [(2)](#ref-for-dfn-representations-52 "Reference 2") [(3)](#ref-for-dfn-representations-53 "Reference 3") [(4)](#ref-for-dfn-representations-54 "Reference 4") [(5)](#ref-for-dfn-representations-55 "Reference 5") [(6)](#ref-for-dfn-representations-56 "Reference 6") [(7)](#ref-for-dfn-representations-57 "Reference 7") [(8)](#ref-for-dfn-representations-58 "Reference 8") +- [§ 6.3.2 Consumption](#ref-for-dfn-representations-59 "§ 6.3.2 Consumption") [(2)](#ref-for-dfn-representations-60 "Reference 2") [(3)](#ref-for-dfn-representations-61 "Reference 3") [(4)](#ref-for-dfn-representations-62 "Reference 4") +- [§ 7. Resolution](#ref-for-dfn-representations-63 "§ 7. Resolution") +- [§ 7.1.1 DID Resolution Options](#ref-for-dfn-representations-64 "§ 7.1.1 DID Resolution Options") [(2)](#ref-for-dfn-representations-65 "Reference 2") [(3)](#ref-for-dfn-representations-66 "Reference 3") +- [§ 7.1.2 DID Resolution Metadata](#ref-for-dfn-representations-67 "§ 7.1.2 DID Resolution Metadata") [(2)](#ref-for-dfn-representations-68 "Reference 2") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-representations-69 "§ 7.2 DID URL Dereferencing") +- [§ 7.2.1 DID URL Dereferencing Options](#ref-for-dfn-representations-70 "§ 7.2.1 DID URL Dereferencing Options") [(2)](#ref-for-dfn-representations-71 "Reference 2") +- [§ 7.3 Metadata Structure](#ref-for-dfn-representations-72 "§ 7.3 Metadata Structure") +- [§ B.2 Creation of a DID](#ref-for-dfn-representations-73 "§ B.2 Creation of a DID") + +[Permalink](#dfn-representation-specific-entry) + +**Referenced in:** + +- [§ 4. Data Model](#ref-for-dfn-representation-specific-entry-1 "§ 4. Data Model") +- [§ 6.1 Production and Consumption](#ref-for-dfn-representation-specific-entry-2 "§ 6.1 Production and Consumption") [(2)](#ref-for-dfn-representation-specific-entry-3 "Reference 2") [(3)](#ref-for-dfn-representation-specific-entry-4 "Reference 3") [(4)](#ref-for-dfn-representation-specific-entry-5 "Reference 4") [(5)](#ref-for-dfn-representation-specific-entry-6 "Reference 5") [(6)](#ref-for-dfn-representation-specific-entry-7 "Reference 6") [(7)](#ref-for-dfn-representation-specific-entry-8 "Reference 7") [(8)](#ref-for-dfn-representation-specific-entry-9 "Reference 8") +- [§ 6.2.1 Production](#ref-for-dfn-representation-specific-entry-10 "§ 6.2.1 Production") +- [§ 6.3 JSON-LD](#ref-for-dfn-representation-specific-entry-11 "§ 6.3 JSON-LD") +- [§ 6.3.1 Production](#ref-for-dfn-representation-specific-entry-12 "§ 6.3.1 Production") [(2)](#ref-for-dfn-representation-specific-entry-13 "Reference 2") + +[Permalink](#dfn-service) + +**Referenced in:** + +- [§ Abstract](#ref-for-dfn-service-1 "§ Abstract") [(2)](#ref-for-dfn-service-2 "Reference 2") +- [§ 1.2 Design Goals](#ref-for-dfn-service-3 "§ 1.2 Design Goals") +- [§ 1.3 Architecture Overview](#ref-for-dfn-service-4 "§ 1.3 Architecture Overview") +- [§ 2. Terminology](#ref-for-dfn-service-5 "§ 2. Terminology") +- [§ 3.2 DID URL Syntax](#ref-for-dfn-service-6 "§ 3.2 DID URL Syntax") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-service-7 "§ 3.2.1 DID Parameters") +- [§ 3.2.2 Relative DID URLs](#ref-for-dfn-service-8 "§ 3.2.2 Relative DID URLs") +- [§ DID Document properties](#ref-for-dfn-service-9 "§ DID Document properties") +- [§ 5.4 Services](#ref-for-dfn-service-10 "§ 5.4 Services") [(2)](#ref-for-dfn-service-11 "Reference 2") [(3)](#ref-for-dfn-service-12 "Reference 3") [(4)](#ref-for-dfn-service-13 "Reference 4") [(5)](#ref-for-dfn-service-14 "Reference 5") [(6)](#ref-for-dfn-service-15 "Reference 6") [(7)](#ref-for-dfn-service-16 "Reference 7") [(8)](#ref-for-dfn-service-17 "Reference 8") [(9)](#ref-for-dfn-service-18 "Reference 9") [(10)](#ref-for-dfn-service-19 "Reference 10") +- [§ 8.3 Security Requirements](#ref-for-dfn-service-20 "§ 8.3 Security Requirements") +- [§ 9.3 Authentication Service Endpoints](#ref-for-dfn-service-21 "§ 9.3 Authentication Service Endpoints") +- [§ 9.12 Immutability](#ref-for-dfn-service-22 "§ 9.12 Immutability") +- [§ 10.6 Service Privacy](#ref-for-dfn-service-23 "§ 10.6 Service Privacy") [(2)](#ref-for-dfn-service-24 "Reference 2") +- [§ B.5 Statements in the DID document](#ref-for-dfn-service-25 "§ B.5 Statements in the DID document") +- [§ B.6 Discovering more information about the DID subject](#ref-for-dfn-service-26 "§ B.6 Discovering more information about the DID subject") + +[Permalink](#dfn-service-endpoints) + +**Referenced in:** + +- [§ 2. Terminology](#ref-for-dfn-service-endpoints-1 "§ 2. Terminology") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-service-endpoints-2 "§ 3.2.1 DID Parameters") +- [§ DID Document properties](#ref-for-dfn-service-endpoints-3 "§ DID Document properties") +- [§ 9.3 Authentication Service Endpoints](#ref-for-dfn-service-endpoints-4 "§ 9.3 Authentication Service Endpoints") [(2)](#ref-for-dfn-service-endpoints-5 "Reference 2") +- [§ 9.5 Notification of DID Document Changes](#ref-for-dfn-service-endpoints-6 "§ 9.5 Notification of DID Document Changes") +- [§ 10.1 Keep Personal Data Private](#ref-for-dfn-service-endpoints-7 "§ 10.1 Keep Personal Data Private") [(2)](#ref-for-dfn-service-endpoints-8 "Reference 2") [(3)](#ref-for-dfn-service-endpoints-9 "Reference 3") +- [§ 10.3 DID Document Correlation Risks](#ref-for-dfn-service-endpoints-10 "§ 10.3 DID Document Correlation Risks") [(2)](#ref-for-dfn-service-endpoints-11 "Reference 2") +- [§ 10.6 Service Privacy](#ref-for-dfn-service-endpoints-12 "§ 10.6 Service Privacy") [(2)](#ref-for-dfn-service-endpoints-13 "Reference 2") [(3)](#ref-for-dfn-service-endpoints-14 "Reference 3") +- [§ B.6 Discovering more information about the DID subject](#ref-for-dfn-service-endpoints-15 "§ B.6 Discovering more information about the DID subject") [(2)](#ref-for-dfn-service-endpoints-16 "Reference 2") + +[Permalink](#dfn-uri) + +**Referenced in:** + +- [§ Abstract](#ref-for-dfn-uri-1 "§ Abstract") +- [§ 1.3 Architecture Overview](#ref-for-dfn-uri-2 "§ 1.3 Architecture Overview") [(2)](#ref-for-dfn-uri-3 "Reference 2") +- [§ 1.4 Conformance](#ref-for-dfn-uri-4 "§ 1.4 Conformance") +- [§ 3.1 DID Syntax](#ref-for-dfn-uri-5 "§ 3.1 DID Syntax") +- [§ Path](#ref-for-dfn-uri-6 "§ Path") [(2)](#ref-for-dfn-uri-7 "Reference 2") +- [§ Query](#ref-for-dfn-uri-8 "§ Query") +- [§ Fragment](#ref-for-dfn-uri-9 "§ Fragment") +- [§ 3.2.1 DID Parameters](#ref-for-dfn-uri-10 "§ 3.2.1 DID Parameters") +- [§ DID Document properties](#ref-for-dfn-uri-11 "§ DID Document properties") +- [§ Service properties](#ref-for-dfn-uri-12 "§ Service properties") [(2)](#ref-for-dfn-uri-13 "Reference 2") [(3)](#ref-for-dfn-uri-14 "Reference 3") +- [§ 5.1.3 Also Known As](#ref-for-dfn-uri-15 "§ 5.1.3 Also Known As") [(2)](#ref-for-dfn-uri-16 "Reference 2") +- [§ 5.4 Services](#ref-for-dfn-uri-17 "§ 5.4 Services") [(2)](#ref-for-dfn-uri-18 "Reference 2") [(3)](#ref-for-dfn-uri-19 "Reference 3") +- [§ 8. Methods](#ref-for-dfn-uri-20 "§ 8. Methods") [(2)](#ref-for-dfn-uri-21 "Reference 2") +- [§ 9.14 Equivalence Properties](#ref-for-dfn-uri-22 "§ 9.14 Equivalence Properties") +- [§ Maintaining Herd Privacy](#ref-for-dfn-uri-23 "§ Maintaining Herd Privacy") [(2)](#ref-for-dfn-uri-24 "Reference 2") +- [§ B.4 Referring to the DID document](#ref-for-dfn-uri-25 "§ B.4 Referring to the DID document") +- [§ B.6 Discovering more information about the DID subject](#ref-for-dfn-uri-26 "§ B.6 Discovering more information about the DID subject") + +[Permalink](#dfn-verifiable-credentials) + +**Referenced in:** + +- [§ 2. Terminology](#ref-for-dfn-verifiable-credentials-1 "§ 2. Terminology") +- [§ 5.3.2 Assertion](#ref-for-dfn-verifiable-credentials-2 "§ 5.3.2 Assertion") [(2)](#ref-for-dfn-verifiable-credentials-3 "Reference 2") +- [§ Binding to Physical Identity](#ref-for-dfn-verifiable-credentials-4 "§ Binding to Physical Identity") + +[Permalink](#dfn-verifiable-data-registry) + +**Referenced in:** + +- [§ 1.3 Architecture Overview](#ref-for-dfn-verifiable-data-registry-1 "§ 1.3 Architecture Overview") +- [§ 7.1.3 DID Document Metadata](#ref-for-dfn-verifiable-data-registry-2 "§ 7.1.3 DID Document Metadata") +- [§ 8. Methods](#ref-for-dfn-verifiable-data-registry-3 "§ 8. Methods") [(2)](#ref-for-dfn-verifiable-data-registry-4 "Reference 2") +- [§ 8.1 Method Syntax](#ref-for-dfn-verifiable-data-registry-5 "§ 8.1 Method Syntax") +- [§ Proving Control of a DID and/or DID Document](#ref-for-dfn-verifiable-data-registry-6 "§ Proving Control of a DID and/or DID Document") +- [§ 9.4 Non-Repudiation](#ref-for-dfn-verifiable-data-registry-7 "§ 9.4 Non-Repudiation") +- [§ 9.5 Notification of DID Document Changes](#ref-for-dfn-verifiable-data-registry-8 "§ 9.5 Notification of DID Document Changes") [(2)](#ref-for-dfn-verifiable-data-registry-9 "Reference 2") +- [§ 9.7 Verification Method Rotation](#ref-for-dfn-verifiable-data-registry-10 "§ 9.7 Verification Method Rotation") +- [§ 10.1 Keep Personal Data Private](#ref-for-dfn-verifiable-data-registry-11 "§ 10.1 Keep Personal Data Private") +- [§ 10.6 Service Privacy](#ref-for-dfn-verifiable-data-registry-12 "§ 10.6 Service Privacy") +- [§ Service Endpoint Alternatives](#ref-for-dfn-verifiable-data-registry-13 "§ Service Endpoint Alternatives") +- [§ B.2 Creation of a DID](#ref-for-dfn-verifiable-data-registry-14 "§ B.2 Creation of a DID") +- [§ B.7 Serving a representation of the DID subject](#ref-for-dfn-verifiable-data-registry-15 "§ B.7 Serving a representation of the DID subject") + +[Permalink](#dfn-verifiable-timestamp) + +**Referenced in:** + +- [§ Proving Control of a DID and/or DID Document](#ref-for-dfn-verifiable-timestamp-1 "§ Proving Control of a DID and/or DID Document") +- [§ 9.4 Non-Repudiation](#ref-for-dfn-verifiable-timestamp-2 "§ 9.4 Non-Repudiation") + +[Permalink](#dfn-verification-method) + +**Referenced in:** + +- [§ Abstract](#ref-for-dfn-verification-method-1 "§ Abstract") +- [§ 1.3 Architecture Overview](#ref-for-dfn-verification-method-2 "§ 1.3 Architecture Overview") +- [§ 2. Terminology](#ref-for-dfn-verification-method-3 "§ 2. Terminology") [(2)](#ref-for-dfn-verification-method-4 "Reference 2") [(3)](#ref-for-dfn-verification-method-5 "Reference 3") [(4)](#ref-for-dfn-verification-method-6 "Reference 4") +- [§ 3.2 DID URL Syntax](#ref-for-dfn-verification-method-7 "§ 3.2 DID URL Syntax") +- [§ 3.2.2 Relative DID URLs](#ref-for-dfn-verification-method-8 "§ 3.2.2 Relative DID URLs") +- [§ DID Document properties](#ref-for-dfn-verification-method-9 "§ DID Document properties") [(2)](#ref-for-dfn-verification-method-10 "Reference 2") +- [§ 5.1.2 DID Controller](#ref-for-dfn-verification-method-11 "§ 5.1.2 DID Controller") [(2)](#ref-for-dfn-verification-method-12 "Reference 2") [(3)](#ref-for-dfn-verification-method-13 "Reference 3") +- [§ 5.2 Verification Methods](#ref-for-dfn-verification-method-14 "§ 5.2 Verification Methods") [(2)](#ref-for-dfn-verification-method-15 "Reference 2") [(3)](#ref-for-dfn-verification-method-16 "Reference 3") [(4)](#ref-for-dfn-verification-method-17 "Reference 4") [(5)](#ref-for-dfn-verification-method-18 "Reference 5") [(6)](#ref-for-dfn-verification-method-19 "Reference 6") [(7)](#ref-for-dfn-verification-method-20 "Reference 7") [(8)](#ref-for-dfn-verification-method-21 "Reference 8") [(9)](#ref-for-dfn-verification-method-22 "Reference 9") [(10)](#ref-for-dfn-verification-method-23 "Reference 10") [(11)](#ref-for-dfn-verification-method-24 "Reference 11") [(12)](#ref-for-dfn-verification-method-25 "Reference 12") [(13)](#ref-for-dfn-verification-method-26 "Reference 13") +- [§ 5.2.1 Verification Material](#ref-for-dfn-verification-method-27 "§ 5.2.1 Verification Material") [(2)](#ref-for-dfn-verification-method-28 "Reference 2") [(3)](#ref-for-dfn-verification-method-29 "Reference 3") [(4)](#ref-for-dfn-verification-method-30 "Reference 4") [(5)](#ref-for-dfn-verification-method-31 "Reference 5") [(6)](#ref-for-dfn-verification-method-32 "Reference 6") [(7)](#ref-for-dfn-verification-method-33 "Reference 7") +- [§ 5.2.2 Referring to Verification Methods](#ref-for-dfn-verification-method-34 "§ 5.2.2 Referring to Verification Methods") [(2)](#ref-for-dfn-verification-method-35 "Reference 2") [(3)](#ref-for-dfn-verification-method-36 "Reference 3") [(4)](#ref-for-dfn-verification-method-37 "Reference 4") [(5)](#ref-for-dfn-verification-method-38 "Reference 5") [(6)](#ref-for-dfn-verification-method-39 "Reference 6") +- [§ 5.3 Verification Relationships](#ref-for-dfn-verification-method-40 "§ 5.3 Verification Relationships") [(2)](#ref-for-dfn-verification-method-41 "Reference 2") [(3)](#ref-for-dfn-verification-method-42 "Reference 3") [(4)](#ref-for-dfn-verification-method-43 "Reference 4") [(5)](#ref-for-dfn-verification-method-44 "Reference 5") [(6)](#ref-for-dfn-verification-method-45 "Reference 6") +- [§ 5.3.1 Authentication](#ref-for-dfn-verification-method-46 "§ 5.3.1 Authentication") [(2)](#ref-for-dfn-verification-method-47 "Reference 2") [(3)](#ref-for-dfn-verification-method-48 "Reference 3") [(4)](#ref-for-dfn-verification-method-49 "Reference 4") [(5)](#ref-for-dfn-verification-method-50 "Reference 5") +- [§ 5.3.2 Assertion](#ref-for-dfn-verification-method-51 "§ 5.3.2 Assertion") [(2)](#ref-for-dfn-verification-method-52 "Reference 2") [(3)](#ref-for-dfn-verification-method-53 "Reference 3") +- [§ 5.3.3 Key Agreement](#ref-for-dfn-verification-method-54 "§ 5.3.3 Key Agreement") [(2)](#ref-for-dfn-verification-method-55 "Reference 2") [(3)](#ref-for-dfn-verification-method-56 "Reference 3") +- [§ 5.3.4 Capability Invocation](#ref-for-dfn-verification-method-57 "§ 5.3.4 Capability Invocation") [(2)](#ref-for-dfn-verification-method-58 "Reference 2") [(3)](#ref-for-dfn-verification-method-59 "Reference 3") [(4)](#ref-for-dfn-verification-method-60 "Reference 4") +- [§ 5.3.5 Capability Delegation](#ref-for-dfn-verification-method-61 "§ 5.3.5 Capability Delegation") [(2)](#ref-for-dfn-verification-method-62 "Reference 2") [(3)](#ref-for-dfn-verification-method-63 "Reference 3") +- [§ 8.2 Method Operations](#ref-for-dfn-verification-method-64 "§ 8.2 Method Operations") [(2)](#ref-for-dfn-verification-method-65 "Reference 2") +- [§ Proving Control of a DID and/or DID Document](#ref-for-dfn-verification-method-66 "§ Proving Control of a DID and/or DID Document") +- [§ 9.7 Verification Method Rotation](#ref-for-dfn-verification-method-67 "§ 9.7 Verification Method Rotation") [(2)](#ref-for-dfn-verification-method-68 "Reference 2") [(3)](#ref-for-dfn-verification-method-69 "Reference 3") [(4)](#ref-for-dfn-verification-method-70 "Reference 4") [(5)](#ref-for-dfn-verification-method-71 "Reference 5") [(6)](#ref-for-dfn-verification-method-72 "Reference 6") [(7)](#ref-for-dfn-verification-method-73 "Reference 7") [(8)](#ref-for-dfn-verification-method-74 "Reference 8") [(9)](#ref-for-dfn-verification-method-75 "Reference 9") [(10)](#ref-for-dfn-verification-method-76 "Reference 10") [(11)](#ref-for-dfn-verification-method-77 "Reference 11") [(12)](#ref-for-dfn-verification-method-78 "Reference 12") [(13)](#ref-for-dfn-verification-method-79 "Reference 13") [(14)](#ref-for-dfn-verification-method-80 "Reference 14") [(15)](#ref-for-dfn-verification-method-81 "Reference 15") +- [§ 9.8 Verification Method Revocation](#ref-for-dfn-verification-method-82 "§ 9.8 Verification Method Revocation") [(2)](#ref-for-dfn-verification-method-83 "Reference 2") [(3)](#ref-for-dfn-verification-method-84 "Reference 3") [(4)](#ref-for-dfn-verification-method-85 "Reference 4") [(5)](#ref-for-dfn-verification-method-86 "Reference 5") [(6)](#ref-for-dfn-verification-method-87 "Reference 6") [(7)](#ref-for-dfn-verification-method-88 "Reference 7") [(8)](#ref-for-dfn-verification-method-89 "Reference 8") [(9)](#ref-for-dfn-verification-method-90 "Reference 9") [(10)](#ref-for-dfn-verification-method-91 "Reference 10") [(11)](#ref-for-dfn-verification-method-92 "Reference 11") [(12)](#ref-for-dfn-verification-method-93 "Reference 12") [(13)](#ref-for-dfn-verification-method-94 "Reference 13") [(14)](#ref-for-dfn-verification-method-95 "Reference 14") [(15)](#ref-for-dfn-verification-method-96 "Reference 15") +- [§ Revocation Semantics](#ref-for-dfn-verification-method-97 "§ Revocation Semantics") +- [§ Revocation in Trustless Systems](#ref-for-dfn-verification-method-98 "§ Revocation in Trustless Systems") +- [§ 9.16 Persistence](#ref-for-dfn-verification-method-99 "§ 9.16 Persistence") +- [§ 10.1 Keep Personal Data Private](#ref-for-dfn-verification-method-100 "§ 10.1 Keep Personal Data Private") +- [§ 10.3 DID Document Correlation Risks](#ref-for-dfn-verification-method-101 "§ 10.3 DID Document Correlation Risks") [(2)](#ref-for-dfn-verification-method-102 "Reference 2") +- [§ 10.4 DID Subject Classification](#ref-for-dfn-verification-method-103 "§ 10.4 DID Subject Classification") +- [§ A.1 DID Documents](#ref-for-dfn-verification-method-104 "§ A.1 DID Documents") +- [§ B.12 Changing the DID controller](#ref-for-dfn-verification-method-105 "§ B.12 Changing the DID controller") [(2)](#ref-for-dfn-verification-method-106 "Reference 2") + +[Permalink](#dfn-verification-relationship) + +**Referenced in:** + +- [§ 5.1.2 DID Controller](#ref-for-dfn-verification-relationship-1 "§ 5.1.2 DID Controller") +- [§ 5.2.2 Referring to Verification Methods](#ref-for-dfn-verification-relationship-2 "§ 5.2.2 Referring to Verification Methods") [(2)](#ref-for-dfn-verification-relationship-3 "Reference 2") +- [§ 5.3 Verification Relationships](#ref-for-dfn-verification-relationship-4 "§ 5.3 Verification Relationships") [(2)](#ref-for-dfn-verification-relationship-5 "Reference 2") [(3)](#ref-for-dfn-verification-relationship-6 "Reference 3") [(4)](#ref-for-dfn-verification-relationship-7 "Reference 4") [(5)](#ref-for-dfn-verification-relationship-8 "Reference 5") [(6)](#ref-for-dfn-verification-relationship-9 "Reference 6") [(7)](#ref-for-dfn-verification-relationship-10 "Reference 7") [(8)](#ref-for-dfn-verification-relationship-11 "Reference 8") [(9)](#ref-for-dfn-verification-relationship-12 "Reference 9") +- [§ 5.3.1 Authentication](#ref-for-dfn-verification-relationship-13 "§ 5.3.1 Authentication") [(2)](#ref-for-dfn-verification-relationship-14 "Reference 2") +- [§ 5.3.2 Assertion](#ref-for-dfn-verification-relationship-15 "§ 5.3.2 Assertion") +- [§ 5.3.3 Key Agreement](#ref-for-dfn-verification-relationship-16 "§ 5.3.3 Key Agreement") +- [§ 5.3.4 Capability Invocation](#ref-for-dfn-verification-relationship-17 "§ 5.3.4 Capability Invocation") +- [§ 5.3.5 Capability Delegation](#ref-for-dfn-verification-relationship-18 "§ 5.3.5 Capability Delegation") [(2)](#ref-for-dfn-verification-relationship-19 "Reference 2") +- [§ 8.2 Method Operations](#ref-for-dfn-verification-relationship-20 "§ 8.2 Method Operations") +- [§ Proving Control of a DID and/or DID Document](#ref-for-dfn-verification-relationship-21 "§ Proving Control of a DID and/or DID Document") +- [§ Binding to Physical Identity](#ref-for-dfn-verification-relationship-22 "§ Binding to Physical Identity") +- [§ 9.8 Verification Method Revocation](#ref-for-dfn-verification-relationship-23 "§ 9.8 Verification Method Revocation") +- [§ 9.17 Level of Assurance](#ref-for-dfn-verification-relationship-24 "§ 9.17 Level of Assurance") + +[Permalink](#dfn-uuid) + +**Referenced in:** + +- [§ 3.2.1 DID Parameters](#ref-for-dfn-uuid-1 "§ 3.2.1 DID Parameters") + +[Permalink](#dfn-datetime) + +**Referenced in:** + +- [§ 6.1 Production and Consumption](#ref-for-dfn-datetime-1 "§ 6.1 Production and Consumption") [(2)](#ref-for-dfn-datetime-2 "Reference 2") +- [§ 6.2.1 Production](#ref-for-dfn-datetime-3 "§ 6.2.1 Production") +- [§ 6.2.2 Consumption](#ref-for-dfn-datetime-4 "§ 6.2.2 Consumption") [(2)](#ref-for-dfn-datetime-5 "Reference 2") + +[Permalink](#dfn-integer) + +**Referenced in:** + +- [§ 6.2.1 Production](#ref-for-dfn-integer-1 "§ 6.2.1 Production") +- [§ 6.2.2 Consumption](#ref-for-dfn-integer-2 "§ 6.2.2 Consumption") + +[Permalink](#dfn-double) + +**Referenced in:** + +- [§ 6.2.1 Production](#ref-for-dfn-double-1 "§ 6.2.1 Production") +- [§ 6.2.2 Consumption](#ref-for-dfn-double-2 "§ 6.2.2 Consumption") [(2)](#ref-for-dfn-double-3 "Reference 2") + +[Permalink](#dfn-id) + +**Referenced in:** + +- [§ DID Document properties](#ref-for-dfn-id-1 "§ DID Document properties") +- [§ 5.1.1 DID Subject](#ref-for-dfn-id-2 "§ 5.1.1 DID Subject") [(2)](#ref-for-dfn-id-3 "Reference 2") [(3)](#ref-for-dfn-id-4 "Reference 3") +- [§ 5.2 Verification Methods](#ref-for-dfn-id-5 "§ 5.2 Verification Methods") +- [§ 5.4 Services](#ref-for-dfn-id-6 "§ 5.4 Services") +- [§ 7.1 DID Resolution](#ref-for-dfn-id-7 "§ 7.1 DID Resolution") +- [§ 9.12 Immutability](#ref-for-dfn-id-8 "§ 9.12 Immutability") [(2)](#ref-for-dfn-id-9 "Reference 2") +- [§ B.3 Determining the DID subject](#ref-for-dfn-id-10 "§ B.3 Determining the DID subject") +- [§ B.5 Statements in the DID document](#ref-for-dfn-id-11 "§ B.5 Statements in the DID document") [(2)](#ref-for-dfn-id-12 "Reference 2") +- [§ B.11 Changing the DID subject](#ref-for-dfn-id-13 "§ B.11 Changing the DID subject") + +[Permalink](#dfn-controller) + +**Referenced in:** + +- [§ 1.3 Architecture Overview](#ref-for-dfn-controller-1 "§ 1.3 Architecture Overview") +- [§ DID Document properties](#ref-for-dfn-controller-2 "§ DID Document properties") +- [§ Verification Method properties](#ref-for-dfn-controller-3 "§ Verification Method properties") +- [§ 5.1.2 DID Controller](#ref-for-dfn-controller-4 "§ 5.1.2 DID Controller") +- [§ 5.2 Verification Methods](#ref-for-dfn-controller-5 "§ 5.2 Verification Methods") +- [§ 8.2 Method Operations](#ref-for-dfn-controller-6 "§ 8.2 Method Operations") +- [§ 9.7 Verification Method Rotation](#ref-for-dfn-controller-7 "§ 9.7 Verification Method Rotation") [(2)](#ref-for-dfn-controller-8 "Reference 2") +- [§ 9.8 Verification Method Revocation](#ref-for-dfn-controller-9 "§ 9.8 Verification Method Revocation") [(2)](#ref-for-dfn-controller-10 "Reference 2") [(3)](#ref-for-dfn-controller-11 "Reference 3") [(4)](#ref-for-dfn-controller-12 "Reference 4") [(5)](#ref-for-dfn-controller-13 "Reference 5") +- [§ 9.9 DID Recovery](#ref-for-dfn-controller-14 "§ 9.9 DID Recovery") [(2)](#ref-for-dfn-controller-15 "Reference 2") +- [§ 9.16 Persistence](#ref-for-dfn-controller-16 "§ 9.16 Persistence") [(2)](#ref-for-dfn-controller-17 "Reference 2") [(3)](#ref-for-dfn-controller-18 "Reference 3") [(4)](#ref-for-dfn-controller-19 "Reference 4") [(5)](#ref-for-dfn-controller-20 "Reference 5") [(6)](#ref-for-dfn-controller-21 "Reference 6") [(7)](#ref-for-dfn-controller-22 "Reference 7") [(8)](#ref-for-dfn-controller-23 "Reference 8") [(9)](#ref-for-dfn-controller-24 "Reference 9") +- [§ 10.6 Service Privacy](#ref-for-dfn-controller-25 "§ 10.6 Service Privacy") +- [§ B.12 Changing the DID controller](#ref-for-dfn-controller-26 "§ B.12 Changing the DID controller") + +[Permalink](#dfn-alsoknownas) + +**Referenced in:** + +- [§ DID Document properties](#ref-for-dfn-alsoknownas-1 "§ DID Document properties") +- [§ 5.1.3 Also Known As](#ref-for-dfn-alsoknownas-2 "§ 5.1.3 Also Known As") [(2)](#ref-for-dfn-alsoknownas-3 "Reference 2") [(3)](#ref-for-dfn-alsoknownas-4 "Reference 3") [(4)](#ref-for-dfn-alsoknownas-5 "Reference 4") +- [§ 7.1.3 DID Document Metadata](#ref-for-dfn-alsoknownas-6 "§ 7.1.3 DID Document Metadata") +- [§ 9.14 Equivalence Properties](#ref-for-dfn-alsoknownas-7 "§ 9.14 Equivalence Properties") [(2)](#ref-for-dfn-alsoknownas-8 "Reference 2") +- [§ B.5 Statements in the DID document](#ref-for-dfn-alsoknownas-9 "§ B.5 Statements in the DID document") +- [§ B.6 Discovering more information about the DID subject](#ref-for-dfn-alsoknownas-10 "§ B.6 Discovering more information about the DID subject") +- [§ B.8 Assigning DIDs to existing web resources](#ref-for-dfn-alsoknownas-11 "§ B.8 Assigning DIDs to existing web resources") + +[Permalink](#dfn-verificationmethod) + +**Referenced in:** + +- [§ DID Document properties](#ref-for-dfn-verificationmethod-1 "§ DID Document properties") +- [§ B.5 Statements in the DID document](#ref-for-dfn-verificationmethod-2 "§ B.5 Statements in the DID document") + +[Permalink](#dfn-publickeyjwk) + +**Referenced in:** + +- [§ Verification Method properties](#ref-for-dfn-publickeyjwk-1 "§ Verification Method properties") [(2)](#ref-for-dfn-publickeyjwk-2 "Reference 2") +- [§ 5.2.1 Verification Material](#ref-for-dfn-publickeyjwk-3 "§ 5.2.1 Verification Material") + +[Permalink](#dfn-publickeymultibase) + +**Referenced in:** + +- [§ Verification Method properties](#ref-for-dfn-publickeymultibase-1 "§ Verification Method properties") +- [§ 5.2.1 Verification Material](#ref-for-dfn-publickeymultibase-2 "§ 5.2.1 Verification Material") + +[Permalink](#dfn-authentication) + +**Referenced in:** + +- [§ DID Document properties](#ref-for-dfn-authentication-1 "§ DID Document properties") +- [§ 5.3 Verification Relationships](#ref-for-dfn-authentication-2 "§ 5.3 Verification Relationships") +- [§ 5.3.1 Authentication](#ref-for-dfn-authentication-3 "§ 5.3.1 Authentication") [(2)](#ref-for-dfn-authentication-4 "Reference 2") [(3)](#ref-for-dfn-authentication-5 "Reference 3") +- [§ 8.2 Method Operations](#ref-for-dfn-authentication-6 "§ 8.2 Method Operations") +- [§ 9.17 Level of Assurance](#ref-for-dfn-authentication-7 "§ 9.17 Level of Assurance") + +[Permalink](#dfn-assertionmethod) + +**Referenced in:** + +- [§ DID Document properties](#ref-for-dfn-assertionmethod-1 "§ DID Document properties") +- [§ 5.3.2 Assertion](#ref-for-dfn-assertionmethod-2 "§ 5.3.2 Assertion") +- [§ 9.17 Level of Assurance](#ref-for-dfn-assertionmethod-3 "§ 9.17 Level of Assurance") + +[Permalink](#dfn-keyagreement) + +**Referenced in:** + +- [§ DID Document properties](#ref-for-dfn-keyagreement-1 "§ DID Document properties") +- [§ 5.3 Verification Relationships](#ref-for-dfn-keyagreement-2 "§ 5.3 Verification Relationships") + +[Permalink](#dfn-capabilityinvocation) + +**Referenced in:** + +- [§ DID Document properties](#ref-for-dfn-capabilityinvocation-1 "§ DID Document properties") +- [§ 5.3.4 Capability Invocation](#ref-for-dfn-capabilityinvocation-2 "§ 5.3.4 Capability Invocation") +- [§ 8.2 Method Operations](#ref-for-dfn-capabilityinvocation-3 "§ 8.2 Method Operations") + +[Permalink](#dfn-capabilitydelegation) + +**Referenced in:** + +- [§ DID Document properties](#ref-for-dfn-capabilitydelegation-1 "§ DID Document properties") + +[Permalink](#dfn-serviceendpoint) + +**Referenced in:** + +- [§ Service properties](#ref-for-dfn-serviceendpoint-1 "§ Service properties") +- [§ 5.4 Services](#ref-for-dfn-serviceendpoint-2 "§ 5.4 Services") + +[Permalink](#dfn-production) + +**Referenced in:** + +- [§ 6. Representations](#ref-for-dfn-production-1 "§ 6. Representations") +- [§ 6.1 Production and Consumption](#ref-for-dfn-production-2 "§ 6.1 Production and Consumption") [(2)](#ref-for-dfn-production-3 "Reference 2") [(3)](#ref-for-dfn-production-4 "Reference 3") [(4)](#ref-for-dfn-production-5 "Reference 4") [(5)](#ref-for-dfn-production-6 "Reference 5") +- [§ 6.2 JSON](#ref-for-dfn-production-7 "§ 6.2 JSON") +- [§ 6.2.1 Production](#ref-for-dfn-production-8 "§ 6.2.1 Production") +- [§ 6.3 JSON-LD](#ref-for-dfn-production-9 "§ 6.3 JSON-LD") +- [§ 6.3.1 Production](#ref-for-dfn-production-10 "§ 6.3.1 Production") [(2)](#ref-for-dfn-production-11 "Reference 2") [(3)](#ref-for-dfn-production-12 "Reference 3") + +[Permalink](#dfn-consumption) + +**Referenced in:** + +- [§ 6. Representations](#ref-for-dfn-consumption-1 "§ 6. Representations") +- [§ 6.1 Production and Consumption](#ref-for-dfn-consumption-2 "§ 6.1 Production and Consumption") [(2)](#ref-for-dfn-consumption-3 "Reference 2") [(3)](#ref-for-dfn-consumption-4 "Reference 3") [(4)](#ref-for-dfn-consumption-5 "Reference 4") [(5)](#ref-for-dfn-consumption-6 "Reference 5") [(6)](#ref-for-dfn-consumption-7 "Reference 6") +- [§ 6.2 JSON](#ref-for-dfn-consumption-8 "§ 6.2 JSON") +- [§ 6.2.2 Consumption](#ref-for-dfn-consumption-9 "§ 6.2.2 Consumption") +- [§ 6.3 JSON-LD](#ref-for-dfn-consumption-10 "§ 6.3 JSON-LD") +- [§ 6.3.2 Consumption](#ref-for-dfn-consumption-11 "§ 6.3.2 Consumption") + +[Permalink](#dfn-context) + +**Referenced in:** + +- [§ 2. Terminology](#ref-for-dfn-context-1 "§ 2. Terminology") +- [§ 6.3.1 Production](#ref-for-dfn-context-2 "§ 6.3.1 Production") + +[Permalink](#dfn-didresolutionmetadata) + +**Referenced in:** + +- [§ 7.1 DID Resolution](#ref-for-dfn-didresolutionmetadata-1 "§ 7.1 DID Resolution") [(2)](#ref-for-dfn-didresolutionmetadata-2 "Reference 2") + +[Permalink](#dfn-diddocument) + +**Referenced in:** + +- [§ 7.1 DID Resolution](#ref-for-dfn-diddocument-1 "§ 7.1 DID Resolution") + +[Permalink](#dfn-diddocumentstream) + +**Referenced in:** + +- [§ 7.1 DID Resolution](#ref-for-dfn-diddocumentstream-1 "§ 7.1 DID Resolution") + +[Permalink](#dfn-diddocumentmetadata) + +**Referenced in:** + +- [§ 7.1 DID Resolution](#ref-for-dfn-diddocumentmetadata-1 "§ 7.1 DID Resolution") [(2)](#ref-for-dfn-diddocumentmetadata-2 "Reference 2") +- [§ 7.2 DID URL Dereferencing](#ref-for-dfn-diddocumentmetadata-3 "§ 7.2 DID URL Dereferencing") + +[Permalink](#dfn-equivalentid) + +**Referenced in:** + +- [§ 7.1.3 DID Document Metadata](#ref-for-dfn-equivalentid-1 "§ 7.1.3 DID Document Metadata") [(2)](#ref-for-dfn-equivalentid-2 "Reference 2") [(3)](#ref-for-dfn-equivalentid-3 "Reference 3") [(4)](#ref-for-dfn-equivalentid-4 "Reference 4") [(5)](#ref-for-dfn-equivalentid-5 "Reference 5") [(6)](#ref-for-dfn-equivalentid-6 "Reference 6") [(7)](#ref-for-dfn-equivalentid-7 "Reference 7") [(8)](#ref-for-dfn-equivalentid-8 "Reference 8") [(9)](#ref-for-dfn-equivalentid-9 "Reference 9") [(10)](#ref-for-dfn-equivalentid-10 "Reference 10") [(11)](#ref-for-dfn-equivalentid-11 "Reference 11") [(12)](#ref-for-dfn-equivalentid-12 "Reference 12") +- [§ 9.14 Equivalence Properties](#ref-for-dfn-equivalentid-13 "§ 9.14 Equivalence Properties") [(2)](#ref-for-dfn-equivalentid-14 "Reference 2") + +[Permalink](#dfn-canonicalid) + +**Referenced in:** + +- [§ 7.1.3 DID Document Metadata](#ref-for-dfn-canonicalid-1 "§ 7.1.3 DID Document Metadata") [(2)](#ref-for-dfn-canonicalid-2 "Reference 2") [(3)](#ref-for-dfn-canonicalid-3 "Reference 3") [(4)](#ref-for-dfn-canonicalid-4 "Reference 4") [(5)](#ref-for-dfn-canonicalid-5 "Reference 5") [(6)](#ref-for-dfn-canonicalid-6 "Reference 6") [(7)](#ref-for-dfn-canonicalid-7 "Reference 7") [(8)](#ref-for-dfn-canonicalid-8 "Reference 8") [(9)](#ref-for-dfn-canonicalid-9 "Reference 9") [(10)](#ref-for-dfn-canonicalid-10 "Reference 10") +- [§ 9.14 Equivalence Properties](#ref-for-dfn-canonicalid-11 "§ 9.14 Equivalence Properties") [(2)](#ref-for-dfn-canonicalid-12 "Reference 2") diff --git a/specifications/json-ld11.md b/specifications/json-ld11.md new file mode 100644 index 0000000..22a7a14 --- /dev/null +++ b/specifications/json-ld11.md @@ -0,0 +1,10308 @@ +--- +description: JSON is a useful data serialization and messaging format. This specification defines JSON-LD 1.1, a JSON-based format to serialize Linked Data. The syntax is designed to easily integrate into deployed systems that already use JSON, and provides a smooth upgrade path from JSON to JSON-LD. It is primarily intended to be a way to use Linked Data in Web-based programming environments, to build interoperable Web services, and to store Linked Data in JSON-based storage engines. +generator: ReSpec 25.6.0 +lang: en +title: JSON-LD 1.1 +viewport: width=device-width, initial-scale=1, shrink-to-fit=no +--- + +[![W3C](https://www.w3.org/StyleSheets/TR/2016/logos/W3C)](https://www.w3.org/) + +# JSON-LD 1.1 + +## A JSON-based Serialization for Linked Data + +## W3C Recommendation 16 July 2020 + +This version: +: [https://www.w3.org/TR/2020/REC-json-ld11-20200716/](https://www.w3.org/TR/2020/REC-json-ld11-20200716/) + +Latest published version: +: + +Latest editor\'s draft: +: + +Test suite: +: + +Implementation report: +: + +Previous version: +: + +Previous Recommendation: +: + +Editors: +: [Gregg Kellogg](https://greggkellogg.net/) (v1.0 and v1.1) +: [Pierre-Antoine Champin](http://champin.net/) ([LIRIS - Université de Lyon](https://liris.cnrs.fr/)) (v1.1) +: [Dave Longley](https://digitalbazaar.com/author/dlongley/) ([Digital Bazaar](https://digitalbazaar.com/)) (v1.1) + +Former editors: +: [Manu Sporny](http://manu.sporny.org/) ([Digital Bazaar](https://digitalbazaar.com/)) (v1.0) +: [Markus Lanthaler](https://www.markus-lanthaler.com/) ([Google](https://www.google.com/)) (v1.0) + +Authors: +: [Manu Sporny](http://manu.sporny.org/) ([Digital Bazaar](https://digitalbazaar.com/)) (v1.0) +: [Dave Longley](https://digitalbazaar.com/author/dlongley/) ([Digital Bazaar](https://digitalbazaar.com/)) (v1.0 and v1.1) +: [Gregg Kellogg](https://greggkellogg.net/) (v1.0 and v1.1) +: [Markus Lanthaler](https://www.markus-lanthaler.com/) ([Google](https://www.google.com/)) (v1.0) +: [Pierre-Antoine Champin](http://champin.net/) ([LIRIS - Université de Lyon](https://liris.cnrs.fr/)) (v1.1) +: [Niklas Lindström](http://neverspace.net/) (v1.0) + +Participate: +: [GitHub w3c/json-ld-syntax](https://github.com/w3c/json-ld-syntax/) +: [File a bug](https://github.com/w3c/json-ld-syntax/issues/) +: [Commit history](https://github.com/w3c/json-ld-syntax/commits/master) +: [Pull requests](https://github.com/w3c/json-ld-syntax/pulls/) + +Please check the [**errata**](https://w3c.github.io/json-ld-syntax/errata/) for any errors or issues reported since publication. + +See also [**translations**](https://www.w3.org/2003/03/Translations/byTechnology?technology=json-ld11). + +This document is also available in this non-normative format: [EPUB](json-ld11.epub) + +[Copyright](https://www.w3.org/Consortium/Legal/ipr-notice#Copyright) © 2010-2020 [W3C](https://www.w3.org/)^®^ ([MIT](https://www.csail.mit.edu/), [ERCIM](https://www.ercim.eu/), [Keio](https://www.keio.ac.jp/), [Beihang](https://ev.buaa.edu.cn/)). W3C [liability](https://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer), [trademark](https://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks) and [permissive document license](https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document) rules apply. + +------------------------------------------------------------------------ + +## Abstract + +JSON is a useful data serialization and messaging format. This specification defines JSON-LD 1.1, a JSON-based format to serialize Linked Data. The syntax is designed to easily integrate into deployed systems that already use JSON, and provides a smooth upgrade path from JSON to JSON-LD. It is primarily intended to be a way to use Linked Data in Web-based programming environments, to build interoperable Web services, and to store Linked Data in JSON-based storage engines. + +This specification describes a superset of the features defined in [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/) \[[JSON-LD10](#bib-json-ld10 "JSON-LD 1.0")\] and, except where noted, documents created using the 1.0 version of this specification remain compatible with JSON-LD 1.1. + +## 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](https://www.w3.org/TR/) at https://www.w3.org/TR/.* + +This document has been developed by the [JSON-LD Working Group](https://www.w3.org/2018/json-ld-wg/) and was derived from the [JSON-LD Community Group\'s](https://www.w3.org/community/json-ld/) [Final Report](https://www.w3.org/2018/jsonld-cg-reports/json-ld/). + +There is a [live JSON-LD playground](https://json-ld.org/playground/) that is capable of demonstrating the features described in this document. + +This specification is intended to [supersede](https://www.w3.org/2019/Process-20190301/#rec-rescind) the [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/) \[[JSON-LD10](#bib-json-ld10 "JSON-LD 1.0")\] specification. + +This document was published by the [JSON-LD Working Group](https://www.w3.org/2018/json-ld-wg/) as a Recommendation. + +[GitHub Issues](https://github.com/w3c/json-ld-syntax/issues/) are preferred for discussion of this specification. Alternatively, you can send comments to our mailing list. Please send them to ([archives](https://lists.w3.org/Archives/Public/public-json-ld-wg/)). + +Please see the Working Group\'s [implementation report](https://w3c.github.io/json-ld-api/reports/). + +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](https://www.w3.org/Consortium/Patent-Policy/). W3C maintains a [public list of any patent disclosures](https://www.w3.org/2004/01/pp-impl/107714/status) 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)](https://www.w3.org/Consortium/Patent-Policy/#def-essential) must disclose the information in accordance with [section 6 of the W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy/#sec-Disclosure). + +This document is governed by the [1 March 2019 W3C Process Document](https://www.w3.org/2019/Process-20190301/). + +### Set of Documents[](#set-of-documents) + +This document is one of three JSON-LD 1.1 Recommendations produced by the [JSON-LD Working Group](https://www.w3.org/2018/json-ld-wg/): + +- [JSON-LD 1.1]() +- [JSON-LD 1.1 Processing Algorithms and API](https://www.w3.org/TR/json-ld11-api/) +- [JSON-LD 1.1 Framing](https://www.w3.org/TR/json-ld11-framing/) + +## Table of Contents + +1. [1. Introduction](#introduction) + 1. [1.1 How to Read this Document](#how-to-read-this-document) + 2. [1.2 Contributing](#contributing) + 3. [1.3 Typographical conventions](#typographical-conventions) + 4. [1.4 Terminology](#terminology) + 5. [1.5 Design Goals and Rationale](#design-goals-and-rationale) + 6. [1.6 Data Model Overview](#data-model-overview) + 7. [1.7 Syntax Tokens and Keywords](#syntax-tokens-and-keywords) +2. [2. Conformance](#conformance) +3. [3. Basic Concepts](#basic-concepts) + 1. [3.1 The Context](#the-context) + 2. [3.2 IRIs](#iris) + 3. [3.3 Node Identifiers](#node-identifiers) + 4. [3.4 Uses of JSON Objects](#uses-of-json-objects) + 5. [3.5 Specifying the Type](#specifying-the-type) +4. [4. Advanced Concepts](#advanced-concepts) + 1. [4.1 Advanced Context Usage](#advanced-context-usage) + 1. [4.1.1 JSON-LD 1.1 Processing Mode](#json-ld-1-1-processing-mode) + 2. [4.1.2 Default Vocabulary](#default-vocabulary) + 3. [4.1.3 Base IRI](#base-iri) + 4. [4.1.4 Using the Document Base for the Default Vocabulary](#document-relative-vocabulary-mapping) + 5. [4.1.5 Compact IRIs](#compact-iris) + 6. [4.1.6 Aliasing Keywords](#aliasing-keywords) + 7. [4.1.7 IRI Expansion within a Context](#iri-expansion-within-a-context) + 8. [4.1.8 Scoped Contexts](#scoped-contexts) + 9. [4.1.9 Context Propagation](#context-propagation) + 10. [4.1.10 Imported Contexts](#imported-contexts) + 11. [4.1.11 Protected Term Definitions](#protected-term-definitions) + 2. [4.2 Describing Values](#describing-values) + 1. [4.2.1 Typed Values](#typed-values) + 2. [4.2.2 JSON Literals](#json-literals) + 3. [4.2.3 Type Coercion](#type-coercion) + 4. [4.2.4 String Internationalization](#string-internationalization) + 1. [4.2.4.1 Base Direction](#base-direction) + 3. [4.3 Value Ordering](#sets-and-lists) + 1. [4.3.1 Lists](#lists) + 2. [4.3.2 Sets](#sets) + 3. [4.3.3 Using `@set` with `@type`](#using-set-with-type) + 4. [4.4 Nested Properties](#nested-properties) + 5. [4.5 Embedding](#embedding) + 1. [4.5.1 Identifying Blank Nodes](#identifying-blank-nodes) + 6. [4.6 Indexed Values](#indexed-values) + 1. [4.6.1 Data Indexing](#data-indexing) + 1. [4.6.1.1 Property-based data indexing](#property-based-data-indexing) + 2. [4.6.2 Language Indexing](#language-indexing) + 3. [4.6.3 Node Identifier Indexing](#node-identifier-indexing) + 4. [4.6.4 Node Type Indexing](#node-type-indexing) + 7. [4.7 Included Nodes](#included-nodes) + 8. [4.8 Reverse Properties](#reverse-properties) + 9. [4.9 Named Graphs](#named-graphs) + 1. [4.9.1 Graph Containers](#graph-containers) + 2. [4.9.2 Named Graph Data Indexing](#named-graph-data-indexing) + 3. [4.9.3 Named Graph Indexing](#named-graph-indexing) + 10. [4.10 Loading Documents](#loading-documents) +5. [5. Forms of JSON-LD](#forms-of-json-ld) + 1. [5.1 Expanded Document Form](#expanded-document-form) + 2. [5.2 Compacted Document Form](#compacted-document-form) + 1. [5.2.1 Shortening IRIs](#shortening-iris) + 2. [5.2.2 Representing Values as Strings](#representing-values-as-strings) + 3. [5.2.3 Representing Lists as Arrays](#representing-lists-as-arrays) + 4. [5.2.4 Reversing Node Relationships](#reversing-node-relationships) + 5. [5.2.5 Indexing Values](#indexing-values) + 6. [5.2.6 Normalizing Values as Objects](#normalizing-values-as-objects) + 7. [5.2.7 Representing Singular Values as Arrays](#representing-singular-values-as-arrays) + 8. [5.2.8 Term Selection](#term-selection) + 3. [5.3 Flattened Document Form](#flattened-document-form) + 4. [5.4 Framed Document Form](#framed-document-form) +6. [6. Modifying Behavior with Link Relationships](#modifying-behavior-with-link-relationships) + 1. [6.1 Interpreting JSON as JSON-LD](#interpreting-json-as-json-ld) + 2. [6.2 Alternate Document Location](#alternate-document-location) +7. [7. Embedding JSON-LD in HTML Documents](#embedding-json-ld-in-html-documents) + 1. [7.1 Inheriting base IRI from HTML\'s `base` element](#inheriting-base-iri-from-html-s-base-element) + 2. [7.2 Restrictions for contents of JSON-LD `script` elements](#restrictions-for-contents-of-json-ld-script-elements) + 3. [7.3 Locating a Specific JSON-LD Script Element](#locating-a-specific-json-ld-script-element) +8. [8. Data Model](#data-model) +9. [9. JSON-LD Grammar](#json-ld-grammar) + 1. [9.1 Terms](#terms) + 2. [9.2 Node Objects](#node-objects) + 3. [9.3 Frame Objects](#frame-objects) + 4. [9.4 Graph Objects](#graph-objects) + 5. [9.5 Value Objects](#value-objects) + 6. [9.6 Value Patterns](#value-patterns) + 7. [9.7 Lists and Sets](#lists-and-sets) + 8. [9.8 Language Maps](#language-maps) + 9. [9.9 Index Maps](#index-maps) + 10. [9.10 Property-based Index Maps](#property-based-index-maps) + 11. [9.11 Id Maps](#id-maps) + 12. [9.12 Type Maps](#type-maps) + 13. [9.13 Included Blocks](#included-blocks) + 14. [9.14 Property Nesting](#property-nesting) + 15. [9.15 Context Definitions](#context-definitions) + 1. [9.15.1 Expanded term definition](#expanded-term-definition) + 16. [9.16 Keywords](#keywords) +10. [10. Relationship to RDF](#relationship-to-rdf) + 1. [10.1 Serializing/Deserializing RDF](#serializing-deserializing-rdf) + 2. [10.2 The `rdf:JSON` Datatype](#the-rdf-json-datatype) + 3. [10.3 The `i18n` Namespace](#the-i18n-namespace) + 4. [10.4 The `rdf:CompoundLiteral` class and the `rdf:language` and `rdf:direction` properties](#the-rdf-compoundliteral-class-and-the-rdf-language-and-rdf-direction-properties) +11. [11. Security Considerations](#security) +12. [12. Privacy Considerations](#privacy) +13. [13. Internationalization Considerations](#internationalization) +14. [A. Image Descriptions](#image-descriptions) + 1. [A.1 Linked Data Dataset](#fig-linked-data-graph-descr) +15. [B. Relationship to Other Linked Data Formats](#relationship-to-other-linked-data-formats) + 1. [B.1 Turtle](#turtle) + 1. [B.1.1 Prefix definitions](#prefix-definitions) + 2. [B.1.2 Embedding](#embedding-0) + 3. [B.1.3 Conversion of native data types](#conversion-of-native-data-types) + 4. [B.1.4 Lists](#lists-0) + 2. [B.2 RDFa](#rdfa) + 3. [B.3 Microdata](#microdata) +16. [C. IANA Considerations](#iana-considerations) + 1. [C.1 Examples](#iana-examples) +17. [D. Open Issues](#open-issues) +18. [E. Changes since 1.0 Recommendation of 16 January 2014](#changes-from-10) +19. [F. Changes since JSON-LD Community Group Final Report](#changes-from-cg) +20. [G. Changes since Candidate Release of 12 December 2019](#changes-from-cr) +21. [H. Changes since Proposed Recommendation Release of 7 May 2020](#changes-from-pr) +22. [I. Acknowledgements](#ack) +23. [J. References](#references) + 1. [J.1 Normative references](#normative-references) + 2. [J.2 Informative references](#informative-references) + +## 1. Introduction[](#introduction) + +*This section is non-normative.* + +Linked Data \[[LINKED-DATA](#bib-linked-data "Linked Data Design Issues")\] is a way to create a network of standards-based machine interpretable data across different documents and Web sites. It allows an application to start at one piece of Linked Data, and follow embedded links to other pieces of Linked Data that are hosted on different sites across the Web. + +JSON-LD is a lightweight syntax to serialize Linked Data in JSON \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\]. Its design allows existing JSON to be interpreted as Linked Data with minimal changes. JSON-LD is primarily intended to be a way to use Linked Data in Web-based programming environments, to build interoperable Web services, and to store Linked Data in JSON-based storage engines. Since JSON-LD is 100% compatible with JSON, the large number of JSON parsers and libraries available today can be reused. In addition to all the features JSON provides, JSON-LD introduces: + +- a universal identifier mechanism for [JSON objects](https://tools.ietf.org/html/rfc8259#section-4) via the use of [IRIs](https://tools.ietf.org/html/rfc3987#section-2), +- a way to disambiguate keys shared among different JSON documents by mapping them to [IRIs](https://tools.ietf.org/html/rfc3987#section-2) via a [context](#dfn-context), +- a mechanism in which a value in a [JSON object](https://tools.ietf.org/html/rfc8259#section-4) may refer to a [resource](https://www.w3.org/TR/rdf11-concepts/#dfn-resource) on a different site on the Web, +- the ability to annotate [strings](https://infra.spec.whatwg.org/#javascript-string) with their language, +- a way to associate datatypes with values such as dates and times, +- and a facility to express one or more directed graphs, such as a social network, in a single document. + +JSON-LD is designed to be usable directly as JSON, with no knowledge of RDF \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\]. It is also designed to be usable as RDF in conjunction with other Linked Data technologies like SPARQL \[[SPARQL11-OVERVIEW](#bib-sparql11-overview "SPARQL 1.1 Overview")\]. Developers who require any of the facilities listed above or need to serialize an [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) or [Dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) in a JSON-based syntax will find JSON-LD of interest. People intending to use JSON-LD with RDF tools will find it can be used as another RDF syntax, as with \[[Turtle](#bib-turtle "RDF 1.1 Turtle")\] and \[[TriG](#bib-trig "RDF 1.1 TriG")\]. Complete details of how JSON-LD relates to RDF are in section [§ 10. Relationship to RDF](#relationship-to-rdf). + +The syntax is designed to not disturb already deployed systems running on JSON, but provide a smooth upgrade path from JSON to JSON-LD. Since the shape of such data varies wildly, JSON-LD features mechanisms to reshape documents into a deterministic structure which simplifies their processing. + +### 1.1 How to Read this Document[](#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 encode Linked Data in a variety of programming languages that can use JSON +- Software developers who want to convert existing JSON to JSON-LD +- Software developers who want to understand the design decisions and language syntax for JSON-LD +- Software developers who want to implement processors and APIs for JSON-LD +- Software developers who want to generate or consume Linked Data, an [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph), or an [RDF Dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) in a JSON syntax + +A companion document, the JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\], specifies how to work with JSON-LD at a higher level by providing a standard library interface for common JSON-LD operations. + +To understand the basics in this specification you must first be familiar with [JSON](https://tools.ietf.org/html/rfc8259), which is detailed in \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\]. + +This document almost exclusively uses the term IRI ([Internationalized Resource Indicator](https://www.w3.org/TR/ld-glossary/#internationalized-resource-identifier)) when discussing hyperlinks. Many Web developers are more familiar with the URL ([Uniform Resource Locator](https://www.w3.org/TR/ld-glossary/#uniform-resource-locator)) terminology. The document also uses, albeit rarely, the URI ([Uniform Resource Indicator](https://www.w3.org/TR/ld-glossary/#uniform-resource-identifier)) terminology. While these terms are often used interchangeably among technical communities, they do have important distinctions from one another and the specification goes to great lengths to try and use the proper terminology at all times. + +This document can highlight changes since the [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/) version. Select to changes. + +### 1.2 Contributing[](#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 working group mailing list: [public-json-ld-wg@w3.org](https://lists.w3.org/Archives/Public/public-json-ld-wg/) +- The working group uses [#json-ld](http://irc.w3.org/?channels=json-ld) IRC channel is available for real-time discussion on [irc.w3.org](http://irc.w3.org). +- The [#json-ld](https://webchat.freenode.net/?channels=json-ld) IRC channel is also available for real-time discussion on irc.freenode.net. + +### 1.3 Typographical conventions[](#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](#dfn-definition) +: A reference to a definition *in this document* is underlined and is also an active link to the definition itself. + +[`markup definition reference`](#dfn-definition) +: 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](#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](#example-1) + +``` nohighlight +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[](#terminology) + +*This section is non-normative.* + +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-other-specifications) + +Terms imported from [ECMAScript Language Specification](https://tc39.es/ecma262/) \[[ECMASCRIPT](#bib-ecmascript "ECMAScript Language Specification")\], [The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc8259) \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\], [Infra Standard](https://infra.spec.whatwg.org/) \[[INFRA](#bib-infra "Infra Standard")\], and [Web IDL](https://heycam.github.io/webidl/) \[[WEBIDL](#bib-webidl "Web IDL")\] + +[array](https://infra.spec.whatwg.org/#list) +: In the JSON serialization, an [array](https://infra.spec.whatwg.org/#list) structure is represented as square brackets surrounding zero or more values. Values are separated by commas. In the [internal representation](https://www.w3.org/TR/json-ld11-api/#dfn-internal-representation), a [list](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab) (also called an [array](https://infra.spec.whatwg.org/#list)) 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](#sets-and-lists) section of JSON-LD 1.1. + +[boolean](https://infra.spec.whatwg.org/#boolean) +: The values `true` and `false` that are used to express one of two possible states. + +[JSON object](https://tools.ietf.org/html/rfc8259#section-4) + +: In the JSON serialization, an [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members). A name is a [string](https://infra.spec.whatwg.org/#javascript-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](https://www.w3.org/TR/json-ld11-api/#dfn-internal-representation) a [JSON object](https://tools.ietf.org/html/rfc8259#section-4) is described as a [map](https://infra.spec.whatwg.org/#ordered-map) (see \[[INFRA](#bib-infra "Infra Standard")\]), composed of [entries](https://infra.spec.whatwg.org/#map-entry) with key/value pairs. + + In the [Application Programming Interface](https://www.w3.org/TR/json-ld11-api/#the-application-programming-interface), a [map](https://infra.spec.whatwg.org/#ordered-map) is described using a \[[WEBIDL](#bib-webidl "Web IDL")\] [record](https://heycam.github.io/webidl/#idl-record). + +[null](https://infra.spec.whatwg.org/#nulls) +: The use of the [null](https://infra.spec.whatwg.org/#nulls) value within JSON-LD is used to ignore or reset values. A [map entry](https://infra.spec.whatwg.org/#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](https://infra.spec.whatwg.org/#map-entry) in the body of a [JSON-LD document](#dfn-json-ld-document) whose value is `null` has the same meaning as if the [map entry](https://infra.spec.whatwg.org/#map-entry) was not defined. If `@value`, `@list`, or `@set` is set to `null` in expanded form, then the entire [JSON object](https://tools.ietf.org/html/rfc8259#section-4) is ignored. + +[number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value) +: In the JSON serialization, a [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value) 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](https://www.w3.org/TR/json-ld11-api/#dfn-internal-representation), a [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value) is equivalent to either a [long](https://heycam.github.io/webidl/#idl-long) or [double](https://heycam.github.io/webidl/#idl-double), depending on if the number has a non-zero fractional part (see \[[WEBIDL](#bib-webidl "Web IDL")\]). + +[scalar](https://infra.spec.whatwg.org/#primitive-data-types) +: A scalar is either a [string](https://infra.spec.whatwg.org/#javascript-string), [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), `true`, or `false`. + +[string](https://infra.spec.whatwg.org/#javascript-string) +: A [string](https://infra.spec.whatwg.org/#javascript-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)](https://tools.ietf.org/html/rfc3987) \[[RFC3987](#bib-rfc3987 "Internationalized Resource Identifiers (IRIs)")\] + +[IRI](https://tools.ietf.org/html/rfc3987#section-2) +: The absolute form of an [IRI](https://tools.ietf.org/html/rfc3987#section-2) containing a *scheme* along with a *path* and optional *query* and *fragment* segments. + +[IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3) +: Denotes the common usage of an [Internationalized Resource Identifier](https://tools.ietf.org/html/rfc3987#section-2). An [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3) may be absolute or [relative](https://tools.ietf.org/html/rfc3987#section-6.5). However, the \"IRI\" that results from such a reference only includes absolute [IRIs](https://tools.ietf.org/html/rfc3987#section-2); any [relative IRI references](https://tools.ietf.org/html/rfc3987#section-6.5) are resolved to their absolute form. + +[relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5) +: A relative IRI reference is an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3) that is relative to some other [IRI](https://tools.ietf.org/html/rfc3987#section-2), typically the [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) of the document. Note that [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property), values of `@type`, and values of [terms](#dfn-term) defined to be *vocabulary relative* are resolved relative to the [vocabulary mapping](#dfn-vocabulary-mapping), not the [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri). + +Terms imported from [RDF 1.1 Concepts and Abstract Syntax](https://www.w3.org/TR/rdf11-concepts/) \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\], [RDF Schema 1.1](https://www.w3.org/TR/rdf-schema/) \[[RDF-SCHEMA](#bib-rdf-schema "RDF Schema 1.1")\], and [Linked Data Design Issues](https://www.w3.org/DesignIssues/LinkedData.html) \[[LINKED-DATA](#bib-linked-data "Linked Data Design Issues")\] + +[base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) +: The [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) is an [IRI](https://tools.ietf.org/html/rfc3987#section-2) established in the [context](#dfn-context), or is based on the [JSON-LD document](#dfn-json-ld-document) location. The [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) is used to turn [relative IRI references](https://tools.ietf.org/html/rfc3987#section-6.5) into [IRIs](https://tools.ietf.org/html/rfc3987#section-2). + +[blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) +: A [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) in a [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) that is neither an [IRI](https://tools.ietf.org/html/rfc3987#section-2), nor a [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal). A [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-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](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). In JSON-LD, a blank node is assigned an identifier starting with the prefix `_:`. + +[blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) +: A [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) is a string that can be used as an identifier for a [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) within the scope of a JSON-LD document. Blank node identifiers begin with `_:`. + +[dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) +: A [dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) representing a collection of [RDF graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) including exactly one [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) and zero or more [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph). + +[datatype IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri) +: A [datatype IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri) is an [IRI](https://tools.ietf.org/html/rfc3987#section-2) identifying a datatype that determines how the lexical form maps to a [literal value](https://www.w3.org/TR/rdf11-concepts/#dfn-literal-value). + +[default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) +: The [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) of a [dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) is an [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) having no [name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name), which may be empty. + +[graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name) +: The [IRI](https://tools.ietf.org/html/rfc3987#section-2) or [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) identifying a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph). + +[language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) +: A [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) consists of a string and a non-empty language tag as defined by \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\]. The [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) must be well-formed according to [section 2.2.9 Classes of Conformance](https://tools.ietf.org/html/bcp47#section-2.2.9) of \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\]. Processors may normalize [language tags](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) to lowercase. + +[Linked Data](https://www.w3.org/DesignIssues/LinkedData.html) +: A set of documents, each containing a representation of a [linked data graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) or [dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset). + +[list](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab) +: A [list](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab) is an ordered sequence of [IRIs](https://tools.ietf.org/html/rfc3987#section-2), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), and [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal). + +[literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) +: An [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) expressed as a value such as a [string](https://infra.spec.whatwg.org/#javascript-string) or [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value). Implicitly or explicitly includes a [datatype IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri) and, if the datatype is `rdf:langString`, an optional [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag). + +[named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) +: A [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) is a [linked data graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) that is identified by an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). + +[node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) +: A [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) in an [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph), either the [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) and [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of at least one [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple). Note that a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) can play both roles ([subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) and [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object)) in a [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph), even in the same [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple). + +[object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) +: An [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) is a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) in a [linked data graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) with at least one incoming edge. + +[property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) +: The name of a directed-arc in a [linked data graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). Every [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) is directional and is labeled with an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier). Whenever possible, a [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) should be labeled with an [IRI](https://tools.ietf.org/html/rfc3987#section-2). + Note + + The use of [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) to label properties is obsolete, and may be removed in a future version of JSON-LD. + + Also, see [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) in \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\]. + +[RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) +: A labeled directed [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph), i.e., a set of [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node) connected by directed-arcs. Also called [linked data graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). + +[resource](https://www.w3.org/TR/rdf11-concepts/#dfn-resource) +: A [resource](https://www.w3.org/TR/rdf11-concepts/#dfn-resource) denoted by an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) or [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) representing something in the world (the \"universe of discourse\"). + +[subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) +: A [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) is a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) in a [linked data graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) with at least one outgoing edge, related to an [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) node through a [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property). + +[triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) +: A component of an [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) including a [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject), [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate), and [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object), which represents a node-arc-node segment of an [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). + +#### JSON-LD Specific Term Definitions[](#json-ld-specific-term-definitions) + +active context +: A [context](#dfn-context) that is used to resolve [terms](#dfn-term) while the processing algorithm is running. + +base direction +: The [base direction](#dfn-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](#dfn-context) using the `@direction` key whose value must be one of the strings `"ltr"`, `"rtl"`, or `null`. See the [Context Definitions](#context-definitions) section of JSON-LD 1.1 for a normative description. + +compact IRI +: A compact IRI has the form of [prefix](#dfn-prefix):*suffix* and is used as a way of expressing an [IRI](https://tools.ietf.org/html/rfc3987#section-2) without needing to define separate [term](#dfn-term) definitions for each IRI contained within a common vocabulary identified by [prefix](#dfn-prefix). + +context +: A set of rules for interpreting a [JSON-LD document](#dfn-json-ld-document) as described in the [The Context](#the-context) section of JSON-LD 1.1, and normatively specified in the [Context Definitions](#context-definitions) section of JSON-LD 1.1. + +default language +: The [default language](#dfn-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](#dfn-context) using the `@language` key whose value must be a [string](https://infra.spec.whatwg.org/#javascript-string) representing a \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\] language code or `null`. See the [Context Definitions](#context-definitions) section of JSON-LD 1.1 for a normative description. + +default object +: A [default object](#dfn-default-object) is a [map](https://infra.spec.whatwg.org/#ordered-map) that has a `@default` key. + +embedded context +: An embedded [context](#dfn-context) is a context which appears as the `@context` [entry](https://infra.spec.whatwg.org/#map-entry) of one of the following: a [node object](#dfn-node-object), a [value object](#dfn-value-object), a [graph object](#dfn-graph-object), a [list object](#dfn-list-object), a [set object](#dfn-set-object), the value of a [nested properties](#dfn-nested-property), or the value of an [expanded term definition](#dfn-expanded-term-definition). Its value may be a [map](https://infra.spec.whatwg.org/#ordered-map) for a [context definition](#dfn-context-definition), as an [IRI](https://tools.ietf.org/html/rfc3987#section-2), or as an [array](https://infra.spec.whatwg.org/#list) combining either of the above. + +expanded term definition +: An expanded term definition is a [term definition](#dfn-term-definition) where the value is a [map](https://infra.spec.whatwg.org/#ordered-map) containing one or more [keyword](#dfn-keyword) keys to define the associated [IRI](https://tools.ietf.org/html/rfc3987#section-2), if this is a reverse property, the type associated with string values, and a container mapping. See the [Expanded Term Definition](#expanded-term-definition) section of JSON-LD 1.1 for a normative description. + +[frame](https://www.w3.org/TR/json-ld11-framing/#dfn-frame) +: A [JSON-LD document](#dfn-json-ld-document), which describes the form for transforming another [JSON-LD document](#dfn-json-ld-document) using matching and embedding rules. A frame document allows additional keywords and certain [map entries](https://infra.spec.whatwg.org/#map-entry) to describe the matching and transforming process. + +[frame object](https://www.w3.org/TR/json-ld11-framing/#dfn-frame-object) +: A frame object is a [map](https://infra.spec.whatwg.org/#ordered-map) element within a [frame](https://www.w3.org/TR/json-ld11-framing/#dfn-frame) which represents a specific portion of the [frame](https://www.w3.org/TR/json-ld11-framing/#dfn-frame) matching either a [node object](#dfn-node-object) or a [value object](#dfn-value-object) in the input. See the [Frame Objects](#frame-objects) section of JSON-LD 1.1 for a normative description. + +graph object +: A [graph object](#dfn-graph-object) represents a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) as the value of a [map entry](https://infra.spec.whatwg.org/#map-entry) within a [node object](#dfn-node-object). When expanded, a graph object must have an `@graph` [entry](https://infra.spec.whatwg.org/#map-entry), and may also have `@id`, and `@index` [entries](https://infra.spec.whatwg.org/#map-entry). A simple graph object is a [graph object](#dfn-graph-object) which does not have an `@id` [entry](https://infra.spec.whatwg.org/#map-entry). Note that [node objects](#dfn-node-object) may have a `@graph` [entry](https://infra.spec.whatwg.org/#map-entry), but are not considered [graph objects](#dfn-graph-object) if they include any other [entries](https://infra.spec.whatwg.org/#map-entry). A top-level object consisting of `@graph` is also not a [graph object](#dfn-graph-object). Note that a [node object](#dfn-node-object) may also represent a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) it it includes other properties. See the [Graph Objects](#graph-objects) section of JSON-LD 1.1 for a normative description. + +id map +: An [id map](#dfn-id-map) is a [map](https://infra.spec.whatwg.org/#ordered-map) value of a [term](#dfn-term) defined with `@container` set to `@id`. The values of the [id map](#dfn-id-map) must be [node objects](#dfn-node-object), and its keys are interpreted as [IRIs](https://tools.ietf.org/html/rfc3987#section-2) representing the `@id` of the associated [node object](#dfn-node-object). If a value in the [id map](#dfn-id-map) contains a key expanding to `@id`, its value must be equivalent to the referencing key in the [id map](#dfn-id-map). See the [Id Maps](#id-maps) section of JSON-LD 1.1 for a normative description. + +implicitly named graph +: A [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) created from the value of a [map entry](https://infra.spec.whatwg.org/#map-entry) having an [expanded term definition](#dfn-expanded-term-definition) where `@container` is set to `@graph`. + +included block +: An [included block](#dfn-included-block) is an [entry](https://infra.spec.whatwg.org/#map-entry) in a [node object](#dfn-node-object) where the key is either `@included` or an alias of `@included` and the value is one or more [node objects](#dfn-node-object). See the [Included Blocks](#included-blocks) section of JSON-LD 1.1 for a normative description. + +index map +: An [index map](#dfn-index-map) is a [map](https://infra.spec.whatwg.org/#ordered-map) value of a [term](#dfn-term) defined with `@container` set to `@index`, whose values must be any of the following types: [string](https://infra.spec.whatwg.org/#javascript-string), [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), `true`, `false`, [null](https://infra.spec.whatwg.org/#nulls), [node object](#dfn-node-object), [value object](#dfn-value-object), [list object](#dfn-list-object), [set object](#dfn-set-object), or an [array](https://infra.spec.whatwg.org/#list) of zero or more of the above possibilities. See the [Index Maps](#index-maps) section in JSON-LD 1.1 for a formal description. + +JSON literal +: A [JSON literal](#dfn-json-literal) is a [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) where the associated [datatype IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri) is `rdf:JSON`. In the [value object](#dfn-value-object) representation, the value of `@type` is `@json`. JSON literals represent values which are valid JSON \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\]. See the [The `rdf:JSON` Datatype](#the-rdf-json-datatype) section in JSON-LD 1.1 for a normative description. + +JSON-LD document +: A [JSON-LD document](#dfn-json-ld-document) is a serialization of an [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset). See the [JSON-LD Grammar](#json-ld-grammar) section in JSON-LD 1.1 for a formal description. + +[JSON-LD internal representation](https://www.w3.org/TR/json-ld11-api/#dfn-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](https://infra.spec.whatwg.org/#list), [maps](https://infra.spec.whatwg.org/#ordered-map), [strings](https://infra.spec.whatwg.org/#javascript-string), [numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), [booleans](https://infra.spec.whatwg.org/#boolean), and [null](https://infra.spec.whatwg.org/#nulls). + +[JSON-LD Processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor) +: A [JSON-LD Processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor) is a system which can perform the algorithms defined in JSON-LD 1.1 Processing Algorithms and API. See the [Conformance](https://www.w3.org/TR/json-ld11-api/#conformance) section in JSON-LD 1.1 API for a formal description. + +JSON-LD value +: A [JSON-LD value](#dfn-json-ld-value) is a [string](https://infra.spec.whatwg.org/#javascript-string), a [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), `true` or `false`, a [typed value](#dfn-typed-value), or a [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string). It represents an [RDF literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal). + +keyword +: A [string](https://infra.spec.whatwg.org/#javascript-string) that is specific to JSON-LD, described in the [Syntax Tokens and Keywords](#syntax-tokens-and-keywords) section of JSON-LD 1.1, and normatively specified in the [Keywords](#keywords) section of JSON-LD 1.1, + +language map +: An [language map](#dfn-language-map) is a [map](https://infra.spec.whatwg.org/#ordered-map) value of a [term](#dfn-term) defined with `@container` set to `@language`, whose keys must be [strings](https://infra.spec.whatwg.org/#javascript-string) representing \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\] language codes and the values must be any of the following types: [null](https://infra.spec.whatwg.org/#nulls), [string](https://infra.spec.whatwg.org/#javascript-string), or an [array](https://infra.spec.whatwg.org/#list) of zero or more of the above possibilities. See the [Language Maps](#language-maps) section of JSON-LD 1.1 for a normative description. + +list object +: A [list object](#dfn-list-object) is a [map](https://infra.spec.whatwg.org/#ordered-map) that has a `@list` key. It may also have an `@index` key, but no other [entries](https://infra.spec.whatwg.org/#map-entry). See the [Lists and Sets](#lists-and-sets) section of JSON-LD 1.1 for a normative description. + +local context +: A [context](#dfn-context) that is specified with a [map](https://infra.spec.whatwg.org/#ordered-map), specified via the `@context` [keyword](#dfn-keyword). + +nested property +: A [nested property](#dfn-nested-property) is a key in a [node object](#dfn-node-object) whose value is a [map](https://infra.spec.whatwg.org/#ordered-map) containing [entries](https://infra.spec.whatwg.org/#map-entry) which are treated as if they were values of the [node object](#dfn-node-object). The [nested property](#dfn-nested-property) itself is semantically meaningless and used only to create a sub-structure within a [node object](#dfn-node-object). See the [Property Nesting](#property-nesting) section of JSON-LD 1.1 for a normative description. + +node object +: A [node object](#dfn-node-object) represents zero or more [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property) of a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) in the [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) serialized by the [JSON-LD document](#dfn-json-ld-document). A [map](https://infra.spec.whatwg.org/#ordered-map) is a [node object](#dfn-node-object) if it exists outside of the JSON-LD [context](#dfn-context) and: + - it does not contain the `@value`, `@list`, or `@set` keywords, or + - it is not the top-most [map](https://infra.spec.whatwg.org/#ordered-map) in the JSON-LD document consisting of no other [entries](https://infra.spec.whatwg.org/#map-entry) than `@graph` and `@context`. + + The [entries](https://infra.spec.whatwg.org/#map-entry) of a [node object](#dfn-node-object) whose keys are not keywords are also called [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property) of the [node object](#dfn-node-object). See the [Node Objects](#node-objects) section of JSON-LD 1.1 for a normative description. + +node reference +: A [node object](#dfn-node-object) used to reference a node having only the `@id` key. + +prefix +: A [prefix](#dfn-prefix) is the first component of a [compact IRI](#dfn-compact-iri) which comes from a [term](#dfn-term) that maps to a string that, when prepended to the suffix of the [compact IRI](#dfn-compact-iri), results in an [IRI](https://tools.ietf.org/html/rfc3987#section-2). + +processing mode +: The [processing mode](#dfn-processing-mode) defines how a [JSON-LD document](#dfn-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](https://infra.spec.whatwg.org/#map-entry) in a [context](#dfn-context), publishers can ensure that processors conformant with [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/) \[[JSON-LD10](#bib-json-ld10 "JSON-LD 1.0")\] will not accidentally process JSON-LD 1.1 documents, possibly creating a different output. The API provides an option for setting the [processing mode](#dfn-processing-mode) to `json-ld-1.0`, which will prevent JSON-LD 1.1 features from being activated, or error if `@version` [entry](https://infra.spec.whatwg.org/#map-entry) in a [context](#dfn-context) is explicitly set to `1.1`. This specification extends [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/) via the `json-ld-1.1` [processing mode](#dfn-processing-mode). + +scoped context +: A [scoped context](#dfn-scoped-context) is part of an [expanded term definition](#dfn-expanded-term-definition) using the `@context` [entry](https://infra.spec.whatwg.org/#map-entry). It has the same form as an [embedded context](#dfn-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](#dfn-set-object) is a [map](https://infra.spec.whatwg.org/#ordered-map) that has an `@set` [entry](https://infra.spec.whatwg.org/#map-entry). It may also have an `@index` key, but no other [entries](https://infra.spec.whatwg.org/#map-entry). See the [Lists and Sets](#lists-and-sets) section of JSON-LD 1.1 for a normative description. + +term +: A [term](#dfn-term) is a short word defined in a [context](#dfn-context) that may be expanded to an [IRI](https://tools.ietf.org/html/rfc3987#section-2). See the [Terms](#terms) section of JSON-LD 1.1 for a normative description. + +term definition +: A term definition is an entry in a [context](#dfn-context), where the key defines a [term](#dfn-term) which may be used within a [map](https://infra.spec.whatwg.org/#ordered-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](https://tools.ietf.org/html/rfc3987#section-2), or a map ([expanded term definition](#dfn-expanded-term-definition)). + +type map +: A [type map](#dfn-type-map) is a [map](https://infra.spec.whatwg.org/#ordered-map) value of a [term](#dfn-term) defined with `@container` set to `@type`, whose keys are interpreted as [IRIs](https://tools.ietf.org/html/rfc3987#section-2) representing the `@type` of the associated [node object](#dfn-node-object); the value must be a [node object](#dfn-node-object), or [array](https://infra.spec.whatwg.org/#list) of node objects. If the value contains a [term](#dfn-term) expanding to `@type`, its values are merged with the map value when expanding. See the [Type Maps](#type-maps) section of JSON-LD 1.1 for a normative description. + +typed value +: A [typed value](#dfn-typed-value) consists of a value, which is a [string](https://infra.spec.whatwg.org/#javascript-string), and a type, which is an [IRI](https://tools.ietf.org/html/rfc3987#section-2). + +value object +: A [value object](#dfn-value-object) is a [map](https://infra.spec.whatwg.org/#ordered-map) that has an `@value` [entry](https://infra.spec.whatwg.org/#map-entry). See the [Value Objects](#value-objects) section of JSON-LD 1.1 for a normative description. + +vocabulary mapping +: The vocabulary mapping is set in the [context](#dfn-context) using the `@vocab` key whose value must be an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [compact IRI](#dfn-compact-iri), a [term](#dfn-term), or `null`. See the [Context Definitions](#context-definitions) section of JSON-LD 1.1 for a normative description. + +### 1.5 Design Goals and Rationale[](#design-goals-and-rationale) + +*This section is non-normative.* + +JSON-LD satisfies the following design goals: + +Simplicity +: No extra processors or software libraries are necessary to use JSON-LD in its most basic form. The language provides developers with a very easy learning curve. Developers not concerned with Linked Data only need to understand JSON, and know to include but ignore the `@context` property, to use the basic functionality in JSON-LD. + +Compatibility +: A JSON-LD document is always a valid JSON document. This ensures that all of the standard JSON libraries work seamlessly with JSON-LD documents. + +Expressiveness +: The syntax serializes labeled directed graphs. This ensures that almost every real world data model can be expressed. + +Terseness +: The JSON-LD syntax is very terse and human readable, requiring as little effort as possible from the developer. + +Zero Edits, most of the time +: JSON-LD ensures a smooth and simple transition from existing JSON-based systems. In many cases, zero edits to the JSON document and the addition of one line to the HTTP response should suffice (see [§ 6.1 Interpreting JSON as JSON-LD](#interpreting-json-as-json-ld)). This allows organizations that have already deployed large JSON-based infrastructure to use JSON-LD\'s features in a way that is not disruptive to their day-to-day operations and is transparent to their current customers. However, there are times where mapping JSON to a graph representation is a complex undertaking. In these instances, rather than extending JSON-LD to support esoteric use cases, we chose not to support the use case. While Zero Edits is a design goal, it is not always possible without adding great complexity to the language. JSON-LD focuses on simplicity when possible. + +Usable as RDF +: JSON-LD is usable by developers as idiomatic JSON, with no need to understand RDF \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\]. JSON-LD is also usable as RDF, so people intending to use JSON-LD with RDF tools will find it can be used like any other RDF syntax. Complete details of how JSON-LD relates to RDF are in section [§ 10. Relationship to RDF](#relationship-to-rdf). + +### 1.6 Data Model Overview[](#data-model-overview) + +*This section is non-normative.* + +Generally speaking, the data model described by a [JSON-LD document](#dfn-json-ld-document) is a labeled, directed [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). The graph contains [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node), which are connected by directed-arcs. A node is either a [resource](https://www.w3.org/TR/rdf11-concepts/#dfn-resource) with [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property), or the data values of those properties including [strings](https://infra.spec.whatwg.org/#javascript-string), [numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), [typed values](#dfn-typed-value) (like dates and times) and [IRIs](https://tools.ietf.org/html/rfc3987#section-2). + +Within a directed graph, nodes are [resources](https://www.w3.org/TR/rdf11-concepts/#dfn-resource), and may be *unnamed*, i.e., not identified by an [IRI](https://tools.ietf.org/html/rfc3987#section-2); which are called [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), and may be identified using a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier). These identifiers may be required to represent a fully connected graph using a tree structure, such as JSON, but otherwise have no intrinsic meaning. Literal values, such as [strings](https://infra.spec.whatwg.org/#javascript-string) and [numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), are also considered [resources](https://www.w3.org/TR/rdf11-concepts/#dfn-resource), and JSON-LD distinguishes between [node objects](#dfn-node-object) and [value objects](#dfn-value-object) to distinguish between the different kinds of [resource](https://www.w3.org/TR/rdf11-concepts/#dfn-resource). + +This simple data model is incredibly flexible and powerful, capable of modeling almost any kind of data. For a deeper explanation of the data model, see section [§ 8. Data Model](#data-model). + +Developers who are familiar with Linked Data technologies will recognize the data model as the RDF Data Model. To dive deeper into how JSON-LD and RDF are related, see section [§ 10. Relationship to RDF](#relationship-to-rdf). + +At the surface level, a [JSON-LD document](#dfn-json-ld-document) is simply [JSON](https://tools.ietf.org/html/rfc8259), detailed in \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\]. For the purpose of describing the core data structures, this is limited to [arrays](https://infra.spec.whatwg.org/#list), [maps](https://infra.spec.whatwg.org/#ordered-map) (the parsed version of a [JSON Object](https://tools.ietf.org/html/rfc8259#section-4)), [strings](https://infra.spec.whatwg.org/#javascript-string), [numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), [booleans](https://infra.spec.whatwg.org/#boolean), and [null](https://infra.spec.whatwg.org/#nulls), called the [JSON-LD internal representation](https://www.w3.org/TR/json-ld11-api/#dfn-internal-representation). This allows surface syntaxes other than JSON to be manipulated using the same algorithms, when the syntax maps to equivalent core data structures. + +Note + +Although not discussed in this specification, parallel work using [YAML Ain't Markup Language (YAML™) Version 1.2](http://yaml.org/spec/1.2/spec.html) \[[YAML](#bib-yaml "YAML Ain’t Markup Language (YAML™) Version 1.2")\] and binary representations such as [Concise Binary Object Representation (CBOR)](https://tools.ietf.org/html/rfc7049) \[[RFC7049](#bib-rfc7049 "Concise Binary Object Representation (CBOR)")\] could be used to map into the [internal representation](https://www.w3.org/TR/json-ld11-api/#dfn-internal-representation), allowing the JSON-LD 1.1 API \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\] to operate as if the source was a JSON document. + +### 1.7 Syntax Tokens and Keywords[](#syntax-tokens-and-keywords) + +*This section is non-normative.* + +JSON-LD specifies a number of syntax tokens and [keywords](#dfn-keyword) that are a core part of the language. A normative description of the [keywords](#dfn-keyword) is given in [§ 9.16 Keywords](#keywords). + +`:` +: The separator for JSON keys and values that use [compact IRIs](#dfn-compact-iri). + +`@base` +: Used to set the [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) against which to resolve those [relative IRI references](https://tools.ietf.org/html/rfc3987#section-6.5) which are otherwise interpreted relative to the document. This keyword is described in [§ 4.1.3 Base IRI](#base-iri). + +`@container` +: Used to set the default container type for a [term](#dfn-term). This keyword is described in the following sections: + - [§ 4.3 Value Ordering](#sets-and-lists), + - [§ 4.6.1 Data Indexing](#data-indexing), + - [§ 4.6.2 Language Indexing](#language-indexing), + - [§ 4.6.3 Node Identifier Indexing](#node-identifier-indexing), + - [§ 4.6.4 Node Type Indexing](#node-type-indexing) + - [§ 4.9 Named Graphs](#named-graphs), + - [§ 4.9.3 Named Graph Indexing](#named-graph-indexing), and + - [§ 4.9.2 Named Graph Data Indexing](#named-graph-data-indexing) + +`@context` +: Used to define the short-hand names that are used throughout a JSON-LD document. These short-hand names are called [terms](#dfn-term) and help developers to express specific identifiers in a compact manner. The `@context` keyword is described in detail in [§ 3.1 The Context](#the-context). + +`@direction` +: Used to set the [base direction](#dfn-base-direction) of a [JSON-LD value](#dfn-json-ld-value), which are not [typed values](#dfn-typed-value) (e.g. [strings](https://infra.spec.whatwg.org/#javascript-string), or [language-tagged strings](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string)). This keyword is described in [§ 4.2.4 String Internationalization](#string-internationalization). + +`@graph` +: Used to express a [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). This keyword is described in [§ 4.9 Named Graphs](#named-graphs). + +`@id` +: Used to uniquely identify [node objects](#dfn-node-object) that are being described in the document with [IRIs](https://tools.ietf.org/html/rfc3987#section-2) or [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier). This keyword is described in [§ 3.3 Node Identifiers](#node-identifiers). A [node reference](#dfn-node-reference) is a [node object](#dfn-node-object) containing only the `@id` property, which may represent a reference to a [node object](#dfn-node-object) found elsewhere in the document. + +`@import` +: Used in a [context definition](#dfn-context-definition) to load an external context within which the containing [context definition](#dfn-context-definition) is merged. This can be useful to add JSON-LD 1.1 features to JSON-LD 1.0 contexts. + +`@included` +: Used in a top-level [node object](#dfn-node-object) to define an [included block](#dfn-included-block), for including secondary [node objects](#dfn-node-object) within another [node object](#dfn-node-object). + +`@index` +: Used to specify that a container is used to index information and that processing should continue deeper into a JSON data structure. This keyword is described in [§ 4.6.1 Data Indexing](#data-indexing). + +`@json` +: Used as the `@type` value of a [JSON literal](#dfn-json-literal). This keyword is described in [§ 4.2.2 JSON Literals](#json-literals). + +`@language` +: Used to specify the language for a particular string value or the default language of a JSON-LD document. This keyword is described in [§ 4.2.4 String Internationalization](#string-internationalization). + +`@list` +: Used to express an ordered set of data. This keyword is described in [§ 4.3.1 Lists](#lists). + +`@nest` +: Used to define a [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) of a [node object](#dfn-node-object) that groups together properties of that node, but is not an edge in the graph. + +`@none` +: Used as an index value in an [index map](#dfn-index-map), [id map](#dfn-id-map), [language map](#dfn-language-map), [type map](#dfn-type-map), or elsewhere where a [map](https://infra.spec.whatwg.org/#ordered-map) is used to index into other values, when the indexed node does not have the feature being indexed. + +`@prefix` +: With the value `true`, allows this [term](#dfn-term) to be used to construct a [compact IRI](#dfn-compact-iri) when compacting. With the value `false` prevents the term from being used to construct a [compact IRI](#dfn-compact-iri). Also determines if the term will be considered when expanding [compact IRIs](#dfn-compact-iri). + +`@propagate` +: Used in a [context definition](#dfn-context-definition) to change the scope of that context. By default, it is `true`, meaning that contexts propagate across [node objects](#dfn-node-object) (other than for [type-scoped contexts](#dfn-type-scoped-context), which default to `false`). Setting this to `false` causes term definitions created within that context to be removed when entering a new [node object](#dfn-node-object). + +`@protected` +: Used to prevent [term definitions](#dfn-term-definition) of a context to be overridden by other contexts. This keyword is described in [§ 4.1.11 Protected Term Definitions](#protected-term-definitions). + +`@reverse` +: Used to express reverse properties. This keyword is described in [§ 4.8 Reverse Properties](#reverse-properties). + +`@set` +: Used to express an unordered set of data and to ensure that values are always represented as arrays. This keyword is described in [§ 4.3.2 Sets](#sets). + +`@type` +: Used to set the type of a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) or the datatype of a [typed value](#dfn-typed-value). This keyword is described further in [§ 3.5 Specifying the Type](#specifying-the-type) and [§ 4.2.1 Typed Values](#typed-values). + Note + + The use of `@type` to define a type for both [node objects](#dfn-node-object) and [value objects](#dfn-value-object) addresses the basic need to type data, be it a literal value or a more complicated resource. Experts may find the overloaded use of the `@type` keyword for both purposes concerning, but should note that Web developer usage of this feature over multiple years has not resulted in its misuse due to the far less frequent use of `@type` to express typed literal values. + +`@value` +: Used to specify the data that is associated with a particular [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) in the graph. This keyword is described in [§ 4.2.4 String Internationalization](#string-internationalization) and [§ 4.2.1 Typed Values](#typed-values). + +`@version` +: Used in a [context definition](#dfn-context-definition) to set the [processing mode](#dfn-processing-mode). New features since [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/) \[[JSON-LD10](#bib-json-ld10 "JSON-LD 1.0")\] described in this specification are not available when [processing mode](#dfn-processing-mode) has been explicitly set to `json-ld-1.0`. + Note + + Within a [context definition](#dfn-context-definition) `@version` takes the specific value `1.1`, not `"json-ld-1.1"`, as a JSON-LD 1.0 processor may accept a string value for `@version`, but will reject a numeric value. + + 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](https://semver.org/). + +`@vocab` +: Used to expand properties and values in `@type` with a common prefix [IRI](https://tools.ietf.org/html/rfc3987#section-2). This keyword is described in [§ 4.1.2 Default Vocabulary](#default-vocabulary). + +All keys, [keywords](#dfn-keyword), and values in JSON-LD are case-sensitive. + +## 2. Conformance[](#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*, *RECOMMENDED*, *SHOULD*, and *SHOULD NOT* in this document are to be interpreted as described in [BCP 14](https://tools.ietf.org/html/bcp14) \[[RFC2119](#bib-rfc2119 "Key words for use in RFCs to Indicate Requirement Levels")\] \[[RFC8174](#bib-rfc8174 "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words")\] when, and only when, they appear in all capitals, as shown here. + +A [JSON-LD document](#dfn-json-ld-document) complies with this specification if it follows the normative statements in appendix [§ 9. JSON-LD Grammar](#json-ld-grammar). JSON documents can be interpreted as JSON-LD by following the normative statements in [§ 6.1 Interpreting JSON as JSON-LD](#interpreting-json-as-json-ld). For convenience, normative statements for documents are often phrased as statements on the properties of the document. + +This specification makes use of the following namespace prefixes: + + Prefix IRI + --------- --------------------------------------------- + dc11 http://purl.org/dc/elements/1.1/ + dcterms http://purl.org/dc/terms/ + cred https://w3id.org/credentials# + foaf http://xmlns.com/foaf/0.1/ + geojson https://purl.org/geojson/vocab# + prov http://www.w3.org/ns/prov# + i18n https://www.w3.org/ns/i18n# + rdf http://www.w3.org/1999/02/22-rdf-syntax-ns# + schema http://schema.org/ + skos http://www.w3.org/2004/02/skos/core# + xsd http://www.w3.org/2001/XMLSchema# + +These are used within this document as part of a [compact IRI](#dfn-compact-iri) as a shorthand for the resulting [IRI](https://tools.ietf.org/html/rfc3987#section-2), such as `dcterms:title` used to represent `http://purl.org/dc/terms/title`. + +## 3. Basic Concepts[](#basic-concepts) + +*This section is non-normative.* + +JSON \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\] is a lightweight, language-independent data interchange format. It is easy to parse and easy to generate. However, it is difficult to integrate JSON from different sources as the data may contain keys that conflict with other data sources. Furthermore, JSON has no built-in support for hyperlinks, which are a fundamental building block on the Web. Let\'s start by looking at an example that we will be using for the rest of this section: + +[Example 2](#example-2-sample-json-document): Sample JSON document + +``` {aria-busy="false"} +{ + "name": "Manu Sporny", + "homepage": "http://manu.sporny.org/", + "image": "http://manu.sporny.org/images/manu.png" +} +``` + +It\'s obvious to humans that the data is about a person whose `name` is \"Manu Sporny\" and that the `homepage` property contains the URL of that person\'s homepage. A machine doesn\'t have such an intuitive understanding and sometimes, even for humans, it is difficult to resolve ambiguities in such representations. This problem can be solved by using unambiguous identifiers to denote the different concepts instead of tokens such as \"name\", \"homepage\", etc. + +Linked Data, and the Web in general, uses [IRIs](https://tools.ietf.org/html/rfc3987#section-2) ([Internationalized Resource Identifiers](https://tools.ietf.org/html/rfc3987#section-2) as described in \[[RFC3987](#bib-rfc3987 "Internationalized Resource Identifiers (IRIs)")\]) for unambiguous identification. The idea is to use [IRIs](https://tools.ietf.org/html/rfc3987#section-2) to assign unambiguous identifiers to data that may be of use to other developers. It is useful for [terms](#dfn-term), like `name` and `homepage`, to expand to [IRIs](https://tools.ietf.org/html/rfc3987#section-2) so that developers don\'t accidentally step on each other\'s terms. Furthermore, developers and machines are able to use this [IRI](https://tools.ietf.org/html/rfc3987#section-2) (by using a web browser, for instance) to go to the term and get a definition of what the term means. This process is known as [IRI](https://tools.ietf.org/html/rfc3987#section-2) dereferencing. + +Leveraging the popular [schema.org vocabulary](http://schema.org/), the example above could be unambiguously expressed as follows: + +[Example 3](#example-3-sample-json-ld-document-using-full-iris-instead-of-terms): Sample JSON-LD document using full IRIs instead of terms + +Expanded (Input) + +Statements + +Turtle (Result) + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22http%3A%2F%2Fschema.org%2Fname%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22http%3A%2F%2Fschema.org%2Furl%22%3A%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2F%22%0A%20%20%20%20%0A%20%20%7D%2C%0A%20%20%22http%3A%2F%2Fschema.org%2Fimage%22%3A%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fimages%2Fmanu.png%22%0A%20%20%7D%0A%7D) + +``` {.expanded .input .selected .nohighlight} +{ + "http://schema.org/name": "Manu Sporny", + "http://schema.org/url": { + "@id": "http://manu.sporny.org/" + ↑ The '@id' keyword means 'This value is an identifier that is an IRI' + }, + "http://schema.org/image": { + "@id": "http://manu.sporny.org/images/manu.png" + } +} +``` + + Subject Property Value + --------- -------------- ---------------------------------------- + \_:b0 schema:image http://manu.sporny.org/images/manu.png + \_:b0 schema:name Manu Sporny + \_:b0 schema:url http://manu.sporny.org/ + +``` {.turtle content-type="text/turtle" result-for="Sample JSON-LD document using full IRIs instead of terms-expanded" to-rdf="" aria-busy="false"} +@prefix schema: . +@prefix xsd: . + + [ + schema:image ; + schema:name "Manu Sporny"; + schema:url + ] . +``` + +In the example above, every property is unambiguously identified by an [IRI](https://tools.ietf.org/html/rfc3987#section-2) and all values representing [IRIs](https://tools.ietf.org/html/rfc3987#section-2) are explicitly marked as such by the `@id` [keyword](#dfn-keyword). While this is a valid JSON-LD document that is very specific about its data, the document is also overly verbose and difficult to work with for human developers. To address this issue, JSON-LD introduces the notion of a [context](#dfn-context) as described in the next section. + +This section only covers the most basic features of JSON-LD. More advanced features, including [typed values](#dfn-typed-value), [indexed values](#indexed-values), and [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), can be found in [§ 4. Advanced Concepts](#advanced-concepts). + +### 3.1 The Context[](#the-context) + +*This section is non-normative.* + +When two people communicate with one another, the conversation takes place in a shared environment, typically called \"the context of the conversation\". This shared context allows the individuals to use shortcut terms, like the first name of a mutual friend, to communicate more quickly but without losing accuracy. A context in JSON-LD works in the same way. It allows two applications to use shortcut terms to communicate with one another more efficiently, but without losing accuracy. + +Simply speaking, a [context](#dfn-context) is used to map [terms](#dfn-term) to [IRIs](https://tools.ietf.org/html/rfc3987#section-2). [Terms](#dfn-term) are case sensitive and most valid [strings](https://infra.spec.whatwg.org/#javascript-string) that are not reserved JSON-LD [keywords](#dfn-keyword) can be used as a [term](#dfn-term). Exceptions are the empty string `""` and strings that have the form of a keyword (i.e., starting with `"@"` followed exclusively by one or more *ALPHA* characters (see \[[RFC5234](#bib-rfc5234 "Augmented BNF for Syntax Specifications: ABNF")\])), which must not be used as terms. Strings that have the form of an [IRI](https://tools.ietf.org/html/rfc3987#section-2) (e.g., containing a `":"`) should not be used as terms. + +For the sample document in the previous section, a [context](#dfn-context) would look something like this: + +[Example 4](#example-4-context-for-the-sample-document-in-the-previous-section): Context for the sample document in the previous section + +``` {.context .nohighlight context-for="Sample JSON document"} +{ + "@context": { + "name": "http://schema.org/name", + ↑ This means that 'name' is shorthand for 'http://schema.org/name' + "image": { + "@id": "http://schema.org/image", + ↑ This means that 'image' is shorthand for 'http://schema.org/image' + "@type": "@id" + ↑ This means that a string value associated with 'image' + should be interpreted as an identifier that is an IRI + }, + "homepage": { + "@id": "http://schema.org/url", + ↑ This means that 'homepage' is shorthand for 'http://schema.org/url' + "@type": "@id" + ↑ This means that a string value associated with 'homepage' + should be interpreted as an identifier that is an IRI + } + } +} +``` + +As the [context](#dfn-context) above shows, the value of a [term definition](#dfn-term-definition) can either be a simple string, mapping the [term](#dfn-term) to an [IRI](https://tools.ietf.org/html/rfc3987#section-2), or a [map](https://infra.spec.whatwg.org/#ordered-map). + +A [context](#dfn-context) is introduced using an [entry](https://infra.spec.whatwg.org/#map-entry) with the key `@context` and may appear within a [node object](#dfn-node-object) or a [value object](#dfn-value-object). + +When an [entry](https://infra.spec.whatwg.org/#map-entry) with a [term](#dfn-term) key has a [map](https://infra.spec.whatwg.org/#ordered-map) value, the [map](https://infra.spec.whatwg.org/#ordered-map) is called an [expanded term definition](#dfn-expanded-term-definition). The example above specifies that the values of `image` and `homepage`, if they are strings, are to be interpreted as [IRIs](https://tools.ietf.org/html/rfc3987#section-2). [Expanded term definitions](#dfn-expanded-term-definition) also allow terms to be used for [index maps](#data-indexing) and to specify whether [array](https://infra.spec.whatwg.org/#list) values are to be interpreted as [sets](#sets) or [lists](#lists). [Expanded term definitions](#dfn-expanded-term-definition) may be defined using [IRIs](https://tools.ietf.org/html/rfc3987#section-2) or [compact IRIs](#dfn-compact-iri) as keys, which is mainly used to associate type or language information with an [IRIs](https://tools.ietf.org/html/rfc3987#section-2) or [compact IRI](#dfn-compact-iri). + +[Contexts](#dfn-context) can either be directly embedded into the document (an [embedded context](#dfn-embedded-context)) or be referenced using a URL. Assuming the context document in the previous example can be retrieved at `https://json-ld.org/contexts/person.jsonld`, it can be referenced by adding a single line and allows a JSON-LD document to be expressed much more concisely as shown in the example below: + +[Example 5](#example-5-referencing-a-json-ld-context): Referencing a JSON-LD context + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%22https%3A%2F%2Fjson-ld.org%2Fcontexts%2Fperson.jsonld%22%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22homepage%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2F%22%2C%0A%20%20%22image%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fimages%2Fmanu.png%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": "https://json-ld.org/contexts/person.jsonld", + "name": "Manu Sporny", + "homepage": "http://manu.sporny.org/", + "image": "http://manu.sporny.org/images/manu.png" +} +``` + +``` {.expanded .result .nohighlight result-for="Referencing a JSON-LD context-compacted"} +[{ + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/homepage": [{ "@id": "http://manu.sporny.org/" }], + "http://xmlns.com/foaf/0.1/img": [{ "@id": "http://manu.sporny.org/images/manu.png" }] +}] +``` + + Subject Property Value + --------- --------------- ---------------------------------------- + \_:b0 foaf:name Manu Sporny + \_:b0 foaf:homepage http://manu.sporny.org/ + \_:b0 foaf:img http://manu.sporny.org/images/manu.png + +``` {.turtle content-type="text/turtle" result-for="Referencing a JSON-LD context-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . +@prefix xsd: . + + [ + foaf:name "Manu Sporny"; + foaf:homepage ; + foaf:img + ] . +``` + +The referenced context not only specifies how the terms map to [IRIs](https://tools.ietf.org/html/rfc3987#section-2) in the Schema.org vocabulary but also specifies that string values associated with the `homepage` and `image` property can be interpreted as an [IRI](https://tools.ietf.org/html/rfc3987#section-2) (`"@type": "@id"`, see [§ 3.2 IRIs](#iris) for more details). This information allows developers to re-use each other\'s data without having to agree to how their data will interoperate on a site-by-site basis. External JSON-LD context documents may contain extra information located outside of the `@context` key, such as documentation about the [terms](#dfn-term) declared in the document. Information contained outside of the `@context` value is ignored when the document is used as an external JSON-LD context document. + +A remote context may also be referenced using a relative URL, which is resolved relative to the location of the document containing the reference. For example, if a document were located at `http://example.org/document.jsonld` and contained a relative reference to `context.jsonld`, the referenced context document would be found relative at `http://example.org/context.jsonld`. + +[Example 6](#example-6-loading-a-relative-context): Loading a relative context + +``` {.nohighlight .changed ignore=""} +{ + "@context": "context.jsonld", + "name": "Manu Sporny", + "homepage": "http://manu.sporny.org/", + "image": "http://manu.sporny.org/images/manu.png" +} +``` + +Note + +Resolution of relative references to context URLs also applies to remote context documents, as they may themselves contain references to other contexts. + +JSON documents can be interpreted as JSON-LD without having to be modified by referencing a [context](#dfn-context) via an [HTTP Link Header](https://tools.ietf.org/html/rfc8288#section-3) as described in [§ 6.1 Interpreting JSON as JSON-LD](#interpreting-json-as-json-ld). It is also possible to apply a custom context using the JSON-LD 1.1 API \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\]. + +In [JSON-LD documents](#dfn-json-ld-document), [contexts](#dfn-context) may also be specified inline. This has the advantage that documents can be processed even in the absence of a connection to the Web. Ultimately, this is a modeling decision and different use cases may require different handling. See [Security Considerations](#iana-security) in [§ C. IANA Considerations](#iana-considerations) for a discussion on using remote contexts. + +[Example 7](#example-7-in-line-context-definition): In-line context definition + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fschema.org%2Fname%22%2C%0A%20%20%20%20%22image%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fschema.org%2Fimage%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22%40id%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22homepage%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fschema.org%2Furl%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22%40id%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22homepage%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2F%22%2C%0A%20%20%22image%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fimages%2Fmanu.png%22%0A%7D) + +``` {.compacted .input .selected .input .nohighlight} +{ + "@context": { + "name": "http://schema.org/name", + "image": { + "@id": "http://schema.org/image", + "@type": "@id" + }, + "homepage": { + "@id": "http://schema.org/url", + "@type": "@id" + } + }, + "name": "Manu Sporny", + "homepage": "http://manu.sporny.org/", + "image": "http://manu.sporny.org/images/manu.png" +} +``` + +``` {.expanded .result .nohighlight result-for="In-line context definition-compacted"} +[{ + "http://schema.org/name": [{"@value": "Manu Sporny"}], + "http://schema.org/url": [{ "@id": "http://manu.sporny.org/" }], + "http://schema.org/image": [{ "@id": "http://manu.sporny.org/images/manu.png" }] +}] +``` + + Subject Property Value + --------- -------------- ---------------------------------------- + \_:b0 schema:image http://manu.sporny.org/images/manu.png + \_:b0 schema:name Manu Sporny + \_:b0 schema:url http://manu.sporny.org/ + +``` {.turtle content-type="text/turtle" result-for="In-line context definition-expanded" to-rdf="" aria-busy="false"} +@prefix schema: . +@prefix xsd: . + + [ + schema:image ; + schema:name "Manu Sporny"; + schema:url + ] . +``` + +This section only covers the most basic features of the JSON-LD Context. The Context can also be used to help interpret other more complex JSON data structures, such as [indexed values](#indexed-values), [ordered values](#sets-and-lists), and [nested properties](#nested-properties). More advanced features related to the JSON-LD Context are covered in [§ 4. Advanced Concepts](#advanced-concepts). + +### 3.2 IRIs[](#iris) + +*This section is non-normative.* + +[IRIs](https://tools.ietf.org/html/rfc3987#section-2) ([Internationalized Resource Identifiers](https://tools.ietf.org/html/rfc3987#section-2) \[[RFC3987](#bib-rfc3987 "Internationalized Resource Identifiers (IRIs)")\]) are fundamental to Linked Data as that is how most [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node) and [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property) are identified. In JSON-LD, IRIs may be represented as an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3). An [IRI](https://tools.ietf.org/html/rfc3987#section-2) is defined in \[[RFC3987](#bib-rfc3987 "Internationalized Resource Identifiers (IRIs)")\] as containing a *scheme* along with *path* and optional *query* and *fragment* segments. A [relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5) is an IRI that is relative to some other [IRI](https://tools.ietf.org/html/rfc3987#section-2). In JSON-LD, with exceptions that are as described below, all [relative IRI references](https://tools.ietf.org/html/rfc3987#section-6.5) are resolved relative to the [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri). + +Note + +As noted in [§ 1.1 How to Read this Document](#how-to-read-this-document), IRIs can often be confused with URLs ([Uniform Resource Locators](https://www.w3.org/TR/ld-glossary/#uniform-resource-locator)), the primary distinction is that a URL *locates* a resource on the web, an IRI *identifies* a resource. While it is a good practice for resource identifiers to be dereferenceable, sometimes this is not practical. In particular, note the \[[URN](#bib-urn "URN Syntax")\] scheme for Uniform Resource Names, such as [UUID](https://tools.ietf.org/html/rfc4122). An example UUID is `urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6`. + +Note + +[Properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property), values of `@type`, and values of [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property) with a [term definition](#dfn-term-definition) that defines them as being relative to the [vocabulary mapping](#dfn-vocabulary-mapping), may have the form of a [relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5), but are resolved using the [vocabulary mapping](#dfn-vocabulary-mapping), and not the [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri). + +A [string](https://infra.spec.whatwg.org/#javascript-string) is interpreted as an [IRI](https://tools.ietf.org/html/rfc3987#section-2) when it is the value of a [map entry](https://infra.spec.whatwg.org/#map-entry) with the key `@id`: + +[Example 8](#example-8-values-of-id-are-interpreted-as-iri): Values of \@id are interpreted as IRI + +``` nohighlight +{ + ... + "homepage": { "@id": "http://example.com/" } + ... +} +``` + +Values that are interpreted as [IRIs](https://tools.ietf.org/html/rfc3987#section-2), can also be expressed as [relative IRI references](https://tools.ietf.org/html/rfc3987#section-6.5). For example, assuming that the following document is located at `http://example.com/about/`, the [relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5) `../` would expand to `http://example.com/` (for more information on where [relative IRI references](https://tools.ietf.org/html/rfc3987#section-6.5) can be used, please refer to section [§ 9. JSON-LD Grammar](#json-ld-grammar)). + +[Example 9](#example-9-iris-can-be-relative): IRIs can be relative + +``` nohighlight +{ + ... + "homepage": { "@id": "../" } + ... +} +``` + +[IRIs](https://tools.ietf.org/html/rfc3987#section-2) can be expressed directly in the key position like so: + +[Example 10](#example-10-iri-as-a-key): IRI as a key + +``` nohighlight +{ + ... + "http://schema.org/name": "Manu Sporny", + ... +} +``` + +In the example above, the key `http://schema.org/name` is interpreted as an [IRI](https://tools.ietf.org/html/rfc3987#section-2). + +Term-to-IRI expansion occurs if the key matches a [term](#dfn-term) defined within the [active context](#dfn-active-context): + +[Example 11](#example-11-term-expansion-from-context-definition): Term expansion from context definition + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fschema.org%2Fname%22%0A%20%20%7D%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22status%22%3A%20%22trollin'%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "name": "http://schema.org/name" + }, + "name": "Manu Sporny", + "status": "trollin'" +} +``` + +``` {.expanded .result .nohighlight result-for="Term expansion from context definition-compacted"} +[{ + "http://schema.org/name": [{"@value": "Manu Sporny"}] +}] +``` + + Subject Property Value + --------- ------------- ------------- + \_:b0 schema:name Manu Sporny + +``` {.turtle content-type="text/turtle" result-for="Term expansion from context definition-expanded" to-rdf="" aria-busy="false"} +@prefix schema: . +@prefix xsd: . + + [ + schema:name "Manu Sporny" + ] . +``` + +JSON keys that do not expand to an [IRI](https://tools.ietf.org/html/rfc3987#section-2), such as `status` in the example above, are not Linked Data and thus ignored when processed. + +If type [coercion](#dfn-coercion) rules are specified in the `@context` for a particular [term](#dfn-term) or property IRI, an IRI is generated: + +[Example 12](#example-12-type-coercion): Type coercion + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%0A%20%20%20%20%22homepage%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fschema.org%2Furl%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22%40id%22%0A%20%20%20%20%7D%0A%20%20%20%20%0A%20%20%7D%2C%0A%20%20%0A%20%20%22homepage%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2F%22%0A%20%20%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + ... + "homepage": { + "@id": "http://schema.org/url", + "@type": "@id" + } + ... + }, + ... + "homepage": "http://manu.sporny.org/" + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Type coercion-compacted"} +[{ + "http://schema.org/url": [{"@id": "http://manu.sporny.org/"}] +}] +``` + + Subject Property Value + --------- ------------ ------------------------- + \_:b0 schema:url http://manu.sporny.org/ + +``` {.turtle content-type="text/turtle" result-for="Type coercion-expanded" to-rdf="" aria-busy="false"} +@prefix schema: . +@prefix xsd: . + + [ + schema:url + ] . +``` + +In the example above, since the value `http://manu.sporny.org/` is expressed as a JSON [string](https://infra.spec.whatwg.org/#javascript-string), the type [coercion](#dfn-coercion) rules will transform the value into an IRI when processing the data. See [§ 4.2.3 Type Coercion](#type-coercion) for more details about this feature. + +In summary, [IRIs](https://tools.ietf.org/html/rfc3987#section-2) can be expressed in a variety of different ways in JSON-LD: + +1. [Map entries](https://infra.spec.whatwg.org/#map-entry) that have a key mapping to a [term](#dfn-term) in the [active context](#dfn-active-context) expand to an [IRI](https://tools.ietf.org/html/rfc3987#section-2) (only applies outside of the [context definition](#dfn-context-definition)). +2. An [IRI](https://tools.ietf.org/html/rfc3987#section-2) is generated for the [string](https://infra.spec.whatwg.org/#javascript-string) value specified using `@id` or `@type`. +3. An [IRI](https://tools.ietf.org/html/rfc3987#section-2) is generated for the [string](https://infra.spec.whatwg.org/#javascript-string) value of any key for which there are [coercion](#dfn-coercion) rules that contain an `@type` key that is set to a value of `@id` or `@vocab`. + +This section only covers the most basic features associated with IRIs in JSON-LD. More advanced features related to IRIs are covered in section [§ 4. Advanced Concepts](#advanced-concepts). + +### 3.3 Node Identifiers[](#node-identifiers) + +*This section is non-normative.* + +To be able to externally reference [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node) in an [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph), it is important that [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node) have an identifier. [IRIs](https://tools.ietf.org/html/rfc3987#section-2) are a fundamental concept of Linked Data, for [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node) to be truly linked, dereferencing the identifier should result in a representation of that [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node). This may allow an application to retrieve further information about a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node). + +In JSON-LD, a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) is identified using the `@id` [keyword](#dfn-keyword): + +[Example 13](#example-13-identifying-a-node): Identifying a node + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fschema.org%2Fname%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fme.markus-lanthaler.com%2F%22%2C%0A%20%20%22name%22%3A%20%22Markus%20Lanthaler%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + ... + "name": "http://schema.org/name" + }, + "@id": "http://me.markus-lanthaler.com/", + "name": "Markus Lanthaler", + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Identifying a node-compacted"} +[{ + "@id": "http://me.markus-lanthaler.com/", + "http://schema.org/name": [{"@value": "Markus Lanthaler"}] +}] +``` + + Subject Property Value + --------------------------------- ------------- ------------------ + http://me.markus-lanthaler.com/ schema:name Markus Lanthaler + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Identifying a node-expanded" to-rdf=""} +@prefix schema: . +@prefix xsd: . + + schema:name "Markus Lanthaler" . +``` + +The example above contains a [node object](#dfn-node-object) identified by the IRI `http://me.markus-lanthaler.com/`. + +This section only covers the most basic features associated with node identifiers in JSON-LD. More advanced features related to node identifiers are covered in section [§ 4. Advanced Concepts](#advanced-concepts). + +### 3.4 Uses of JSON Objects[](#uses-of-json-objects) + +*This section is non-normative.* + +As a syntax, JSON has only a limited number of syntactic elements: + +- [Numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), which describe literal numeric values, +- [Strings](https://infra.spec.whatwg.org/#javascript-string), which may describe literal string values, or be used as the keys in a [JSON object](https://tools.ietf.org/html/rfc8259#section-4). +- [Boolean](https://infra.spec.whatwg.org/#boolean) `true` and `false`, which describe literal boolean values, +- `null`, which describes the absence of a value, +- [Arrays](https://infra.spec.whatwg.org/#list), which describe an ordered set of values of any type, and +- [JSON objects](https://tools.ietf.org/html/rfc8259#section-4), which provide a set of [map entries](https://infra.spec.whatwg.org/#map-entry), relating keys with values. + +The JSON-LD data model allows for a richer set of resources, based on the RDF data model. The data model is described more fully in [§ 8. Data Model](#data-model). JSON-LD uses JSON objects to describe various resources, along with the relationships between these resources: + +[Node objects](#dfn-node-object) +: Node objects are used to define nodes in the [linked data graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) which may have both incoming and outgoing edges. Node objects are principle structure for defining [resources](https://www.w3.org/TR/rdf11-concepts/#dfn-resource) having [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property). See [§ 9.2 Node Objects](#node-objects) for the normative definition. + +[Value objects](#dfn-value-object) +: Value objects are used for describing literal nodes in a [linked data graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) which may have only incoming edges. In JSON, some literal nodes may be described without the use of a [JSON object](https://tools.ietf.org/html/rfc8259#section-4) (e.g., [numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), [strings](https://infra.spec.whatwg.org/#javascript-string), and [boolean](https://infra.spec.whatwg.org/#boolean) values), but in the [expanded form](https://www.w3.org/TR/json-ld11-api/#dfn-expanded), all literal nodes are described using [value objects](#dfn-value-object). See [§ 4.2 Describing Values](#describing-values) for more information, and [§ 9.5 Value Objects](#value-objects) for the normative definition. + +[List Objects](#dfn-list-object) and [Set objects](#dfn-set-object) +: [List Objects](#dfn-list-object) are a special kind of JSON-LD [maps](https://infra.spec.whatwg.org/#ordered-map), distinct from [node objects](#dfn-node-object) and [value objects](#dfn-value-object), used to express ordered values by wrapping an [array](https://infra.spec.whatwg.org/#list) in a [map](https://infra.spec.whatwg.org/#ordered-map) under the key `@list`. [Set Objects](#dfn-set-object) exist for uniformity, and are equivalent to the array value of the `@set` key. See [§ 4.3.1 Lists](#lists) and [§ 4.3.2 Sets](#sets) for more detail. + +Map Objects +: JSON-LD uses various forms of [maps](https://infra.spec.whatwg.org/#ordered-map) as ways to more easily access values of a [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property). + + [Language Maps](#dfn-language-map) + : Allows multiple values differing in their associated language to be indexed by [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag). See [§ 4.6.2 Language Indexing](#language-indexing) for more information, and [§ 9.8 Language Maps](#language-maps) for the normative definition. + + [Index Maps](#dfn-index-map) + : Allows multiple values ([node objects](#dfn-node-object) or [value objects](#dfn-value-object)) to be indexed by an associated `@index`. See [§ 4.6.1 Data Indexing](#data-indexing) for more information, and [§ 9.9 Index Maps](#index-maps) for the normative definition. + + [Id Maps](#dfn-id-map) + : Allows multiple [node objects](#dfn-node-object) to be indexed by an associated `@id`. See [§ 4.6.3 Node Identifier Indexing](#node-identifier-indexing) for more information, and [§ 9.11 Id Maps](#id-maps) for the normative definition. + + [Type Maps](#dfn-type-map) + : Allows multiple [node objects](#dfn-node-object) to be indexed by an associated `@type`. See [§ 4.6.4 Node Type Indexing](#node-type-indexing) for more information, and [§ 9.12 Type Maps](#type-maps) for the normative definition. + + [Named Graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) Indexing + : Allows multiple [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) to be indexed by an associated [graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name). See [§ 4.9.3 Named Graph Indexing](#named-graph-indexing) for more information. + +[Graph objects](#dfn-graph-object) +: A [graph object](#dfn-graph-object) is much like a [node object](#dfn-node-object), except that it defines a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph). See [§ 4.9 Named Graphs](#named-graphs) for more information, and [§ 9.4 Graph Objects](#graph-objects) for the normative definition. A [node object](#dfn-node-object) may also describe a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), in addition to other properties defined on the node. The notable difference is that a [graph object](#dfn-graph-object) only describes a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph). + +[Context Definitions](#dfn-context-definition) +: A Context Definition uses the [JSON object](https://tools.ietf.org/html/rfc8259#section-4) form, but is not itself data in a [linked data graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). A Context Definition also may contain expanded term definitions, which are also represented using JSON objects. See [§ 3.1 The Context](#the-context), [§ 4.1 Advanced Context Usage](#advanced-context-usage) for more information, and [§ 9.15 Context Definitions](#context-definitions) for the normative definition. + +### 3.5 Specifying the Type[](#specifying-the-type) + +*This section is non-normative.* + +In Linked Data, it is common to specify the type of a graph node; in many cases, this can be inferred based on the properties used within a given [node object](#dfn-node-object), or the property for which a node is a value. For example, in the *schema.org* vocabulary, the *givenName* property is associated with a *Person*. Therefore, one may reason that if a [node object](#dfn-node-object) contains the property *givenName*, that the type is a *Person*; making this explicit with `@type` helps to clarify the association. + +The type of a particular [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) can be specified using the `@type` [keyword](#dfn-keyword). In Linked Data, types are uniquely identified with an [IRI](https://tools.ietf.org/html/rfc3987#section-2). + +[Example 14](#example-14-specifying-the-type-for-a-node): Specifying the type for a node + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%0A%20%20%20%20%22givenName%22%3A%20%22http%3A%2F%2Fschema.org%2FgivenName%22%2C%0A%20%20%20%20%22familyName%22%3A%20%22http%3A%2F%2Fschema.org%2FfamilyName%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fme.markus-lanthaler.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%22http%3A%2F%2Fschema.org%2FPerson%22%2C%0A%20%20%22givenName%22%3A%20%22Markus%22%2C%0A%20%20%22familyName%22%3A%20%22Lanthaler%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + ... + "givenName": "http://schema.org/givenName", + "familyName": "http://schema.org/familyName" + }, + "@id": "http://me.markus-lanthaler.com/", + "@type": "http://schema.org/Person", + "givenName": "Markus", + "familyName": "Lanthaler", + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Specifying the type for a node-compacted"} +[{ + "@id": "http://me.markus-lanthaler.com/", + "@type": ["http://schema.org/Person"], + "http://schema.org/givenName": [{"@value": "Markus"}], + "http://schema.org/familyName": [{"@value": "Lanthaler"}] +}] +``` + + Subject Property Value + --------------------------------- ------------------- --------------- + http://me.markus-lanthaler.com/ rdf:type schema:Person + http://me.markus-lanthaler.com/ schema:givenName Markus + http://me.markus-lanthaler.com/ schema:familyName Lanthaler + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Specifying the type for a node-expanded" to-rdf=""} +@prefix schema: . +@prefix xsd: . + + a schema:Person; + schema:givenName "Markus"; + schema:familyName "Lanthaler" . +``` + +A node can be assigned more than one type by using an [array](https://infra.spec.whatwg.org/#list): + +[Example 15](#example-15-specifying-multiple-types-for-a-node): Specifying multiple types for a node + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fme.markus-lanthaler.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%5B%0A%20%20%20%20%20%22http%3A%2F%2Fschema.org%2FPerson%22%2C%0A%20%20%20%20%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2FPerson%22%0A%20%20%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + ... + "@id": "http://me.markus-lanthaler.com/", + "@type": [ + "http://schema.org/Person", + "http://xmlns.com/foaf/0.1/Person" + ], + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Specifying multiple types for a node-compacted"} +[{ + "@id": "http://me.markus-lanthaler.com/", + "@type": ["http://schema.org/Person", "http://xmlns.com/foaf/0.1/Person"] +}] +``` + + Subject Property Value + --------------------------------- ---------- --------------- + http://me.markus-lanthaler.com/ rdf:type schema:Person + http://me.markus-lanthaler.com/ rdf:type foaf:Person + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Specifying multiple types for a node-expanded" to-rdf=""} +@prefix schema: . +@prefix foaf: . +@prefix xsd: . + + a schema:Person, foaf:Person. +``` + +The value of a `@type` key may also be a [term](#dfn-term) defined in the [active context](#dfn-active-context): + +[Example 16](#example-16-using-a-term-to-specify-the-type): Using a term to specify the type + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%0A%20%20%20%20%22Person%22%3A%20%22http%3A%2F%2Fschema.org%2FPerson%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fplaces%23BrewEats%22%2C%0A%20%20%22%40type%22%3A%20%22Person%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + ... + "Person": "http://schema.org/Person" + }, + "@id": "http://example.org/places#BrewEats", + "@type": "Person", + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Using a term to specify the type-compacted"} +[{ + "@id": "http://example.org/places#BrewEats", + "@type": ["http://schema.org/Person"] +}] +``` + + Subject Property Value + ------------------------------------ ---------- --------------- + http://example.org/places#BrewEats rdf:type schema:Person + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Using a term to specify the type-expanded" to-rdf=""} +@prefix schema: . +@prefix xsd: . + + a schema:Person. +``` + +In addition to setting the type of nodes, `@type` can also be used to set the type of a value to create a [typed value](#dfn-typed-value). This use of `@type` is similar to that used to define the type of a [node object](#dfn-node-object), but value objects are restricted to having just a single type. The use of `@type` to create typed values is discussed more fully in [§ 4.2.1 Typed Values](#typed-values). + +Typed values can also be defined implicitly, by specifying `@type` in an expanded term definition. This is covered more fully in [§ 4.2.3 Type Coercion](#type-coercion). + +## 4. Advanced Concepts[](#advanced-concepts) + +*This section is non-normative.* + +JSON-LD has a number of features that provide functionality above and beyond the core functionality described above. JSON can be used to express data using such structures, and the features described in this section can be used to interpret a variety of different JSON structures as Linked Data. A JSON-LD processor will make use of provided and embedded contexts to interpret property values in a number of different idiomatic ways. + +Describing values + +: One pattern in JSON is for the value of a property to be a string. Often times, this string actually represents some other typed value, for example an IRI, a date, or a string in some specific language. See [§ 4.2 Describing Values](#describing-values) for details on how to describe such value typing. + +Value ordering + +: In JSON, a property with an array value implies an implicit order; arrays in JSON-LD do not convey any ordering of the contained elements by default, unless defined using embedded structures or through a context definition. See [§ 4.3 Value Ordering](#sets-and-lists) for a further discussion. + +Property nesting + +: Another JSON idiom often found in APIs is to use an intermediate object to group together related properties of an object; in JSON-LD these are referred to as [nested properties](#dfn-nested-property) and are described in [§ 4.4 Nested Properties](#nested-properties). + +Referencing objects + +: Linked Data is all about describing the relationships between different resources. Sometimes these relationships are between resources defined in different documents described on the web, sometimes the resources are described within the same document. + + [Example 17](#example-17-referencing-objects-on-the-web): Referencing Objects on the Web + + Compacted (Input) + Expanded (Result) + Statements + Turtle + [Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%2C%0A%20%20%20%20%22knows%22%3A%20%7B%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22knows%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%0A%7D) + + ``` {.compacted .input .selected .nohighlight} + { + "@context": { + "@vocab": "http://xmlns.com/foaf/0.1/", + "knows": {"@type": "@id"} + }, + "@id": "http://manu.sporny.org/about#manu", + "@type": "Person", + "name": "Manu Sporny", + "knows": "https://greggkellogg.net/foaf#me" + } + ``` + + ``` {.expanded .result .nohighlight result-for="Referencing Objects on the Web-compacted"} + [{ + "@id": "http://manu.sporny.org/about#manu", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/knows": [{"@id": "https://greggkellogg.net/foaf#me"}] + }] + ``` + + Subject Property Value + ----------------------------------- ------------ ---------------------------------- + http://manu.sporny.org/about#manu rdf:type foaf:Person + http://manu.sporny.org/about#manu foaf:name Manu Sporny + http://manu.sporny.org/about#manu foaf:knows https://greggkellogg.net/foaf#me + + ``` {.turtle .nohighlight content-type="text/turtle" result-for="Referencing Objects on the Web-expanded" to-rdf=""} + @prefix foaf: . + @prefix xsd: . + + a foaf:Person; + foaf:name "Manu Sporny"; + foaf:knows . + ``` + + In this case, a document residing at `http://manu.sporny.org/about` may contain the example above, and reference another document at `https://greggkellogg.net/foaf` which could include a similar representation. + + A common idiom found in JSON usage is objects being specified as the value of other objects, called object [embedding](#dfn-embedding) in JSON-LD; for example, a friend specified as an object value of a *Person*: + + [Example 18](#example-18-embedding-objects): Embedding Objects + + Compacted (Input) + Expanded (Result) + Statements + Turtle + [Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22knows%22%3A%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%0A%20%20%7D%0A%7D) + + ``` {.compacted .input .selected .nohighlight title="Embedding Objects"} + { + "@context": { + "@vocab": "http://xmlns.com/foaf/0.1/" + }, + "@id": "http://manu.sporny.org/about#manu", + "@type": "Person", + "name": "Manu Sporny", + "knows": { + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg" + } + } + ``` + + ``` {.expanded .result .nohighlight result-for="Embedding Objects-compacted"} + [{ + "@id": "http://manu.sporny.org/about#manu", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/knows": [{ + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Gregg Kellogg"}] + }] + }] + ``` + + Subject Property Value + ----------------------------------- ------------ ---------------------------------- + http://manu.sporny.org/about#manu rdf:type foaf:Person + http://manu.sporny.org/about#manu foaf:name Manu Sporny + https://greggkellogg.net/foaf#me rdf:type foaf:Person + https://greggkellogg.net/foaf#me foaf:name Gregg Kellogg + http://manu.sporny.org/about#manu foaf:knows https://greggkellogg.net/foaf#me + + ``` {.turtle .nohighlight content-type="text/turtle" result-for="Embedding Objects-expanded" to-rdf=""} + @prefix foaf: . + @prefix xsd: . + + a foaf:Person; + foaf:name "Manu Sporny"; + foaf:knows . + a foaf:Person; + foaf:name "Gregg Kellogg" . + ``` + + See [§ 4.5 Embedding](#embedding) details these relationships. + +Indexed values + +: Another common idiom in JSON is to use an intermediate object to represent property values via indexing. JSON-LD allows data to be indexed in a number of different ways, as detailed in [§ 4.6 Indexed Values](#indexed-values). + +Reverse Properties + +: JSON-LD serializes directed [graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). That means that every [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) points from a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) to another [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) or [value](#dfn-json-ld-value). However, in some cases, it is desirable to serialize in the reverse direction, as detailed in [§ 4.8 Reverse Properties](#reverse-properties). + +The following sections describe such advanced functionality in more detail. + +### 4.1 Advanced Context Usage[](#advanced-context-usage) + +*This section is non-normative.* + +Section [§ 3.1 The Context](#the-context) introduced the basics of what makes JSON-LD work. This section expands on the basic principles of the [context](#dfn-context) and demonstrates how more advanced use cases can be achieved using JSON-LD. + +In general, contexts may be used any time a [map](https://infra.spec.whatwg.org/#ordered-map) is defined. The only time that one cannot express a context is as a direct child of another context definition (other than as part of an [expanded term definition](#dfn-expanded-term-definition)). For example, a [JSON-LD document](#dfn-json-ld-document) may have the form of an [array](https://infra.spec.whatwg.org/#list) composed of one or more [node objects](#dfn-node-object), which use a context definition in each top-level [node object](#dfn-node-object): + +[Example 19](#example-19-using-multiple-contexts): Using multiple contexts + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%5B%0A%20%20%7B%0A%20%20%20%20%22%40context%22%3A%20%22https%3A%2F%2Fjson-ld.org%2Fcontexts%2Fperson.jsonld%22%2C%0A%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%20%20%22homepage%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2F%22%2C%0A%20%20%20%20%22depiction%22%3A%20%22http%3A%2F%2Ftwitter.com%2Faccount%2Fprofile_image%2Fmanusporny%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40context%22%3A%20%22https%3A%2F%2Fjson-ld.org%2Fcontexts%2Fplace.jsonld%22%2C%0A%20%20%20%20%22name%22%3A%20%22The%20Empire%20State%20Building%22%2C%0A%20%20%20%20%22description%22%3A%20%22The%20Empire%20State%20Building%20is%20a%20102-story%20landmark%20in%20New%20York%20City.%22%2C%0A%20%20%20%20%22geo%22%3A%20%7B%0A%20%20%20%20%20%20%22latitude%22%3A%20%2240.75%22%2C%0A%20%20%20%20%20%20%22longitude%22%3A%20%2273.98%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%5D) + +``` {.compacted .input .selected .nohighlight} +[ + { + "@context": "https://json-ld.org/contexts/person.jsonld", + "name": "Manu Sporny", + "homepage": "http://manu.sporny.org/", + "depiction": "http://twitter.com/account/profile_image/manusporny" + }, { + "@context": "https://json-ld.org/contexts/place.jsonld", + "name": "The Empire State Building", + "description": "The Empire State Building is a 102-story landmark in New York City.", + "geo": { + "latitude": "40.75", + "longitude": "73.98" + } + } +] +``` + +``` {.expanded .result .nohighlight result-for="Using multiple contexts-compacted"} +[{ + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/homepage": [{"@id": "http://manu.sporny.org/"}], + "http://xmlns.com/foaf/0.1/depiction": [{"@id": "http://twitter.com/account/profile_image/manusporny"}] +}, { + "http://purl.org/dc/terms/title": [{"@value": "The Empire State Building"}], + "http://purl.org/dc/terms/description": [{ + "@value": "The Empire State Building is a 102-story landmark in New York City." + }], + "http://schema.org/geo": [{ + "http://www.w3.org/2003/01/geo/wgs84_pos#lat": [{ + "@type": "http://www.w3.org/2001/XMLSchema#decimal", + "@value": "40.75" + }], + "http://www.w3.org/2003/01/geo/wgs84_pos#long": [{ + "@type": "http://www.w3.org/2001/XMLSchema#decimal", + "@value": "73.98" + }] + }] +}] +``` + + Subject Property Value Value Type + --------- --------------------- --------------------------------------------------------------------- ------------- + \_:b0 foaf:name Manu Sporny + \_:b0 foaf:homepage http://manu.sporny.org/ + \_:b0 foaf:depiction http://twitter.com/account/profile_image/manusporny + \_:b1 dcterms:title The Empire State Building + \_:b1 dcterms:description The Empire State Building is a 102-story landmark in New York City. + \_:b2 geo:lat 40.75 xsd:decimal + \_:b2 geo:long 73.98 xsd:decimal + \_:b1 schema:geo \_:b2 + +``` {.turtle content-type="text/turtle" result-for="Using multiple contexts-expanded" to-rdf="" aria-busy="false"} +@prefix dcterms: . +@prefix foaf: . +@prefix geo: . +@prefix schema: . +@prefix xsd: . + +[ + foaf:name "Manu Sporny"; + foaf:homepage ; + foaf:depiction +] . + +[ + dcterms:title "The Empire State Building"; + dcterms:description "The Empire State Building is a 102-story landmark in New York City."; + schema:geo [ + geo:lat 40.75; + geo:long 73.98 + ] +] . +``` + +The outer array is standard for a document in [expanded document form](#dfn-expanded-document-form) and [flattened document form](#dfn-flattened-document-form), and may be necessary when describing a disconnected graph, where nodes may not reference each other. In such cases, using a top-level [map](https://infra.spec.whatwg.org/#ordered-map) with a `@graph` property can be useful for saving the repetition of `@context`. See [§ 4.5 Embedding](#embedding) for more. + +[Example 20](#example-20-describing-disconnected-nodes-with-graph): Describing disconnected nodes with \@graph + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%5B%0A%20%20%20%20%22https%3A%2F%2Fjson-ld.org%2Fcontexts%2Fperson.jsonld%22%2C%0A%20%20%20%20%22https%3A%2F%2Fjson-ld.org%2Fcontexts%2Fplace.jsonld%22%2C%0A%20%20%20%20%7B%22title%22%3A%20%22http%3A%2F%2Fpurl.org%2Fdc%2Fterms%2Ftitle%22%7D%0A%20%20%5D%2C%0A%20%20%22%40graph%22%3A%20%5B%7B%0A%20%20%20%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fname%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%20%20%22homepage%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2F%22%2C%0A%20%20%20%20%22depiction%22%3A%20%22http%3A%2F%2Ftwitter.com%2Faccount%2Fprofile_image%2Fmanusporny%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22title%22%3A%20%22The%20Empire%20State%20Building%22%2C%0A%20%20%20%20%22description%22%3A%20%22The%20Empire%20State%20Building%20is%20a%20102-story%20landmark%20in%20New%20York%20City.%22%2C%0A%20%20%20%20%22geo%22%3A%20%7B%0A%20%20%20%20%20%20%22latitude%22%3A%20%2240.75%22%2C%0A%20%20%20%20%20%20%22longitude%22%3A%20%2273.98%22%0A%20%20%20%20%7D%0A%20%20%7D%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": [ + "https://json-ld.org/contexts/person.jsonld", + "https://json-ld.org/contexts/place.jsonld", + {"title": "http://purl.org/dc/terms/title"} + ], + "@graph": [{ + "http://xmlns.com/foaf/0.1/name": "Manu Sporny", + "homepage": "http://manu.sporny.org/", + "depiction": "http://twitter.com/account/profile_image/manusporny" + }, { + "title": "The Empire State Building", + "description": "The Empire State Building is a 102-story landmark in New York City.", + "geo": { + "latitude": "40.75", + "longitude": "73.98" + } + }] +} +``` + +``` {.expanded .result .nohighlight result-for="Describing disconnected nodes with @graph-compacted"} +[{ + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/homepage": [{"@id": "http://manu.sporny.org/"}], + "http://xmlns.com/foaf/0.1/depiction": [{"@id": "http://twitter.com/account/profile_image/manusporny"}] +}, { + "http://purl.org/dc/terms/title": [{"@value": "The Empire State Building"}], + "http://purl.org/dc/terms/description": [{ + "@value": "The Empire State Building is a 102-story landmark in New York City." + }], + "http://schema.org/geo": [{ + "http://www.w3.org/2003/01/geo/wgs84_pos#lat": [{ + "@type": "http://www.w3.org/2001/XMLSchema#decimal", + "@value": "40.75" + }], + "http://www.w3.org/2003/01/geo/wgs84_pos#long": [{ + "@type": "http://www.w3.org/2001/XMLSchema#decimal", + "@value": "73.98" + }] + }] +}] +``` + + Subject Property Value Value Type + --------- --------------------- --------------------------------------------------------------------- ------------- + \_:b0 foaf:name Manu Sporny + \_:b0 foaf:homepage http://manu.sporny.org/ + \_:b0 foaf:depiction http://twitter.com/account/profile_image/manusporny + \_:b1 dcterms:title The Empire State Building + \_:b1 dcterms:description The Empire State Building is a 102-story landmark in New York City. + \_:b2 geo:lat 40.75 xsd:decimal + \_:b2 geo:long 73.98 xsd:decimal + \_:b1 schema:geo \_:b2 + +``` {.turtle content-type="text/turtle" result-for="Describing disconnected nodes with @graph-expanded" to-rdf="" aria-busy="false"} +@prefix dcterms: . +@prefix foaf: . +@prefix geo: . +@prefix schema: . +@prefix xsd: . + +[ + foaf:name "Manu Sporny"; + foaf:homepage ; + foaf:depiction +] . + +[ + dcterms:title "The Empire State Building"; + dcterms:description "The Empire State Building is a 102-story landmark in New York City."; + schema:geo [ + geo:lat 40.75; + geo:long 73.98 + ] +] . +``` + +Duplicate context [terms](#dfn-term) are overridden using a most-recently-defined-wins mechanism. + +[Example 21](#example-21-embedded-contexts-within-node-objects): Embedded contexts within node objects + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fexample.com%2Fperson%23name%22%2C%0A%20%20%20%20%22details%22%3A%20%22http%3A%2F%2Fexample.com%2Fperson%23details%22%0A%20%20%7D%2C%0A%20%20%22name%22%3A%20%22Markus%20Lanthaler%22%2C%0A%20%20%0A%20%20%22details%22%3A%20%7B%0A%20%20%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fexample.com%2Forganization%23name%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22name%22%3A%20%22Graz%20University%20of%20Technology%22%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "name": "http://example.com/person#name", + "details": "http://example.com/person#details" + }, + "name": "Markus Lanthaler", + ... + "details": { + "@context": { + "name": "http://example.com/organization#name" + }, + "name": "Graz University of Technology" + } +} +``` + +``` {.expanded .result .nohighlight result-for="Embedded contexts within node objects-compacted"} +[{ + "http://example.com/person#details": [{ + "http://example.com/organization#name": [{ + "@value": "Graz University of Technology" + }] + }], + "http://example.com/person#name": [{"@value": "Markus Lanthaler"}] +}] +``` + + Subject Property Value + --------- -------------------------------------- ------------------------------- + \_:b1 http://example.com/organization#name Graz University of Technology + \_:b0 http://example.com/person#details \_:b1 + \_:b0 http://example.com/person#name Markus Lanthaler + +``` {.turtle content-type="text/turtle" result-for="Embedded contexts within node objects-expanded" to-rdf="" aria-busy="false"} +@prefix person: . +@prefix org: . + +[ + person:name "Markus Lanthaler"; + person:details [org:name "Graz University of Technology"] +] . +``` + +In the example above, the `name` [term](#dfn-term) is overridden in the more deeply nested `details` structure, which uses its own [embedded context](#dfn-embedded-context). Note that this is rarely a good authoring practice and is typically used when working with legacy applications that depend on a specific structure of the [map](https://infra.spec.whatwg.org/#ordered-map). If a [term](#dfn-term) is redefined within a context, all previous rules associated with the previous definition are removed. If a [term](#dfn-term) is redefined to `null`, the [term](#dfn-term) is effectively removed from the list of [terms](#dfn-term) defined in the [active context](#dfn-active-context). + +Multiple contexts may be combined using an [array](https://infra.spec.whatwg.org/#list), which is processed in order. The set of contexts defined within a specific [map](https://infra.spec.whatwg.org/#ordered-map) are referred to as [local contexts](#dfn-local-context). The [active context](#dfn-active-context) refers to the accumulation of [local contexts](#dfn-local-context) that are in scope at a specific point within the document. Setting a [local context](#dfn-local-context) to `null` effectively resets the [active context](#dfn-active-context) to an empty context, without [term definitions](#dfn-term-definition), [default language](#dfn-default-language), or other things defined within previous contexts. The following example specifies an external context and then layers an [embedded context](#dfn-embedded-context) on top of the external context: + +In JSON-LD 1.1, there are other mechanisms for introducing contexts, including scoped contexts and imported contexts, and there are new ways of protecting term definitions, so there are cases where the last defined inline context is not necessarily one which defines the scope of terms. See [§ 4.1.8 Scoped Contexts](#scoped-contexts), [§ 4.1.9 Context Propagation](#context-propagation), [§ 4.1.10 Imported Contexts](#imported-contexts), and [§ 4.1.11 Protected Term Definitions](#protected-term-definitions) for further information. + +[Example 22](#example-22-combining-external-and-local-contexts): Combining external and local contexts + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%5B%0A%20%20%20%20%22https%3A%2F%2Fjson-ld.org%2Fcontexts%2Fperson.jsonld%22%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22pic%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fdepiction%22%2C%0A%20%20%20%20%20%20%20%20%22%40type%22%3A%20%22%40id%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%5D%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22homepage%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2F%22%2C%0A%20%20%22pic%22%3A%20%22http%3A%2F%2Ftwitter.com%2Faccount%2Fprofile_image%2Fmanusporny%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": [ + "https://json-ld.org/contexts/person.jsonld", + { + "pic": { + "@id": "http://xmlns.com/foaf/0.1/depiction", + "@type": "@id" + } + } + ], + "name": "Manu Sporny", + "homepage": "http://manu.sporny.org/", + "pic": "http://twitter.com/account/profile_image/manusporny" +} +``` + +``` {.expanded .result .nohighlight result-for="Combining external and local contexts-compacted"} +[{ + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/homepage": [{"@id": "http://manu.sporny.org/"}], + "http://xmlns.com/foaf/0.1/depiction": [{ + "@id": "http://twitter.com/account/profile_image/manusporny" + }] +}] +``` + + Subject Property Value Value Type + --------- ---------------- ----------------------------------------------------- ------------------------------------------------------ + \_:b0 foaf:name Manu Sporny + \_:b0 foaf:homepage http://manu.sporny.org/ [IRI](https://tools.ietf.org/html/rfc3987#section-2) + \_:b0 foaf:depiction http://twitter.com/account/profile_image/manusporny IRI + +``` {.turtle content-type="text/turtle" result-for="Combining external and local contexts-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . + +[ + foaf:name "Manu Sporny"; + foaf:homepage ; + foaf:depiction +] . +``` + +Note + +When possible, the [context](#dfn-context) definition should be put at the top of a JSON-LD document. This makes the document easier to read and might make streaming parsers more efficient. Documents that do not have the [context](#dfn-context) at the top are still conformant JSON-LD. + +Note + +To avoid forward-compatibility issues, [terms](#dfn-term) starting with an `@` character followed exclusively by one or more *ALPHA* characters (see \[[RFC5234](#bib-rfc5234 "Augmented BNF for Syntax Specifications: ABNF")\]) are to be avoided as they might be used as [keyword](#dfn-keyword) in future versions of JSON-LD. Terms starting with an `@` character that are not [JSON-LD 1.1 keywords](#dfn-keyword) are treated as any other term, i.e., they are ignored unless mapped to an [IRI](https://tools.ietf.org/html/rfc3987#section-2). Furthermore, the use of empty [terms](#dfn-term) (`""`) is not allowed as not all programming languages are able to handle empty JSON keys. + +#### 4.1.1 JSON-LD 1.1 Processing Mode[](#json-ld-1-1-processing-mode) + +*This section is non-normative.* + +New features defined in JSON-LD 1.1 are available unless the [processing mode](#dfn-processing-mode) is set to `json-ld-1.0`. This may be set through an API option. The [processing mode](#dfn-processing-mode) may be explicitly set to `json-ld-1.1` using the `@version` [entry](https://infra.spec.whatwg.org/#map-entry) in a [context](#dfn-context) set to the value `1.1` as a [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), or through an API option. Explicitly setting the [processing mode](#dfn-processing-mode) to `json-ld-1.1` will prohibit JSON-LD 1.0 processors from incorrectly processing a JSON-LD 1.1 document. + +[Example 23](#example-23-setting-version-in-context): Setting \@version in context + +``` nohighlight +{ + "@context": { + "@version": 1.1, + ... + }, + ... +} +``` + +The first `context` encountered when processing a document which contains `@version` determines the `processing mode`, unless it is defined explicitly through an API option. This means that if `"@version": 1.1` is encountered after processing a context without `@version`, the former will be interpreted as having had `"@version": 1.1` defined within it. + +Note + +Setting the [processing mode](#dfn-processing-mode) explicitly to `json-ld-1.1` is *RECOMMENDED* to prevent a [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/) processor from incorrectly processing a JSON-LD 1.1 document and producing different results. + +#### 4.1.2 Default Vocabulary[](#default-vocabulary) + +*This section is non-normative.* + +At times, all properties and types may come from the same vocabulary. JSON-LD\'s `@vocab` keyword allows an author to set a common prefix which is used as the [vocabulary mapping](#dfn-vocabulary-mapping) and is used for all properties and types that do not match a [term](#dfn-term) and are neither an [IRI](https://tools.ietf.org/html/rfc3987#section-2) nor a [compact IRI](#dfn-compact-iri) (i.e., they do not contain a colon). + +[Example 24](#example-24-using-a-default-vocabulary): Using a default vocabulary + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%2F%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fplaces%23BrewEats%22%2C%0A%20%20%22%40type%22%3A%20%22Restaurant%22%2C%0A%20%20%22name%22%3A%20%22Brew%20Eats%22%0A%20%20%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@vocab": "http://example.com/vocab/" + }, + "@id": "http://example.org/places#BrewEats", + "@type": "Restaurant", + "name": "Brew Eats" + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Using a default vocabulary-compacted"} +[{ + "@id": "http://example.org/places#BrewEats", + "@type": ["http://example.com/vocab/Restaurant"], + "http://example.com/vocab/name": [{"@value": "Brew Eats"}] +}] +``` + + Subject Property Value + ------------------------------------ ------------------------------- ------------------------------------- + http://example.org/places#BrewEats rdf:type http://example.com/vocab/Restaurant + http://example.org/places#BrewEats http://example.com/vocab/name Brew Eats + +``` {.turtle content-type="text/turtle" result-for="Using a default vocabulary-expanded" to-rdf="" aria-busy="false"} +@prefix ex: . + + a ex:Restaurant; + ex:name "Brew Eats" . +``` + +If `@vocab` is used but certain keys in an [map](https://infra.spec.whatwg.org/#ordered-map) should not be expanded using the vocabulary [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [term](#dfn-term) can be explicitly set to [null](https://infra.spec.whatwg.org/#nulls) in the [context](#dfn-context). For instance, in the example below the `databaseId` [entry](https://infra.spec.whatwg.org/#map-entry) would not expand to an [IRI](https://tools.ietf.org/html/rfc3987#section-2) causing the property to be dropped when expanding. + +[Example 25](#example-25-using-the-null-keyword-to-ignore-data): Using the null keyword to ignore data + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%2F%22%2C%0A%20%20%20%20%20%22databaseId%22%3A%20null%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fplaces%23BrewEats%22%2C%0A%20%20%22%40type%22%3A%20%22Restaurant%22%2C%0A%20%20%22name%22%3A%20%22Brew%20Eats%22%2C%0A%20%20%22databaseId%22%3A%20%2223987520%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@vocab": "http://example.com/vocab/", + "databaseId": null + }, + "@id": "http://example.org/places#BrewEats", + "@type": "Restaurant", + "name": "Brew Eats", + "databaseId": "23987520" +} +``` + +``` {.expanded .result .nohighlight result-for="Using the null keyword to ignore data-compacted"} +[{ + "@id": "http://example.org/places#BrewEats", + "@type": ["http://example.com/vocab/Restaurant"], + "http://example.com/vocab/name": [{"@value": "Brew Eats"}] +}] +``` + + Subject Property Value + ------------------------------------ ------------------------------- ------------------------------------- + http://example.org/places#BrewEats rdf:type http://example.com/vocab/Restaurant + http://example.org/places#BrewEats http://example.com/vocab/name Brew Eats + +``` {.turtle content-type="text/turtle" result-for="Using the null keyword to ignore data-expanded" to-rdf="" aria-busy="false"} +@prefix ex: . + + a ex:Restaurant; + ex:name "Brew Eats" . +``` + +Since JSON-LD 1.1, the [vocabulary mapping](#dfn-vocabulary-mapping) in a [local context](#dfn-local-context) can be set to a [relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5), which is concatenated to any [vocabulary mapping](#dfn-vocabulary-mapping) in the [active context](#dfn-active-context) (see [§ 4.1.4 Using the Document Base for the Default Vocabulary](#document-relative-vocabulary-mapping) for how this applies if there is no [vocabulary mapping](#dfn-vocabulary-mapping) in the [active context](#dfn-active-context)). + +The following example illustrates the affect of expanding a property using a [relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5), which is shown in the Expanded (Result) tab below. + +[Example 26](#example-26-using-a-default-vocabulary-relative-to-a-previous-default-vocabulary): Using a default vocabulary relative to a previous default vocabulary + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%5B%7B%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fexample.com%2F%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22%40vocab%22%3A%20%22vocab%2F%22%0A%20%20%7D%5D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fplaces%23BrewEats%22%2C%0A%20%20%22%40type%22%3A%20%22Restaurant%22%2C%0A%20%20%22name%22%3A%20%22Brew%20Eats%22%0A%20%20%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": [{ + "@vocab": "http://example.com/" + }, { + "@version": 1.1, + "@vocab": "vocab/" + }], + "@id": "http://example.org/places#BrewEats", + "@type": "Restaurant", + "name": "Brew Eats" + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Using a default vocabulary relative to a previous default vocabulary-compacted"} +[{ + "@id": "http://example.org/places#BrewEats", + "@type": ["http://example.com/vocab/Restaurant"], + "http://example.com/vocab/name": [{"@value": "Brew Eats"}] +}] +``` + + Subject Property Value + ------------------------------------ ------------------------------- ------------------------------------- + http://example.org/places#BrewEats rdf:type http://example.com/vocab/Restaurant + http://example.org/places#BrewEats http://example.com/vocab/name Brew Eats + +``` {.turtle content-type="text/turtle" result-for="Using a default vocabulary relative to a previous default vocabulary-expanded" to-rdf="" aria-busy="false"} +@prefix ex: . + + a ex:Restaurant; + ex:name "Brew Eats" . +``` + +Note + +The grammar for `@vocab`, as defined in [§ 9.15 Context Definitions](#context-definitions) allows the value to be a [term](#dfn-term) or [compact IRI](#dfn-compact-iri). Note that terms used in the value of `@vocab` must be in scope at the time the context is introduced, otherwise there would be a circular dependency between `@vocab` and other terms defined in the same context. + +#### 4.1.3 Base IRI[](#base-iri) + +*This section is non-normative.* + +JSON-LD allows [IRIs](https://tools.ietf.org/html/rfc3987#section-2) to be specified in a relative form which is resolved against the document base according [section 5.1 Establishing a Base URI](https://tools.ietf.org/html/rfc3986#section-5.1) of \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]. The [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) may be explicitly set with a [context](#dfn-context) using the `@base` keyword. + +For example, if a JSON-LD document was retrieved from `http://example.com/document.jsonld`, [relative IRI references](https://tools.ietf.org/html/rfc3987#section-6.5) would resolve against that [IRI](https://tools.ietf.org/html/rfc3987#section-2): + +[Example 27](#example-27-use-a-relative-iri-reference-as-node-identifier): Use a relative IRI reference as node identifier + +``` nohighlight +{ + "@context": { + "label": "http://www.w3.org/2000/01/rdf-schema#label" + }, + "@id": "", + "label": "Just a simple document" +} +``` + +This document uses an empty `@id`, which resolves to the document base. However, if the document is moved to a different location, the [IRI](https://tools.ietf.org/html/rfc3987#section-2) would change. To prevent this without having to use an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [context](#dfn-context) may define an `@base` mapping, to overwrite the [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) for the document. + +[Example 28](#example-28-setting-the-document-base-in-a-document): Setting the document base in a document + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40base%22%3A%20%22http%3A%2F%2Fexample.com%2Fdocument.jsonld%22%2C%0A%20%20%20%20%22label%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2000%2F01%2Frdf-schema%23label%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22%22%2C%0A%20%20%22label%22%3A%20%22Just%20a%20simple%20document%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@base": "http://example.com/document.jsonld", + "label": "http://www.w3.org/2000/01/rdf-schema#label" + }, + "@id": "", + "label": "Just a simple document" +} +``` + +``` {.expanded .result .nohighlight result-for="Setting the document base in a document-compacted"} +[{ + "@id": "http://example.com/document.jsonld", + "http://www.w3.org/2000/01/rdf-schema#label": [{"@value": "Just a simple document"}] +}] +``` + + Subject Property Value + ------------------------------------ ------------ ------------------------ + http://example.com/document.jsonld rdfs:label Just a simple document + +``` {.turtle content-type="text/turtle" result-for="Setting the document base in a document-expanded" to-rdf="" aria-busy="false"} +@base . +@prefix rdfs: . + +<> rdfs:label "Just a simple document" . +``` + +Setting `@base` to [null](https://infra.spec.whatwg.org/#nulls) will prevent [relative IRI references](https://tools.ietf.org/html/rfc3987#section-6.5) from being expanded to [IRIs](https://tools.ietf.org/html/rfc3987#section-2). + +Please note that the `@base` will be ignored if used in external contexts. + +#### 4.1.4 Using the Document Base for the Default Vocabulary[](#document-relative-vocabulary-mapping) + +*This section is non-normative.* + +In some cases, vocabulary terms are defined directly within the document itself, rather than in an external vocabulary. Since JSON-LD 1.1, the [vocabulary mapping](#dfn-vocabulary-mapping) in a [local context](#dfn-local-context) can be set to a [relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5), which is, if there is no vocabulary mapping in scope, resolved against the [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri). This causes terms which are expanded relative to the vocabulary, such as the keys of [node objects](#dfn-node-object), to be based on the [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) to create [IRIs](https://tools.ietf.org/html/rfc3987#section-2). + +[Example 29](#example-29-using-as-the-vocabulary-mapping): Using \"#\" as the vocabulary mapping + +``` {.input .nohighlight base="http://example/document"} +{ + "@context": { + "@version": 1.1, + "@base": "http://example/document", + "@vocab": "#" + }, + "@id": "http://example.org/places#BrewEats", + "@type": "Restaurant", + "name": "Brew Eats" + ... +} +``` + +If this document were located at `http://example/document`, it would expand as follows: + +[Example 30](#example-30-using-as-the-vocabulary-mapping-expanded): Using \"#\" as the vocabulary mapping (expanded) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%5B%7B%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fplaces%23BrewEats%22%2C%0A%20%20%22%40type%22%3A%20%5B%22http%3A%2F%2Fexample%2Fdocument%23Restaurant%22%5D%2C%0A%20%20%22http%3A%2F%2Fexample%2Fdocument%23name%22%3A%20%5B%7B%22%40value%22%3A%20%22Brew%20Eats%22%7D%5D%0A%7D%5D) + +``` {.expanded .result .selected .nohighlight} +[{ + "@id": "http://example.org/places#BrewEats", + "@type": ["http://example/document#Restaurant"], + "http://example/document#name": [{"@value": "Brew Eats"}] +}] +``` + + Subject Property Value + ------------------------------------ ------------------------------ ------------------------------------ + http://example.org/places#BrewEats rdf:type http://example/document#Restaurant + http://example.org/places#BrewEats http://example/document#name Brew Eats + +``` {.turtle content-type="text/turtle" result-for="Using \"#\" as the vocabulary mapping (expanded)-expanded" to-rdf="" aria-busy="false"} + a ; + "Brew Eats" . +``` + +#### 4.1.5 Compact IRIs[](#compact-iris) + +*This section is non-normative.* + +A [compact IRI](#dfn-compact-iri) is a way of expressing an [IRI](https://tools.ietf.org/html/rfc3987#section-2) using a *prefix* and *suffix* separated by a colon (`:`). The [prefix](#dfn-prefix) is a [term](#dfn-term) taken from the [active context](#dfn-active-context) and is a short string identifying a particular [IRI](https://tools.ietf.org/html/rfc3987#section-2) in a JSON-LD document. For example, the prefix `foaf` may be used as a shorthand for the Friend-of-a-Friend vocabulary, which is identified using the [IRI](https://tools.ietf.org/html/rfc3987#section-2) `http://xmlns.com/foaf/0.1/`. A developer may append any of the FOAF vocabulary terms to the end of the prefix to specify a short-hand version of the [IRI](https://tools.ietf.org/html/rfc3987#section-2) for the vocabulary term. For example, `foaf:name` would be expanded to the IRI `http://xmlns.com/foaf/0.1/name`. + +[Example 31](#example-31-prefix-expansion): Prefix expansion + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22foaf%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%0A%20%20%20%20%0A%20%20%7D%2C%0A%20%20%22%40type%22%3A%20%22foaf%3APerson%22%2C%0A%20%20%22foaf%3Aname%22%3A%20%22Dave%20Longley%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "foaf": "http://xmlns.com/foaf/0.1/" + ... + }, + "@type": "foaf:Person", + "foaf:name": "Dave Longley", + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Prefix expansion-compacted"} +[{ + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Dave Longley"}] +}] +``` + + Subject Property Value + --------- ----------- -------------- + \_:b0 rdf:type foaf:Person + \_:b0 foaf:name Dave Longley + +``` {.turtle content-type="text/turtle" result-for="Prefix expansion-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . +@prefix xsd: . + + [ + a foaf:Person; + foaf:name "Dave Longley" + ] . +``` + +In the example above, `foaf:name` expands to the [IRI](https://tools.ietf.org/html/rfc3987#section-2) `http://xmlns.com/foaf/0.1/name` and `foaf:Person` expands to `http://xmlns.com/foaf/0.1/Person`. + +[Prefixes](#dfn-prefix) are expanded when the form of the value is a [compact IRI](#dfn-compact-iri) represented as a `prefix:suffix` combination, the *prefix* matches a [term](#dfn-term) defined within the [active context](#dfn-active-context), and the *suffix* does not begin with two slashes (`//`). The [compact IRI](#dfn-compact-iri) is expanded by concatenating the [IRI](https://tools.ietf.org/html/rfc3987#section-2) mapped to the *prefix* to the (possibly empty) *suffix*. If the *prefix* is not defined in the [active context](#dfn-active-context), or the suffix begins with two slashes (such as in `http://example.com`), the value is interpreted as [IRI](https://tools.ietf.org/html/rfc3987#section-2) instead. If the prefix is an underscore (`_`), the value is interpreted as [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) instead. + +It\'s also possible to use compact IRIs within the context as shown in the following example: + +[Example 32](#example-32-using-vocabularies): Using vocabularies + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22xsd%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23%22%2C%0A%20%20%20%20%22foaf%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%2C%0A%20%20%20%20%22foaf%3Ahomepage%22%3A%20%7B%20%22%40type%22%3A%20%22%40id%22%20%7D%2C%0A%20%20%20%20%22picture%22%3A%20%7B%20%22%40id%22%3A%20%22foaf%3Adepiction%22%2C%20%22%40type%22%3A%20%22%40id%22%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fme.markus-lanthaler.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%22foaf%3APerson%22%2C%0A%20%20%22foaf%3Aname%22%3A%20%22Markus%20Lanthaler%22%2C%0A%20%20%22foaf%3Ahomepage%22%3A%20%22http%3A%2F%2Fwww.markus-lanthaler.com%2F%22%2C%0A%20%20%22picture%22%3A%20%22http%3A%2F%2Ftwitter.com%2Faccount%2Fprofile_image%2Fmarkuslanthaler%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "xsd": "http://www.w3.org/2001/XMLSchema#", + "foaf": "http://xmlns.com/foaf/0.1/", + "foaf:homepage": { "@type": "@id" }, + "picture": { "@id": "foaf:depiction", "@type": "@id" } + }, + "@id": "http://me.markus-lanthaler.com/", + "@type": "foaf:Person", + "foaf:name": "Markus Lanthaler", + "foaf:homepage": "http://www.markus-lanthaler.com/", + "picture": "http://twitter.com/account/profile_image/markuslanthaler" +} +``` + +``` {.expanded .result .result .nohighlight result-for="Using vocabularies-compacted"} +[{ + "@id": "http://me.markus-lanthaler.com/", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{ + "@value": "Markus Lanthaler" + }], + "http://xmlns.com/foaf/0.1/homepage": [{ + "@id": "http://www.markus-lanthaler.com/" + }], + "http://xmlns.com/foaf/0.1/depiction": [{ + "@id": "http://twitter.com/account/profile_image/markuslanthaler" + }] +}] +``` + + Subject Property Value + --------------------------------- ---------------- ---------------------------------------------------------- + http://me.markus-lanthaler.com/ rdf:type foaf:Person + http://me.markus-lanthaler.com/ foaf:name Markus Lanthaler + http://me.markus-lanthaler.com/ foaf:depiction http://twitter.com/account/profile_image/markuslanthaler + http://me.markus-lanthaler.com/ foaf:homepage http://www.markus-lanthaler.com/ + +``` {.turtle content-type="text/turtle" result-for="Using vocabularies-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . +@prefix xsd: . + + a foaf:Person; + foaf:name "Markus Lanthaler"; + foaf:homepage ; + foaf:depiction . +``` + +When operating explicitly with the [processing mode](#dfn-processing-mode) for [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/) compatibility, terms may be chosen as [compact IRI](#dfn-compact-iri) prefixes when compacting only if a [simple term definition](#dfn-simple-term-definition) is used where the value ends with a URI [gen-delim](https://tools.ietf.org/html/rfc3986#section-2.2) character (e.g, `/`, `#` and others, see \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]). + +In JSON-LD 1.1, terms may be chosen as [compact IRI](#dfn-compact-iri) prefixes when expanding or compacting only if a [simple term definition](#dfn-simple-term-definition) is used where the value ends with a URI [gen-delim](https://tools.ietf.org/html/rfc3986#section-2.2) character, or if their [expanded term definition](#dfn-expanded-term-definition) contains a `@prefix` [entry](https://infra.spec.whatwg.org/#map-entry) with the value `true`. If a [simple term definition](#dfn-simple-term-definition) does not end with a URI [gen-delim](https://tools.ietf.org/html/rfc3986#section-2.2) character, or a [expanded term definition](#dfn-expanded-term-definition) contains a `@prefix` [entry](https://infra.spec.whatwg.org/#map-entry) with the value `false`, the term will not be used for either expanding [compact IRIs](#dfn-compact-iri) or compacting [IRIs](https://tools.ietf.org/html/rfc3987#section-2) to [compact IRIs](#dfn-compact-iri). + +Note + +The term selection behavior for 1.0 processors was changed as a result of an errata against [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/) reported [here](https://lists.w3.org/Archives/Public/public-rdf-comments/2018Jan/0002.html). This does not affect the behavior of processing existing JSON-LD documents, but creates a slight change when compacting documents using [Compact IRIs](#dfn-compact-iri). + +The behavior when compacting can be illustrated by considering the following input document in expanded form: + +[Example 33](#term-selection-example): Expanded document used to illustrate compact IRI creation + +``` {.expanded .input aria-busy="false"} +[{ + "http://example.com/vocab/property": [{"@value": "property"}], + "http://example.com/vocab/propertyOne": [{"@value": "propertyOne"}] +}] +``` + +Using the following context in the 1.0 [processing mode](#dfn-processing-mode) will now select the term *vocab* rather than *property*, even though the IRI associated with *property* captures more of the original IRI. + +[Example 34](#term-selection-context-0): Compact IRI generation context (1.0) + +``` {.context aria-busy="false"} +{ + "@context": { + "vocab": "http://example.com/vocab/", + "property": "http://example.com/vocab/property" + } +} +``` + +Compacting using the previous context with the above expanded input document results in the following compacted result: + +[Example 35](#example-35-compact-iri-generation-term-selection-1-0): Compact IRI generation term selection (1.0) + +Compacted (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-compacted&json-ld=%5B%7B%0A%20%20%22http%3A%2F%2Fexample.com%2Fvocab%2Fproperty%22%3A%20%5B%7B%22%40value%22%3A%20%22property%22%7D%5D%2C%0A%20%20%22http%3A%2F%2Fexample.com%2Fvocab%2FpropertyOne%22%3A%20%5B%7B%22%40value%22%3A%20%22propertyOne%22%7D%5D%0A%7D%5D&context=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22vocab%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%2F%22%2C%0A%20%20%20%20%22property%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%2Fproperty%22%0A%20%20%7D%0A%7D) + +``` {.compacted .result .selected .nohighlight result-for="Expanded document used to illustrate compact IRI creation" context="Compact IRI generation context (1.0)" data-compact="" title="Compact IRI generation term selection (1.0)-compacted"} +{ + "@context": { + "vocab": "http://example.com/vocab/", + "property": "http://example.com/vocab/property" + }, + "property": "property", + "vocab:propertyOne": "propertyOne" +} +``` + + Subject Property Value + --------- -------------------------------------- ------------- + \_:b0 http://example.com/vocab/property property + \_:b0 http://example.com/vocab/propertyOne propertyOne + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Expanded document used to illustrate compact IRI creation" to-rdf=""} +@prefix vocab: . + +[ vocab:property "property"; vocab:propertyOne "propertyOne"] . +``` + +In the original \[[JSON-LD10](#bib-json-ld10 "JSON-LD 1.0")\], the term selection algorithm would have selected *property*, creating the Compact IRI *property:One*. The original behavior can be made explicit using `@prefix`: + +[Example 36](#term-selection-context-1): Compact IRI generation context (1.1) + +``` {.context aria-busy="false"} +{ + "@context": { + "@version": 1.1, + "vocab": "http://example.com/vocab/", + "property": { + "@id": "http://example.com/vocab/property", + "@prefix": true + } + } +} +``` + +[Example 37](#example-37-compact-iri-generation-term-selection-1-1): Compact IRI generation term selection (1.1) + +Compacted (Input) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-compacted&json-ld=%5B%7B%0A%20%20%22http%3A%2F%2Fexample.com%2Fvocab%2Fproperty%22%3A%20%5B%7B%22%40value%22%3A%20%22property%22%7D%5D%2C%0A%20%20%22http%3A%2F%2Fexample.com%2Fvocab%2FpropertyOne%22%3A%20%5B%7B%22%40value%22%3A%20%22propertyOne%22%7D%5D%0A%7D%5D&context=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22vocab%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%2F%22%2C%0A%20%20%20%20%22property%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%2Fproperty%22%2C%0A%20%20%20%20%20%20%22%40prefix%22%3A%20true%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight result-for="Expanded document used to illustrate compact IRI creation" context="Compact IRI generation context (1.1)" data-compact="" title="Compact IRI generation term selection (1.1)-compacted"} +{ + "@context": { + "@version": 1.1, + "vocab": "http://example.com/vocab/", + "property": { + "@id": "http://example.com/vocab/property", + "@prefix": true + } + }, + "property": "property", + "property:One": "propertyOne" +} +``` + + Subject Property Value + --------- -------------------------------------- ------------- + \_:b0 http://example.com/vocab/property property + \_:b0 http://example.com/vocab/propertyOne propertyOne + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Expanded document used to illustrate compact IRI creation" to-rdf=""} +@prefix vocab: . + +[ vocab:property "property"; vocab:propertyOne "propertyOne"] . +``` + +In this case, the *property* term would not normally be usable as a prefix, both because it is defined with an [expanded term definition](#dfn-expanded-term-definition), and because its `@id` does not end in a [gen-delim](https://tools.ietf.org/html/rfc3986#section-2.2) character. Adding `"@prefix": true` allows it to be used as the prefix portion of the [compact IRI](#dfn-compact-iri) *property:One*. + +#### 4.1.6 Aliasing Keywords[](#aliasing-keywords) + +*This section is non-normative.* + +Each of the JSON-LD [keywords](#dfn-keyword), except for `@context`, may be aliased to application-specific keywords. This feature allows legacy JSON content to be utilized by JSON-LD by re-using JSON keys that already exist in legacy documents. This feature also allows developers to design domain-specific implementations using only the JSON-LD [context](#dfn-context). + +[Example 38](#example-38-aliasing-keywords): Aliasing keywords + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22url%22%3A%20%22%40id%22%2C%0A%20%20%20%20%22a%22%3A%20%22%40type%22%2C%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fname%22%0A%20%20%7D%2C%0A%20%20%22url%22%3A%20%22http%3A%2F%2Fexample.com%2Fabout%23gregg%22%2C%0A%20%20%22a%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2FPerson%22%2C%0A%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "url": "@id", + "a": "@type", + "name": "http://xmlns.com/foaf/0.1/name" + }, + "url": "http://example.com/about#gregg", + "a": "http://xmlns.com/foaf/0.1/Person", + "name": "Gregg Kellogg" +} +``` + +``` {.expanded .result .result .nohighlight result-for="Aliasing keywords-compacted"} +[{ + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Gregg Kellogg"}], + "@id": "http://example.com/about#gregg" +}] +``` + + Subject Property Value + -------------------------------- ----------- --------------- + http://example.com/about#gregg rdf:type foaf:Person + http://example.com/about#gregg foaf:name Gregg Kellogg + +``` {.turtle content-type="text/turtle" result-for="Aliasing keywords-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . + + a foaf:Person; + foaf:name "Gregg Kellogg" . +``` + +In the example above, the `@id` and `@type` [keywords](#dfn-keyword) have been given the aliases **url** and **a**, respectively. + +Other than for `@type`, properties of [expanded term definitions](#dfn-expanded-term-definition) where the term is a [keyword](#dfn-keyword) result in an error. Unless the [processing mode](#dfn-processing-mode) is set to `json-ld-1.0`, there is also an exception for `@type`; see [§ 4.3.3 Using `@set` with `@type`](#using-set-with-type) for further details and usage examples. + +Unless the [processing mode](#dfn-processing-mode) is set to `json-ld-1.0`, aliases of [keywords](#dfn-keyword) are either [simple term definitions](#dfn-simple-term-definition), where the value is a [keyword](#dfn-keyword), or a [expanded term definitions](#dfn-expanded-term-definition) with an `@id` [entry](https://infra.spec.whatwg.org/#map-entry) and optionally an `@protected` [entry](https://infra.spec.whatwg.org/#map-entry); no other entries are allowed. There is also an exception for aliases of `@type`, as indicated above. See [§ 4.1.11 Protected Term Definitions](#protected-term-definitions) for further details of using `@protected`. + +Since keywords cannot be redefined, they can also not be aliased to other keywords. + +Note + +Aliased keywords may not be used within a [context](#dfn-context), itself. + +See [§ 9.16 Keywords](#keywords) for a normative definition of all keywords. + +#### 4.1.7 IRI Expansion within a Context[](#iri-expansion-within-a-context) + +*This section is non-normative.* + +In general, normal IRI expansion rules apply anywhere an IRI is expected (see [§ 3.2 IRIs](#iris)). Within a [context](#dfn-context) definition, this can mean that terms defined within the context may also be used within that context as long as there are no circular dependencies. For example, it is common to use the `xsd` namespace when defining [typed values](#dfn-typed-value): + +[Example 39](#example-39-iri-expansion-within-a-context): IRI expansion within a context + +``` nohighlight +{ + "@context": { + "xsd": "http://www.w3.org/2001/XMLSchema#", + "name": "http://xmlns.com/foaf/0.1/name", + "age": { + "@id": "http://xmlns.com/foaf/0.1/age", + "@type": "xsd:integer" + }, + "homepage": { + "@id": "http://xmlns.com/foaf/0.1/homepage", + "@type": "@id" + } + }, + ... +} +``` + +In this example, the `xsd` [term](#dfn-term) is defined and used as a [prefix](#dfn-prefix) for the `@type` coercion of the `age` property. + +[Terms](#dfn-term) may also be used when defining the IRI of another [term](#dfn-term): + +[Example 40](#example-40-using-a-term-to-define-the-iri-of-another-term-within-a-context): Using a term to define the IRI of another term within a context + +``` nohighlight +{ + "@context": { + "foaf": "http://xmlns.com/foaf/0.1/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "name": "foaf:name", + "age": { + "@id": "foaf:age", + "@type": "xsd:integer" + }, + "homepage": { + "@id": "foaf:homepage", + "@type": "@id" + } + }, + ... +} +``` + +[Compact IRIs](#dfn-compact-iri) and [IRIs](https://tools.ietf.org/html/rfc3987#section-2) may be used on the left-hand side of a [term](#dfn-term) definition. + +[Example 41](#example-41-using-a-compact-iri-as-a-term): Using a compact IRI as a term + +``` nohighlight +{ + "@context": { + "foaf": "http://xmlns.com/foaf/0.1/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "name": "foaf:name", + "foaf:age": { + "@id": "http://xmlns.com/foaf/0.1/age", + "@type": "xsd:integer" + }, + "foaf:homepage": { + "@type": "@id" + } + }, + ... +} +``` + +In this example, the [compact IRI](#dfn-compact-iri) form is used in two different ways. In the first approach, `foaf:age` declares both the [IRI](https://tools.ietf.org/html/rfc3987#section-2) for the [term](#dfn-term) (using short-form) as well as the `@type` associated with the [term](#dfn-term). In the second approach, only the `@type` associated with the [term](#dfn-term) is specified. The full [IRI](https://tools.ietf.org/html/rfc3987#section-2) for `foaf:homepage` is determined by looking up the `foaf` [prefix](#dfn-prefix) in the [context](#dfn-context). + +Warning + +If a [compact IRI](#dfn-compact-iri) is used as a [term](#dfn-term), it must expand to the value that [compact IRI](#dfn-compact-iri) would have on its own when expanded. This represents a change to the original 1.0 algorithm to prevent terms from expanding to a different [IRI](https://tools.ietf.org/html/rfc3987#section-2), which could lead to undesired results. + +[Example 42](#example-42-illegal-aliasing-of-a-compact-iri-to-a-different-iri): Illegal Aliasing of a compact IRI to a different IRI + +``` nohighlight +{ + "@context": { + "foaf": "http://xmlns.com/foaf/0.1/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "name": "foaf:name", + "foaf:age": { + "@id": "http://xmlns.com/foaf/0.1/age", + "@type": "xsd:integer" + }, + "foaf:homepage": { + "@id": "http://schema.org/url", + "@type": "@id" + } + }, + ... +} +``` + +[IRIs](https://tools.ietf.org/html/rfc3987#section-2) may also be used in the key position in a [context](#dfn-context): + +[Example 43](#example-43-associating-context-definitions-with-iris): Associating context definitions with IRIs + +``` nohighlight +{ + "@context": { + "foaf": "http://xmlns.com/foaf/0.1/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "name": "foaf:name", + "foaf:age": { + "@id": "http://xmlns.com/foaf/0.1/age", + "@type": "xsd:integer" + }, + "http://xmlns.com/foaf/0.1/homepage": { + "@type": "@id" + } + }, + ... +} +``` + +In order for the [IRI](https://tools.ietf.org/html/rfc3987#section-2) to match above, the [IRI](https://tools.ietf.org/html/rfc3987#section-2) needs to be used in the [JSON-LD document](#dfn-json-ld-document). Also note that `foaf:homepage` will not use the `{ "@type": "@id" }` declaration because `foaf:homepage` is not the same as `http://xmlns.com/foaf/0.1/homepage`. That is, [terms](#dfn-term) are looked up in a [context](#dfn-context) using direct string comparison before the [prefix](#dfn-prefix) lookup mechanism is applied. + +Warning + +Neither an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3) nor a [compact IRI](#dfn-compact-iri) may expand to some other unrelated [IRI](https://tools.ietf.org/html/rfc3987#section-2). This represents a change to the original 1.0 algorithm which allowed this behavior but discouraged it. + +The only other exception for using terms in the [context](#dfn-context) is that circular definitions are not allowed. That is, a definition of *term1* cannot depend on the definition of *term2* if *term2* also depends on *term1*. For example, the following [context](#dfn-context) definition is illegal: + +[Example 44](#example-44-illegal-circular-definition-of-terms-within-a-context): Illegal circular definition of terms within a context + +``` {.nohighlight ignore=""} +{ + "@context": { + "term1": "term2:foo", + "term2": "term1:bar" + }, + ... +} +``` + +#### 4.1.8 Scoped Contexts[](#scoped-contexts) + +*This section is non-normative.* + +An [expanded term definition](#dfn-expanded-term-definition) can include a `@context` property, which defines a [context](#dfn-context) (a [scoped context](#dfn-scoped-context)) for [values](#dfn-json-ld-value) of properties defined using that [term](#dfn-term). When used for a [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property), this is called a [property-scoped context](#dfn-property-scoped-context). This allows values to use [term definitions](#dfn-term-definition), the [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri), [vocabulary mappings](#dfn-vocabulary-mapping) or the [default language](#dfn-default-language) which are different from the [node object](#dfn-node-object) they are contained in, as if the [context](#dfn-context) was specified within the value itself. + +[Example 45](#example-45-defining-an-context-within-a-term-definition): Defining an \@context within a term definition + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fschema.org%2Fname%22%2C%0A%20%20%20%20%22interest%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Finterest%22%2C%0A%20%20%20%20%20%20%22%40context%22%3A%20%7B%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%7D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22interest%22%3A%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fwww.w3.org%2FTR%2Fjson-ld11%2F%22%2C%0A%20%20%20%20%22name%22%3A%20%22JSON-LD%22%2C%0A%20%20%20%20%22topic%22%3A%20%22Linking%20Data%22%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "name": "http://schema.org/name", + "interest": { + "@id": "http://xmlns.com/foaf/0.1/interest", + "@context": {"@vocab": "http://xmlns.com/foaf/0.1/"} + } + }, + "name": "Manu Sporny", + "interest": { + "@id": "https://www.w3.org/TR/json-ld11/", + "name": "JSON-LD", + "topic": "Linking Data" + } +} +``` + +``` {.expanded .result .nohighlight result-for="Defining an @context within a term definition-compacted"} +[{ + "http://xmlns.com/foaf/0.1/interest": [ + { + "@id": "https://www.w3.org/TR/json-ld11/", + "http://schema.org/name": [{"@value": "JSON-LD"}], + "http://xmlns.com/foaf/0.1/topic": [{"@value": "Linking Data"}] + } + ], + "http://schema.org/name": [{"@value": "Manu Sporny"}] +}] +``` + + Subject Property Value + ---------------------------------- --------------- ---------------------------------- + https://www.w3.org/TR/json-ld11/ schema:name JSON-LD + https://www.w3.org/TR/json-ld11/ foaf:topic Linking Data + \_:b0 schema:name Manu Sporny + \_:b0 foaf:interest https://www.w3.org/TR/json-ld11/ + +``` {.turtle content-type="text/turtle" result-for="Defining an @context within a term definition-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . +@prefix schema: . + +[ + schema:name "Manu Sporny"; + foaf:interest +] . + schema:name "JSON-LD"; + foaf:topic "Linking Data" . +``` + +In this case, the social profile is defined using the schema.org vocabulary, but interest is imported from FOAF, and is used to define a node describing one of Manu\'s interests where those [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property) now come from the FOAF vocabulary. + +Expanding this document, uses a combination of terms defined in the outer context, and those defined specifically for that term in a [property-scoped context](#dfn-property-scoped-context). + +Scoping can also be performed using a term used as a value of `@type`: + +[Example 46](#example-46-defining-an-context-within-a-term-definition-used-on-type): Defining an \@context within a term definition used on \@type + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fschema.org%2Fname%22%2C%0A%20%20%20%20%22interest%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Finterest%22%2C%0A%20%20%20%20%22Person%22%3A%20%22http%3A%2F%2Fschema.org%2FPerson%22%2C%0A%20%20%20%20%22Document%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2FDocument%22%2C%0A%20%20%20%20%20%20%22%40context%22%3A%20%7B%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%7D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22interest%22%3A%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fwww.w3.org%2FTR%2Fjson-ld11%2F%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Document%22%2C%0A%20%20%20%20%22name%22%3A%20%22JSON-LD%22%2C%0A%20%20%20%20%22topic%22%3A%20%22Linking%20Data%22%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "name": "http://schema.org/name", + "interest": "http://xmlns.com/foaf/0.1/interest", + "Person": "http://schema.org/Person", + "Document": { + "@id": "http://xmlns.com/foaf/0.1/Document", + "@context": {"@vocab": "http://xmlns.com/foaf/0.1/"} + } + }, + "@type": "Person", + "name": "Manu Sporny", + "interest": { + "@id": "https://www.w3.org/TR/json-ld11/", + "@type": "Document", + "name": "JSON-LD", + "topic": "Linking Data" + } +} +``` + +``` {.expanded .result .result .nohighlight result-for="Defining an @context within a term definition used on @type-compacted"} +[{ + "@type": ["http://schema.org/Person"], + "http://xmlns.com/foaf/0.1/interest": [ + { + "@id": "https://www.w3.org/TR/json-ld11/", + "@type": ["http://xmlns.com/foaf/0.1/Document"], + "http://schema.org/name": [{"@value": "JSON-LD"}], + "http://xmlns.com/foaf/0.1/topic": [{"@value": "Linking Data"}] + } + ], + "http://schema.org/name": [{"@value": "Manu Sporny"}] +}] +``` + + Subject Property Value + ---------------------------------- --------------- ---------------------------------- + \_:b0 rdf:type schema:Person + https://www.w3.org/TR/json-ld11/ rdf:type foaf:Document + https://www.w3.org/TR/json-ld11/ schema:name JSON-LD + https://www.w3.org/TR/json-ld11/ foaf:topic Linking Data + \_:b0 schema:name Manu Sporny + \_:b0 foaf:interest https://www.w3.org/TR/json-ld11/ + +``` {.turtle content-type="text/turtle" result-for="Defining an @context within a term definition used on @type-expanded" to-rdf="" no-lint="" aria-busy="false"} +@prefix foaf: . +@prefix schema: . + +[ + a schema:Person; + schema:name "Manu Sporny"; + foaf:interest +] . + a foaf:Document; + schema:name "JSON-LD"; + foaf:topic "Linking Data" . +``` + +Scoping on `@type` is useful when common properties are used to relate things of different types, where the vocabularies in use within different entities calls for different context scoping. For example, `hasPart`/`partOf` may be common terms used in a document, but mean different things depending on the context. A [type-scoped context](#dfn-type-scoped-context) is only in effect for the [node object](#dfn-node-object) on which the type is used; the previous in-scope [contexts](#dfn-context) are placed back into effect when traversing into another [node object](#dfn-node-object). As described further in [§ 4.1.9 Context Propagation](#context-propagation), this may be controlled using the `@propagate` keyword. + +Note + +Any [property-scoped](#dfn-property-scoped-context) or local [contexts](#dfn-context) that were introduced in the [node object](#dfn-node-object) would still be in effect when traversing into another [node object](#dfn-node-object). + +When expanding, each value of `@type` is considered (ordering them lexicographically) where that value is also a [term](#dfn-term) in the [active context](#dfn-active-context) having its own [type-scoped context](#dfn-type-scoped-context). If so, that the [scoped context](#dfn-scoped-context) is applied to the [active context](#dfn-active-context). + +Note + +The values of `@type` are unordered, so if multiple types are listed, the order that [type-scoped contexts](#dfn-type-scoped-context) are applied is based on lexicographical ordering. + +For example, consider the following semantically equivalent examples. The first example, shows how properties and types can define their own scoped contexts, which are included when expanding. + +[Example 47](#example-47-expansion-using-embedded-and-scoped-contexts): Expansion using embedded and scoped contexts + +``` {aria-busy="false"} +{ + "@context": { + "@version": 1.1, + "@vocab": "http://example.com/vocab/", + "property": { + "@id": "http://example.com/vocab/property", + "@context": { + "term1": "http://example.com/vocab/term1" + ↑ Scoped context for "property" defines term1 + } + }, + "Type1": { + "@id": "http://example.com/vocab/Type1", + "@context": { + "term3": "http://example.com/vocab/term3" + ↑ Scoped context for "Type1" defines term3 + } + }, + "Type2": { + "@id": "http://example.com/vocab/Type2", + "@context": { + "term4": "http://example.com/vocab/term4" + ↑ Scoped context for "Type2" defines term4 + } + } + }, + "property": { + "@context": { + "term2": "http://example.com/vocab/term2" + ↑ Embedded context defines term2 + }, + "@type": ["Type2", "Type1"], + "term1": "a", + "term2": "b", + "term3": "c", + "term4": "d" + } +} +``` + +Contexts are processed depending on how they are defined. A [property-scoped context](#dfn-property-scoped-context) is processed first, followed by any [embedded context](#dfn-embedded-context), followed lastly by the [type-scoped contexts](#dfn-type-scoped-context), in the appropriate order. The previous example is logically equivalent to the following: + +[Example 48](#example-48-expansion-using-embedded-and-scoped-contexts-embedding-equivalent): Expansion using embedded and scoped contexts (embedding equivalent) + +``` {aria-busy="false"} +{ + "@context": { + "@vocab": "http://example.com/vocab/", + "property": "http://example.com/vocab/property", + "Type1": "http://example.com/vocab/Type1", + "Type2": "http://example.com/vocab/Type2" + }, + "property": { + "@context": [{ + "term1": "http://example.com/vocab/term1" + ↑ Previously scoped context for "property" defines term1 + }, { + "term2": "http://example.com/vocab/term2" + ↑ Embedded context defines term2 + }, { + "term3": "http://example.com/vocab/term3" + ↑ Previously scoped context for "Type1" defines term3 + }, { + "term4": "http://example.com/vocab/term4" + ↑ Previously scoped context for "Type2" defines term4 + }], + "@type": ["Type2", "Type1"], + "term1": "a", + "term2": "b", + "term3": "c", + "term4": "d" + } +} +``` + +Note + +If a [term](#dfn-term) defines a [scoped context](#dfn-scoped-context), and then that term is later redefined, the association of the context defined in the earlier [expanded term definition](#dfn-expanded-term-definition) is lost within the scope of that redefinition. This is consistent with [term definitions](#dfn-term-definition) of a term overriding previous term definitions from earlier less deeply nested definitions, as discussed in [§ 4.1 Advanced Context Usage](#advanced-context-usage). + +Note + +[Scoped Contexts](#dfn-scoped-context) are a new feature in JSON-LD 1.1. + +#### 4.1.9 Context Propagation[](#context-propagation) + +*This section is non-normative.* + +Once introduced, [contexts](#dfn-context) remain in effect until a subsequent [context](#dfn-context) removes it by setting `@context` to `null`, or by redefining terms, with the exception of [type-scoped contexts](#dfn-type-scoped-context), which limit the effect of that context until the next [node object](#dfn-node-object) is entered. This behavior can be changed using the `@propagate` keyword. + +The following example illustrates how terms defined in a context with `@propagate` set to `false` are effectively removed when descending into new [node object](#dfn-node-object). + +[Example 49](#example-49-marking-a-context-to-not-propagate): Marking a context to not propagate + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22term%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Foriginal%22%2C%0A%20%20%20%20%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22%40propagate%22%3A%20false%2C%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%22term%22%3A%20%22http%3A%2F%2Fexample.org%2Fnon-propagated-term%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22term%22%3A%20%7B%0A%20%20%0A%20%20%20%20%22term%22%3A%20%7B%0A%20%20%20%20%0A%20%20%20%20%20%20%22term%22%3A%20%22This%20term%20is%20from%20the%20first%20context%22%0A%20%20%20%20%20%20%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "term": { + "@id": "http://example.org/original", + "@context": { + "@propagate": false, + ↑ Scoped context only lasts in one node-object + "term": "http://example.org/non-propagated-term" + } + } + }, + "term": { + ↑ This term is the original + "term": { + ↑ This term is from the scoped context + "term": "This term is from the first context" + ↑ This term is the original again + } + } +} +``` + +``` {.expanded .result .result .nohighlight result-for="Marking a context to not propagate-compacted"} +[{ + "http://example.org/original": [{ + "http://example.org/non-propagated-term": [{ + "http://example.org/original": [ + {"@value": "This term is from the first context"} + ] + }] + }] +}] +``` + + Subject Property Value + --------- ---------------------------------------- ------------------------------------- + \_:b2 http://example.org/original This term is from the first context + \_:b1 http://example.org/non-propagated-term \_:b2 + \_:b0 http://example.org/original \_:b1 + +``` {.turtle content-type="text/turtle" result-for="Marking a context to not propagate-expanded" to-rdf="" no-lint="" aria-busy="false"} +@prefix ex: . +[ + ex:original [ + ex:non-propagated-term [ + ex:original "This term is from the first context" + ] + ] +] . +``` + +Note + +Contexts included within an array must all have the same value for `@propagate` due to the way that rollback is defined in [JSON-LD 1.1 Processing Algorithms and API](https://www.w3.org/TR/json-ld11-api/). + +#### 4.1.10 Imported Contexts[](#imported-contexts) + +*This section is non-normative.* + +JSON-LD 1.0 included mechanisms for modifying the [context](#dfn-context) that is in effect. This included the capability to load and process a remote [context](#dfn-context) and then apply further changes to it via new [contexts](#dfn-context). + +However, with the introduction of JSON-LD 1.1, it is also desirable to be able to load a remote [context](#dfn-context), in particular an existing JSON-LD 1.0 [context](#dfn-context), and apply JSON-LD 1.1 features to it prior to processing. + +By using the `@import` keyword in a [context](#dfn-context), another remote [context](#dfn-context), referred to as an imported [context](#dfn-context), can be loaded and modified prior to processing. The modifications are expressed in the [context](#dfn-context) that includes the `@import` keyword, referred to as the wrapping [context](#dfn-context). Once an imported [context](#dfn-context) is loaded, the contents of the wrapping [context](#dfn-context) are merged into it prior to processing. The merge operation will cause each key-value pair in the wrapping [context](#dfn-context) to be added to the loaded imported [context](#dfn-context), with the wrapping [context](#dfn-context) key-value pairs taking precedence. + +By enabling existing [contexts](#dfn-context) to be reused and edited inline prior to processing, context-wide keywords can be applied to adjust all term definitions in the imported [context](#dfn-context). Similarly, term definitions can be replaced prior to processing, enabling adjustments that, for instance, ensure term definitions match previously protected terms or that they include additional type coercion information. + +The following examples illustrate how `@import` can be used to express a [type-scoped context](#dfn-type-scoped-context) that loads an imported [context](#dfn-context) and sets `@propagate` to `true`, as a technique for making other similar modifications. + +Suppose there was a [context](#dfn-context) that could be referenced remotely via the URL `https://json-ld.org/contexts/remote-context.jsonld`: + +[Example 50](#example-50-a-remote-context-to-be-imported-in-a-type-scoped-context): A remote context to be imported in a type-scoped context + +``` nohighlight +{ + "@context": { + "Type1": "http://example.com/vocab/Type1", + "Type2": "http://example.com/vocab/Type2", + "term1": "http://example.com/vocab#term1", + "term2": "http://example.com/vocab#term2", + ... + } +} +``` + +A wrapping [context](#dfn-context) could be used to source it and modify it: + +[Example 51](#example-51-sourcing-a-context-in-a-type-scoped-context-and-setting-it-to-propagate): Sourcing a context in a type-scoped context and setting it to propagate + +``` nohighlight +{ + "@context": { + "@version": 1.1, + "MyType": { + "@id": "http://example.com/vocab#MyType", + "@context": { + "@version": 1.1, + "@import": "https://json-ld.org/contexts/remote-context.jsonld", + "@propagate": true + } + } + } +} +``` + +The effect would be the same as if the entire imported [context](#dfn-context) had been copied into the [type-scoped context](#dfn-type-scoped-context): + +[Example 52](#example-52-result-of-sourcing-a-context-in-a-type-scoped-context-and-setting-it-to-propagate): Result of sourcing a context in a type-scoped context and setting it to propagate + +``` nohighlight +{ + "@context": { + "@version": 1.1, + "MyType": { + "@id": "http://example.com/vocab#MyType", + "@context": { + "@version": 1.1, + "Type1": "http://example.com/vocab/Type1", + "Type2": "http://example.com/vocab/Type2", + "term1": "http://example.com/vocab#term1", + "term2": "http://example.com/vocab#term2", + ... + "@propagate": true + } + } + } +} +``` + +Similarly, the wrapping [context](#dfn-context) may replace term definitions or set other context-wide keywords that may affect how the imported [context](#dfn-context) term definitions will be processed: + +[Example 53](#example-53-sourcing-a-context-to-modify-vocab-and-a-term-definition): Sourcing a context to modify \@vocab and a term definition + +``` nohighlight +{ + "@context": { + "@version": 1.1, + "@import": "https://json-ld.org/contexts/remote-context.jsonld", + "@vocab": "http://example.org/vocab#", + ↑ This will replace any previous @vocab definition prior to processing it + "term1": { + "@id": "http://example.org/vocab#term1", + "@type": "http://www.w3.org/2001/XMLSchema#integer" + } + ↑ This will replace the old term1 definition prior to processing it + } +} +``` + +Again, the effect would be the same as if the entire imported [context](#dfn-context) had been copied into the [context](#dfn-context): + +[Example 54](#example-54-result-of-sourcing-a-context-to-modify-vocab-and-a-term-definition): Result of sourcing a context to modify \@vocab and a term definition + +``` nohighlight +{ + "@context": { + "@version": 1.1, + "Type1": "http://example.com/vocab/Type1", + "Type2": "http://example.com/vocab/Type2", + "term1": { + "@id": "http://example.org/vocab#term1", + "@type": "http://www.w3.org/2001/XMLSchema#integer" + }, + ↑ Note term1 has been replaced prior to processing + "term2": "http://example.com/vocab#term2", + ..., + "@vocab": "http://example.org/vocab#" + } +} +``` + +The result of loading imported [contexts](#dfn-context) must be [context definition](#dfn-context-definition), not an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or an [array](https://infra.spec.whatwg.org/#list). Additionally, the imported context cannot include an `@import` [entry](https://infra.spec.whatwg.org/#map-entry). + +#### 4.1.11 Protected Term Definitions[](#protected-term-definitions) + +*This section is non-normative.* + +JSON-LD is used in many specifications as the specified data format. However, there is also a desire to allow some JSON-LD contents to be processed as plain JSON, without using any of the JSON-LD algorithms. Because JSON-LD is very flexible, some terms from the original format may be locally overridden through the use of [embedded contexts](#dfn-embedded-context), and take a different meaning for JSON-LD based implementations. On the other hand, \"plain JSON\" implementations may not be able to interpret these [embedded contexts](#dfn-embedded-context), and hence will still interpret those terms with their original meaning. To prevent this divergence of interpretation, JSON-LD 1.1 allows term definitions to be *protected*. + +A protected term definition is a term definition with an [entry](https://infra.spec.whatwg.org/#map-entry) `@protected` set to `true`. It generally prevents further contexts from overriding this term definition, either through a new definition of the same term, or through clearing the context with `"@context": null`. Such attempts will raise an error and abort the processing (except in some specific situations described [below](#overriding-protected-terms)). + +[Example 55](#example-55-a-protected-term-definition-can-generally-not-be-overridden): A protected term definition can generally not be overridden + +``` {aria-busy="false"} +{ + "@context": [ + { + "@version": 1.1, + "Person": "http://xmlns.com/foaf/0.1/Person", + "knows": "http://xmlns.com/foaf/0.1/knows", + "name": { + "@id": "http://xmlns.com/foaf/0.1/name", + "@protected": true + } + }, + { + – this attempt will fail with an error + "name": "http://schema.org/name" + } + ], + "@type": "Person", + "name": "Manu Sporny", + "knows": { + "@context": [ + – this attempt would also fail with an error + null, + "http://schema.org/" + ], + "name": "Gregg Kellogg" + } +} +``` + +When all or most term definitions of a context need to be protected, it is possible to add an [entry](https://infra.spec.whatwg.org/#map-entry) `@protected` set to `true` to the context itself. It has the same effect as protecting each of its term definitions individually. Exceptions can be made by adding an [entry](https://infra.spec.whatwg.org/#map-entry) `@protected` set to `false` in some term definitions. + +[Example 56](#example-56-a-protected-context-with-an-exception): A protected \@context with an exception + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%20%20%22%40protected%22%3A%20true%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fschema.org%2Fname%22%2C%0A%20%20%20%20%20%20%22member%22%3A%20%22http%3A%2F%2Fschema.org%2Fmember%22%2C%0A%20%20%20%20%20%20%22Person%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fschema.org%2FPerson%22%2C%0A%20%20%20%20%20%20%20%20%22%40protected%22%3A%20false%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%5D%2C%0A%20%20%22name%22%3A%20%22Digital%20Bazaar%22%2C%0A%20%20%22member%22%3A%20%7B%0A%20%20%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%22Person%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2FPerson%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": [ + { + "@version": 1.1, + "@protected": true, + "name": "http://schema.org/name", + "member": "http://schema.org/member", + "Person": { + "@id": "http://schema.org/Person", + "@protected": false + } + } + ], + "name": "Digital Bazaar", + "member": { + "@context": { + ­– name *is* protected, so the following would fail with an error + – "name": "http://xmlns.com/foaf/0.1/Person", + ­– Person is *not* protected, and can be overridden + "Person": "http://xmlns.com/foaf/0.1/Person" + }, + "@type": "Person", + "name": "Manu Sporny" + } +} +``` + +``` {.expanded .result .nohighlight result-for="A protected @context with an exception-compacted"} +[{ + "http://schema.org/name": [{"@value": "Digital Bazaar"}], + "http://schema.org/member": [ + { + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://schema.org/name": [{"@value": "Manu Sporny"}] + } + ] +}] +``` + + Subject Property Value + --------- --------------- ---------------- + \_:b0 schema:name Digital Bazaar + \_:b0 schema:member \_:b1 + \_:b1 rdf:type foaf:Person + \_:b1 schema:name Manu Sporny + +``` {.turtle content-type="text/turtle" result-for="A protected @context with an exception-expanded" to-rdf="" no-lint="" aria-busy="false"} +@prefix foaf: . +@prefix schema: . + +[ + schema:name "Digital Bazaar"; + schema:member [ + a foaf:Person; + schema:name "Manu Sporny" + ] +] . +``` + +While protected terms can in general not be overridden, there are two exceptions to this rule. The first exception is that a context is allowed to redefine a protected term if the new definition is identical to the protected term definition (modulo the `@protected` flag). The rationale is that the new definition does not violate the protection, as it does not change the semantics of the protected term. This is useful for widespread term definitions, such as aliasing `@type` to `type`, which may occur (including in a protected form) in several contexts. + +[Example 57](#example-57-overriding-permitted-if-both-definitions-are-identical): Overriding permitted if both definitions are identical + +Original + +Expanded + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%20%20%22%40protected%22%3A%20true%2C%0A%20%20%20%20%20%20%22id%22%3A%20%22%40id%22%2C%0A%20%20%20%20%20%20%22type%22%3A%20%22%40type%22%2C%0A%20%20%20%20%20%20%22Organization%22%3A%20%22http%3A%2F%2Fexample.org%2Forga%2FOrganization%22%2C%0A%20%20%20%20%20%20%22member%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Forga%2Fmember%22%2C%0A%20%20%20%20%20%20%20%20%22%40type%22%3A%20%22%40id%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22id%22%3A%20%22%40id%22%2C%0A%20%20%20%20%20%20%22type%22%3A%20%22%40type%22%2C%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%22Person%22%3A%20%22http%3A%2F%2Fschema.org%2FPerson%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fschema.org%2Fname%22%0A%20%20%20%20%7D%0A%20%20%5D%2C%0A%20%20%22id%22%3A%20%22https%3A%2F%2Fdigitalbazaar.com%2F%22%2C%0A%20%20%22type%22%3A%20%22Organization%22%2C%0A%20%20%22member%22%20%3A%20%7B%0A%20%20%20%20%22id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%20%20%22type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%0A%20%20%7D%0A%7D) + +``` {.original .selected .nohighlight ignore=""} +{ + "@context": [ + { + "@version": 1.1, + "@protected": true, + "id": "@id", + "type": "@type", + "Organization": "http://example.org/orga/Organization", + "member": { + "@id": "http://example.org/orga/member", + "@type": "@id" + } + }, + { + "id": "@id", + "type": "@type", + ­– Those "redefinitions" do not raise an error. + ­– Note however that the terms are still protected + "Person": "http://schema.org/Person", + "name": "http://schema.org/name" + } + ], + "id": "https://digitalbazaar.com/", + "type": "Organization", + "member" : { + "id": "http://manu.sporny.org/about#manu", + "type": "Person", + "name": "Manu Sporny" + } +} +``` + +``` {.expanded .nohighlight result-for="Overriding permitted if both definitions are identical-original" ignore=""} +[{ + "@id": "https://digitalbazaar.com/", + "@type": ["http://example.org/orga/Organization"], + "http://example.org/orga/member": [ + { + "@id": "http://manu.sporny.org/about#manu", + "@type": ["http://schema.org/Person"], + "http://schema.org/name": [{"@value": "Manu Sporny"}] + } + ] +}] +``` + + Subject Property Value + ----------------------------------- -------------------------------- -------------------------------------- + https://digitalbazaar.com/ rdf:type http://example.org/orga/Organization + https://digitalbazaar.com/ http://example.org/orga/member http://manu.sporny.org/about#manu + http://manu.sporny.org/about#manu rdf:type schema:Person + http://manu.sporny.org/about#manu schema:name Manu Sporny + +``` {.turtle content-type="text/turtle" result-for="Overriding permitted if both definitions are identical-expanded" ignore="" to-rdf="" aria-busy="false"} +@prefix o: . +@prefix schema: . + + a o:Organization ; + o:member . + + a schema:Person ; + schema:name "Manu Sporny". +``` + +The second exception is that a [property-scoped context](#dfn-property-scoped-context) is not affected by protection, and can therefore override protected terms, either with a new term definition, or by clearing the context with `"@context": null`. + +The rationale is that \"plain JSON\" implementations, relying on a given specification, will only traverse properties defined by that specification. [Scoped contexts](#dfn-scoped-context) belonging to the specified properties are part of the specification, so the \"plain JSON\" implementations are expected to be aware of the change of semantics they induce. [Scoped contexts](#dfn-scoped-context) belonging to other properties apply to parts of the document that \"plain JSON\" implementations will ignore. In both cases, there is therefore no risk of diverging interpretations between JSON-LD-aware implementations and \"plain JSON\" implementations, so overriding is permitted. + +[Example 58](#example-58-overriding-permitted-in-property-scoped-context): overriding permitted in property scoped context + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%20%20%22%40protected%22%3A%20true%2C%0A%20%20%20%20%20%20%22Organization%22%3A%20%22http%3A%2F%2Fschema.org%2FOrganization%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fschema.org%2Fname%22%2C%0A%20%20%20%20%20%20%22employee%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fschema.org%2Femployee%22%2C%0A%20%20%20%20%20%20%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22%40protected%22%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fschema.org%2FfamilyName%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%22location%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fbased_near%22%2C%0A%20%20%20%20%20%20%20%20%22%40context%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20null%2C%0A%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%7B%20%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%20%7D%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%5D%2C%0A%20%20%22%40type%22%3A%20%22Organization%22%2C%0A%20%20%22name%22%3A%20%22Digital%20Bazaar%22%2C%0A%20%20%22employee%22%20%3A%20%7B%0A%20%20%20%20%22name%22%3A%20%22Sporny%22%2C%0A%20%20%20%20%22location%22%3A%20%7B%22name%22%3A%20%22Blacksburg%2C%20Virginia%22%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": [ + { + – This context reflects the specification used by "plain JSON" implementations + "@version": 1.1, + "@protected": true, + "Organization": "http://schema.org/Organization", + "name": "http://schema.org/name", + "employee": { + "@id": "http://schema.org/employee", + "@context": { + "@protected": true, + "name": "http://schema.org/familyName" + } + ↑ overrides the definition of "name" + } + }, + { + – This context extends the previous one, + – only JSON-LD-aware implementations are expected to use it + "location": { + "@id": "http://xmlns.com/foaf/0.1/based_near", + "@context": [ + null, + ↑ clears the context entirely, including all protected terms + { "@vocab": "http://xmlns.com/foaf/0.1/" } + ] + } + } + ], + "@type": "Organization", + "name": "Digital Bazaar", + "employee" : { + "name": "Sporny", + "location": {"name": "Blacksburg, Virginia"} + } +} +``` + +``` {.expanded .result .nohighlight result-for="overriding permitted in property scoped context-compacted" ignore=""} +[{ + "@type": ["http://schema.org/Organization"], + "http://schema.org/name": [{"@value": "Digital Bazaar"}], + "http://schema.org/employee": [ + { + "http://schema.org/familyName": [{"@value": "Sporny"}], + "http://xmlns.com/foaf/0.1/based_near": [ + { + "http://xmlns.com/foaf/0.1/name": [{"@value": "Blacksburg, Virginia"}] + } + ] + } + ] +}] +``` + + Subject Property Value + --------- ------------------- ---------------------- + \_:b0 rdf:type schema:Organization + \_:b0 schema:name Digital Bazaar + \_:b0 schema:employee \_:b1 + \_:b1 schema:familyName Sporny + \_:b1 foaf:based_near \_:b2 + \_:b2 foaf:name Blacksburg, Virginia + +``` {.turtle content-type="text/turtle" result-for="overriding permitted in property scoped context-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . +@prefix schema: . + +[ + a schema:Organization; + schema:name "Digital Bazaar"; + schema:employee [ + schema:familyName "Sporny"; + foaf:based_near [ + foaf:name "Blacksburg, Virginia" + ]; + ]; +] . +``` + +Note + +By preventing terms from being overridden, protection also prevents any adaptation of a term (e.g., defining a more precise datatype, restricting the term\'s use to lists, etc.). This kind of adaptation is frequent with some general purpose contexts, for which protection would therefore hinder their usability. As a consequence, context publishers should use this feature with care. + +Note + +Protected term definitions are a new feature in JSON-LD 1.1. + +### 4.2 Describing Values[](#describing-values) + +*This section is non-normative.* + +Values are leaf nodes in a graph associated with scalar values such as [strings](https://infra.spec.whatwg.org/#javascript-string), dates, times, and other such atomic values. + +#### 4.2.1 Typed Values[](#typed-values) + +*This section is non-normative.* + +A value with an associated type, also known as a [typed value](#dfn-typed-value), is indicated by associating a value with an [IRI](https://tools.ietf.org/html/rfc3987#section-2) which indicates the value\'s type. Typed values may be expressed in JSON-LD in three ways: + +1. By utilizing the `@type` [keyword](#dfn-keyword) when defining a [term](#dfn-term) within an `@context` section. +2. By utilizing a [value object](#dfn-value-object). +3. By using a native JSON type such as [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), `true`, or `false`. + +The first example uses the `@type` keyword to associate a type with a particular [term](#dfn-term) in the `@context`: + +[Example 59](#example-59-expanded-term-definition-with-type-coercion): Expanded term definition with type coercion + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22modified%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fpurl.org%2Fdc%2Fterms%2Fmodified%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23dateTime%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fdocs%2F1%22%2C%0A%20%20%22modified%22%3A%20%222010-05-29T14%3A17%3A39%2B02%3A00%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "modified": { + "@id": "http://purl.org/dc/terms/modified", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + } + }, + ... + "@id": "http://example.com/docs/1", + "modified": "2010-05-29T14:17:39+02:00", + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Expanded term definition with type coercion-compacted"} +[{ + "@id": "http://example.com/docs/1", + "http://purl.org/dc/terms/modified": [ + { + "@type": "http://www.w3.org/2001/XMLSchema#dateTime", + "@value": "2010-05-29T14:17:39+02:00" + } + ] +}] +``` + + Subject Property Value Value Type + --------------------------- ------------------ --------------------------- -------------- + http://example.com/docs/1 dcterms:modified 2010-05-29T14:17:39+02:00 xsd:dateTime + +``` {.turtle content-type="text/turtle" result-for="Expanded term definition with type coercion-expanded" to-rdf="" aria-busy="false"} +@prefix dcterms: . +@prefix xsd: . + + dcterms:modified "2010-05-29T14:17:39+02:00"^^xsd:dateTime . +``` + +The *modified* key\'s value above is automatically interpreted as a *dateTime* value because of the information specified in the `@context`. The example tabs show how a [JSON-LD processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor) will interpret the data. + +The second example uses the expanded form of setting the type information in the body of a JSON-LD document: + +[Example 60](#example-60-expanded-value-with-type): Expanded value with type + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22modified%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fpurl.org%2Fdc%2Fterms%2Fmodified%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%0A%20%20%22modified%22%3A%20%7B%0A%20%20%20%20%22%40value%22%3A%20%222010-05-29T14%3A17%3A39%2B02%3A00%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23dateTime%22%0A%20%20%7D%0A%20%20%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "modified": { + "@id": "http://purl.org/dc/terms/modified" + } + }, + ... + "modified": { + "@value": "2010-05-29T14:17:39+02:00", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + } + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Expanded value with type-compacted"} +[{ + "http://purl.org/dc/terms/modified": [ + { + "@type": "http://www.w3.org/2001/XMLSchema#dateTime", + "@value": "2010-05-29T14:17:39+02:00" + } + ] +}] +``` + + Subject Property Value Value Type + --------- ------------------ --------------------------- -------------- + \_:b0 dcterms:modified 2010-05-29T14:17:39+02:00 xsd:dateTime + +``` {.turtle content-type="text/turtle" result-for="Expanded value with type-expanded" to-rdf="" aria-busy="false"} +@prefix dcterms: . +@prefix xsd: . + +[ dcterms:modified "2010-05-29T14:17:39+02:00"^^xsd:dateTime ] . +``` + +Both examples above would generate the value `2010-05-29T14:17:39+02:00` with the type `http://www.w3.org/2001/XMLSchema#dateTime`. Note that it is also possible to use a [term](#dfn-term) or a [compact IRI](#dfn-compact-iri) to express the value of a type. + +Note + +The `@type` [keyword](#dfn-keyword) is also used to associate a type with a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node). The concept of a [node type](#dfn-node-type) and a [value type](#dfn-value-type) are distinct. For more on adding types to [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node), see [§ 3.5 Specifying the Type](#specifying-the-type). + +Note + +When expanding, an `@type` defined within a [term definition](#dfn-term-definition) can be associated with a [string](https://infra.spec.whatwg.org/#javascript-string) value to create an expanded [value object](#dfn-value-object), which is described in [§ 4.2.3 Type Coercion](#type-coercion). Type coercion only takes place on string values, not for values which are [maps](https://infra.spec.whatwg.org/#ordered-map), such as [node objects](#dfn-node-object) and [value objects](#dfn-value-object) in their expanded form. + +A node type specifies the type of thing that is being described, like a person, place, event, or web page. A value type specifies the data type of a particular value, such as an integer, a floating point number, or a date. + +[Example 61](#context-sensitivity-for-type): Example demonstrating the context-sensitivity for \@type + +``` nohighlight +{ + ... + "@id": "http://example.org/posts#TripToWestVirginia", + "@type": "http://schema.org/BlogPosting", ← This is a node type + "http://purl.org/dc/terms/modified": { + "@value": "2010-05-29T14:17:39+02:00", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" ← This is a value type + } + ... +} +``` + +The first use of `@type` associates a [node type](#dfn-node-type) (`http://schema.org/BlogPosting`) with the [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node), which is expressed using the `@id` [keyword](#dfn-keyword). The second use of `@type` associates a [value type](#dfn-value-type) (`http://www.w3.org/2001/XMLSchema#dateTime`) with the value expressed using the `@value` [keyword](#dfn-keyword). As a general rule, when `@value` and `@type` are used in the same [map](https://infra.spec.whatwg.org/#ordered-map), the `@type` [keyword](#dfn-keyword) is expressing a [value type](#dfn-value-type). Otherwise, the `@type` [keyword](#dfn-keyword) is expressing a [node type](#dfn-node-type). The example above expresses the following data: + +[Example 62](#example-62-example-demonstrating-the-context-sensitivity-for-type-statements): Example demonstrating the context-sensitivity for \@type (statements) + +Compacted (Input) + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fposts%23TripToWestVirginia%22%2C%0A%20%20%22%40type%22%3A%20%22http%3A%2F%2Fschema.org%2FBlogPosting%22%2C%20%20%0A%20%20%22http%3A%2F%2Fpurl.org%2Fdc%2Fterms%2Fmodified%22%3A%20%7B%0A%20%20%20%20%22%40value%22%3A%20%222010-05-29T14%3A17%3A39%2B02%3A00%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23dateTime%22%20%20%0A%20%20%7D%0A%20%20%0A%7D) + + Subject Property Value Value Type + --------------------------------------------- ------------------ --------------------------- -------------- + http://example.org/posts#TripToWestVirginia rdf:type schema:BlogPosting + http://example.org/posts#TripToWestVirginia dcterms:modified 2010-05-29T14:17:39+02:00 xsd:dateTime + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Example demonstrating the context-sensitivity for @type" to-rdf=""} +@prefix dcterms: . +@prefix schema: . +@prefix xsd: . + + a schema:BlogPosting; + dcterms:modified "2010-05-29T14:17:39+02:00"^^xsd:dateTime . +``` + +#### 4.2.2 JSON Literals[](#json-literals) + +*This section is non-normative.* + +At times, it is useful to include JSON within JSON-LD that is not interpreted as JSON-LD. Generally, a JSON-LD processor will ignore properties which don\'t map to [IRIs](https://tools.ietf.org/html/rfc3987#section-2), but this causes them to be excluded when performing various algorithmic transformations. But, when the data that is being described is, itself, JSON, it\'s important that it survives algorithmic transformations. + +Warning + +JSON-LD is intended to allow native JSON to be interpreted through the use of a [context](#dfn-context). The use of [JSON literals](#dfn-json-literal) creates blobs of data which are not available for interpretation. It is for use only in the rare cases that JSON cannot be represented as JSON-LD. + +When a term is defined with `@type` set to `@json`, a JSON-LD processor will treat the value as a [JSON literal](#dfn-json-literal), rather than interpreting it further as JSON-LD. In the [expanded document form](#dfn-expanded-document-form), such JSON will become the value of `@value` within a [value object](#dfn-value-object) having `"@type": "@json"`. + +When transformed into RDF, the JSON literal will have a lexical form based on a specific serialization of the JSON, as described in [Compaction algorithm](https://www.w3.org/TR/json-ld11-api/#compaction-algorithm) of \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\] and [the JSON datatype](#the-rdf-json-datatype). + +The following example shows an example of a [JSON Literal](#dfn-json-literal) contained as the value of a property. Note that the RDF results use a canonicalized form of the JSON to ensure interoperability between different processors. JSON canonicalization is described in [Data Round Tripping](https://www.w3.org/TR/json-ld11-api/#data-round-tripping) in \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\]. + +[Example 63](#example-63-json-literal): JSON Literal + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22e%22%3A%20%7B%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%2Fjson%22%2C%20%22%40type%22%3A%20%22%40json%22%7D%0A%20%20%7D%2C%0A%20%20%22e%22%3A%20%5B%0A%20%20%20%2056.0%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22d%22%3A%20true%2C%0A%20%20%20%20%20%20%2210%22%3A%20null%2C%0A%20%20%20%20%20%20%221%22%3A%20%5B%20%5D%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "e": {"@id": "http://example.com/vocab/json", "@type": "@json"} + }, + "e": [ + 56.0, + { + "d": true, + "10": null, + "1": [ ] + } + ] +} +``` + +``` {.expanded .result .nohighlight result-for="JSON Literal-compacted"} +[{ + "http://example.com/vocab/json": [{ + "@value": [ + 56.0, + { + "d": true, + "10": null, + "1": [] + } + ], + "@type": "@json" + }] +}] +``` + + Subject Property Value Value Type + --------- ------------------------------- -------------------------------------------- ------------ + \_:b0 http://example.com/vocab/json \[56,{\"1\":\[\],\"10\":null,\"d\":true}\] rdf:JSON + +``` {.turtle .nohighlight content-type="text/turtle" result-for="JSON Literal-compacted" to-rdf=""} +@prefix ex: . +@prefix rdf: . +[ex:json """[56,{"1":[],"10":null,"d":true}]"""^^rdf:JSON] . +``` + +Note + +Generally, when a JSON-LD processor encounters `null`, the associated [entry](https://infra.spec.whatwg.org/#map-entry) or value is removed. However, `null` is a valid JSON token; when used as the value of a [JSON literal](#dfn-json-literal), a `null` value will be preserved. + +#### 4.2.3 Type Coercion[](#type-coercion) + +*This section is non-normative.* + +JSON-LD supports the coercion of [string](https://infra.spec.whatwg.org/#javascript-string) values to particular data types. Type coercion allows someone deploying JSON-LD to use [string](https://infra.spec.whatwg.org/#javascript-string) property values and have those values be interpreted as [typed values](#dfn-typed-value) by associating an [IRI](https://tools.ietf.org/html/rfc3987#section-2) with the value in the expanded [value object](#dfn-value-object) representation. Using type coercion, [string](https://infra.spec.whatwg.org/#javascript-string) value representation can be used without requiring the data type to be specified explicitly with each piece of data. + +Type coercion is specified within an [expanded term definition](#dfn-expanded-term-definition) using the `@type` key. The value of this key expands to an [IRI](https://tools.ietf.org/html/rfc3987#section-2). Alternatively, the [keyword](#dfn-keyword) `@id` or `@vocab` may be used as value to indicate that within the body of a JSON-LD document, a [string](https://infra.spec.whatwg.org/#javascript-string) value of a [term](#dfn-term) coerced to `@id` or `@vocab` is to be interpreted as an [IRI](https://tools.ietf.org/html/rfc3987#section-2). The difference between `@id` and `@vocab` is how values are expanded to [IRIs](https://tools.ietf.org/html/rfc3987#section-2). `@vocab` first tries to expand the value by interpreting it as [term](#dfn-term). If no matching [term](#dfn-term) is found in the [active context](#dfn-active-context), it tries to expand it as an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or a [compact IRI](#dfn-compact-iri) if there\'s a colon in the value; otherwise, it will expand the value using the [active context\'s](#dfn-active-context) [vocabulary mapping](#dfn-vocabulary-mapping), if present. Values coerced to `@id` in contrast are expanded as an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or a [compact IRI](#dfn-compact-iri) if a colon is present; otherwise, they are interpreted as [relative IRI references](https://tools.ietf.org/html/rfc3987#section-6.5). + +Note + +The ability to coerce a value using a [term definition](#dfn-term-definition) is distinct from setting one or more types on a [node object](#dfn-node-object), as the former does not result in new data being added to the graph, while the latter manages node types through adding additional relationships to the graph. + +[Terms](#dfn-term) or [compact IRIs](#dfn-compact-iri) used as the value of a `@type` key may be defined within the same context. This means that one may specify a [term](#dfn-term) like `xsd` and then use `xsd:integer` within the same context definition. + +The example below demonstrates how a JSON-LD author can coerce values to [typed values](#dfn-typed-value) and [IRIs](https://tools.ietf.org/html/rfc3987#section-2). + +[Example 64](#example-64-expanded-term-definition-with-types): Expanded term definition with types + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22xsd%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23%22%2C%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fname%22%2C%0A%20%20%20%20%22age%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fage%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22xsd%3Ainteger%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22homepage%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fhomepage%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22%40id%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fpeople%23john%22%2C%0A%20%20%22name%22%3A%20%22John%20Smith%22%2C%0A%20%20%22age%22%3A%20%2241%22%2C%0A%20%20%22homepage%22%3A%20%5B%0A%20%20%20%20%22http%3A%2F%2Fpersonal.example.org%2F%22%2C%0A%20%20%20%20%22http%3A%2F%2Fwork.example.com%2Fjsmith%2F%22%0A%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "xsd": "http://www.w3.org/2001/XMLSchema#", + "name": "http://xmlns.com/foaf/0.1/name", + "age": { + "@id": "http://xmlns.com/foaf/0.1/age", + "@type": "xsd:integer" + }, + "homepage": { + "@id": "http://xmlns.com/foaf/0.1/homepage", + "@type": "@id" + } + }, + "@id": "http://example.com/people#john", + "name": "John Smith", + "age": "41", + "homepage": [ + "http://personal.example.org/", + "http://work.example.com/jsmith/" + ] +} +``` + +``` {.expanded .result .nohighlight result-for="Expanded term definition with types-compacted"} +[{ + "@id": "http://example.com/people#john", + "http://xmlns.com/foaf/0.1/name": [{"@value": "John Smith"}], + "http://xmlns.com/foaf/0.1/age": [{ + "@value": "41", + "@type": "http://www.w3.org/2001/XMLSchema#integer" + }], + "http://xmlns.com/foaf/0.1/homepage": [{ + "@id": "http://personal.example.org/" + }, { + "@id": "http://work.example.com/jsmith/" + }] +}] +``` + + Subject Property Value Value Type + -------------------------------- --------------- --------------------------------- ------------------------------------------------------ + http://example.com/people#john foaf:name John Smith   + http://example.com/people#john foaf:age 41 xsd:integer + http://example.com/people#john foaf:homepage http://personal.example.org/ [IRI](https://tools.ietf.org/html/rfc3987#section-2) + http://example.com/people#john foaf:homepage http://work.example.com/jsmith/ [IRI](https://tools.ietf.org/html/rfc3987#section-2) + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Expanded term definition with types-expanded" to-rdf=""} +@prefix dcterms: . +@prefix foaf: . + + foaf:name "John Smith"; + foaf:age 41; + foaf:homepage , + +. +``` + +It is important to note that [terms](#dfn-term) are only used in expansion for vocabulary-relative positions, such as for keys and values of [map entries](https://infra.spec.whatwg.org/#map-entry). Values of `@id` are considered to be document-relative, and do not use term definitions for expansion. For example, consider the following: + +[Example 65](#example-65-term-expansion-for-values-not-identifiers): Term expansion for values, not identifiers + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40base%22%3A%20%22http%3A%2F%2Fexample1.com%2F%22%2C%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fexample2.com%2F%22%2C%0A%20%20%20%20%22knows%22%3A%20%7B%22%40type%22%3A%20%22%40vocab%22%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22fred%22%2C%0A%20%20%22knows%22%3A%20%5B%0A%20%20%20%20%7B%22%40id%22%3A%20%22barney%22%2C%20%22mnemonic%22%3A%20%22the%20sidekick%22%7D%2C%0A%20%20%20%20%22barney%22%0A%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@base": "http://example1.com/", + "@vocab": "http://example2.com/", + "knows": {"@type": "@vocab"} + }, + "@id": "fred", + "knows": [ + {"@id": "barney", "mnemonic": "the sidekick"}, + "barney" + ] +} +``` + +``` {.expanded .result .nohighlight result-for="Term expansion for values, not identifiers-compacted"} +[{ + "@id": "http://example1.com/fred", + "http://example2.com/knows": [{ + "@id": "http://example1.com/barney", + "http://example2.com/mnemonic": [{"@value": "the sidekick"}] + }, { + "@id": "http://example2.com/barney" + }] +}] +``` + + Subject Property Value + ---------------------------- ------------------------------ ---------------------------- + http://example1.com/barney http://example2.com/mnemonic the sidekick + http://example1.com/fred http://example2.com/knows http://example1.com/barney + http://example1.com/fred http://example2.com/knows http://example2.com/barney + +``` {.turtle content-type="text/turtle" result-for="Term expansion for values, not identifiers-expanded" to-rdf="" aria-busy="false"} +@prefix xsd: . +@prefix ex1: . +@prefix ex2: . + +ex1:barney ex2:mnemonic "the sidekick" . + +ex1:fred ex2:knows ex1:barney, ex2:barney . +``` + +The unexpected result is that \"barney\" expands to both `http://example1.com/barney` and `http://example2.com/barney`, depending where it is encountered. String values interpreted as [IRIs](https://tools.ietf.org/html/rfc3987#section-2) because of the associated [term definitions](#dfn-term-definition) are typically considered to be document-relative. In some cases, it makes sense to interpret these relative to the vocabulary, prescribed using `"@type": "@vocab"` in the [term definition](#dfn-term-definition), though this can lead to unexpected consequences such as these. + +In the previous example, \"barney\" appears twice, once as the value of `@id`, which is always interpreted as a document-relative IRI, and once as the value of \"fred\", which is defined to be vocabulary-relative, thus the different expanded values. + +For more on this see [§ 4.1.2 Default Vocabulary](#default-vocabulary). + +A variation on the previous example using `"@type": "@id"` instead of `@vocab` illustrates the behavior of interpreting \"barney\" relative to the document: + +[Example 66](#example-66-terms-not-expanded-when-document-relative): Terms not expanded when document-relative + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40base%22%3A%20%22http%3A%2F%2Fexample1.com%2F%22%2C%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fexample2.com%2F%22%2C%0A%20%20%20%20%22knows%22%3A%20%7B%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22fred%22%2C%0A%20%20%22knows%22%3A%20%5B%0A%20%20%20%20%7B%22%40id%22%3A%20%22barney%22%2C%20%22mnemonic%22%3A%20%22the%20sidekick%22%7D%2C%0A%20%20%20%20%22barney%22%0A%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@base": "http://example1.com/", + "@vocab": "http://example2.com/", + "knows": {"@type": "@id"} + }, + "@id": "fred", + "knows": [ + {"@id": "barney", "mnemonic": "the sidekick"}, + "barney" + ] +} +``` + +``` {.expanded .result .nohighlight result-for="Terms not expanded when document-relative-compacted"} +[{ + "@id": "http://example1.com/fred", + "http://example2.com/knows": [{ + "@id": "http://example1.com/barney", + "http://example2.com/mnemonic": [{"@value": "the sidekick"}] + }, { + "@id": "http://example1.com/barney" + }] +}] +``` + +``` {.turtle content-type="text/turtle" result-for="Terms not expanded when document-relative-expanded" to-rdf="" aria-busy="false"} +@prefix xsd: . +@prefix ex1: . +@prefix ex2: . + +ex1:barney ex2:mnemonic "the sidekick" . + +ex1:fred ex2:knows ex1:barney, ex1:barney . +``` + +Note + +The triple `ex1:fred ex2:knows ex1:barney .` is emitted twice, but exists only once in an output dataset, as it is a duplicate triple. + +Terms may also be defined using [IRIs](https://tools.ietf.org/html/rfc3987#section-2) or [compact IRIs](#dfn-compact-iri). This allows coercion rules to be applied to keys which are not represented as a simple [term](#dfn-term). For example: + +[Example 67](#example-67-term-definitions-using-iris-and-compact-iris): Term definitions using IRIs and compact IRIs + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22xsd%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23%22%2C%0A%20%20%20%20%22foaf%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%2C%0A%20%20%20%20%22foaf%3Aage%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fage%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22xsd%3Ainteger%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fhomepage%22%3A%20%7B%0A%20%20%20%20%20%20%22%40type%22%3A%20%22%40id%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22foaf%3Aname%22%3A%20%22John%20Smith%22%2C%0A%20%20%22foaf%3Aage%22%3A%20%2241%22%2C%0A%20%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fhomepage%22%3A%20%5B%0A%20%20%20%20%22http%3A%2F%2Fpersonal.example.org%2F%22%2C%0A%20%20%20%20%22http%3A%2F%2Fwork.example.com%2Fjsmith%2F%22%0A%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "xsd": "http://www.w3.org/2001/XMLSchema#", + "foaf": "http://xmlns.com/foaf/0.1/", + "foaf:age": { + "@id": "http://xmlns.com/foaf/0.1/age", + "@type": "xsd:integer" + }, + "http://xmlns.com/foaf/0.1/homepage": { + "@type": "@id" + } + }, + "foaf:name": "John Smith", + "foaf:age": "41", + "http://xmlns.com/foaf/0.1/homepage": [ + "http://personal.example.org/", + "http://work.example.com/jsmith/" + ] +} +``` + +``` {.expanded .result .nohighlight result-for="Term definitions using IRIs and compact IRIs-compacted"} +[{ + "http://xmlns.com/foaf/0.1/age": [{"@type": "http://www.w3.org/2001/XMLSchema#integer", "@value": "41"}], + "http://xmlns.com/foaf/0.1/name": [{"@value": "John Smith"}], + "http://xmlns.com/foaf/0.1/homepage": [ + {"@id": "http://personal.example.org/"}, + {"@id": "http://work.example.com/jsmith/"} + ] +} +] +``` + + Subject Property Value Value Type + --------- --------------- --------------------------------- ------------- + \_:b0 foaf:age 41 xsd:integer + \_:b0 foaf:name John Smith + \_:b0 foaf:homepage http://personal.example.org/ + \_:b0 foaf:homepage http://work.example.com/jsmith/ + +``` {.turtle content-type="text/turtle" result-for="Term definitions using IRIs and compact IRIs-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . +@prefix xsd: . + + [ + foaf:age 41; + foaf:homepage , + ; + foaf:name "John Smith" +] . +``` + +In this case the `@id` definition in the term definition is optional. If it does exist, the [IRI](https://tools.ietf.org/html/rfc3987#section-2) or [compact IRI](#dfn-compact-iri) representing the term will always be expanded to [IRI](https://tools.ietf.org/html/rfc3987#section-2) defined by the `@id` key---regardless of whether a prefix is defined or not. + +Type coercion is always performed using the unexpanded value of the key. In the example above, that means that type coercion is done looking for `foaf:age` in the [active context](#dfn-active-context) and not for the corresponding, expanded [IRI](https://tools.ietf.org/html/rfc3987#section-2) `http://xmlns.com/foaf/0.1/age`. + +Note + +Keys in the context are treated as [terms](#dfn-term) for the purpose of expansion and value coercion. At times, this may result in multiple representations for the same expanded IRI. For example, one could specify that `dog` and `cat` both expanded to `http://example.com/vocab#animal`. Doing this could be useful for establishing different type coercion or language specification rules. + +#### 4.2.4 String Internationalization[](#string-internationalization) + +*This section is non-normative.* + +At times, it is important to annotate a [string](https://infra.spec.whatwg.org/#javascript-string) with its language. In JSON-LD this is possible in a variety of ways. First, it is possible to define a [default language](#dfn-default-language) for a JSON-LD document by setting the `@language` key in the [context](#dfn-context): + +[Example 68](#example-68-setting-the-default-language-of-a-json-ld-document): Setting the default language of a JSON-LD document + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fexample.org%2Fname%22%2C%0A%20%20%20%20%22occupation%22%3A%20%22http%3A%2F%2Fexample.org%2Foccupation%22%2C%0A%20%20%20%20%0A%20%20%20%20%22%40language%22%3A%20%22ja%22%0A%20%20%7D%2C%0A%20%20%22name%22%3A%20%22%E8%8A%B1%E6%BE%84%22%2C%0A%20%20%22occupation%22%3A%20%22%E7%A7%91%E5%AD%A6%E8%80%85%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "name": "http://example.org/name", + "occupation": "http://example.org/occupation", + ... + "@language": "ja" + }, + "name": "花澄", + "occupation": "科学者" +} +``` + +``` {.expanded .result .nohighlight result-for="Setting the default language of a JSON-LD document-compacted"} +[{ + "http://example.org/name": [{"@value": "花澄", "@language": "ja"}], + "http://example.org/occupation": [{"@value": "科学者", "@language": "ja"}] +}] +``` + + Subject Property Value Language + --------- ------------------------------- -------- ---------- + \_:b0 http://example.org/name 花澄 ja + \_:b0 http://example.org/occupation 科学者 ja + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Setting the default language of a JSON-LD document-expanded" to-rdf=""} +@prefix ex: . + +[ + ex:name "花澄"@ja; + ex:occupation "科学者"@ja +] . +``` + +The example above would associate the `ja` language tag with the two [strings](https://infra.spec.whatwg.org/#javascript-string) *花澄* and *科学者* [Languages tags](https://tools.ietf.org/html/bcp47#section-2) are defined in \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\]. The [default language](#dfn-default-language) applies to all [string](https://infra.spec.whatwg.org/#javascript-string) values that are not [type coerced](#type-coercion). + +To clear the [default language](#dfn-default-language) for a subtree, `@language` can be set to `null` in an intervening context, such as a [scoped context](#dfn-scoped-context) as follows: + +[Example 69](#example-69-clearing-default-language): Clearing default language + +``` nohighlight +{ + "@context": { + ... + "@version": 1.1, + "@vocab": "http://example.com/", + "@language": "ja", + "details": { + "@context": { + "@language": null + } + } + }, + "name": "花澄", + "details": {"occupation": "Ninja"} +} +``` + +Second, it is possible to associate a language with a specific [term](#dfn-term) using an [expanded term definition](#dfn-expanded-term-definition): + +[Example 70](#example-70-expanded-term-definition-with-language): Expanded term definition with language + +``` nohighlight +{ + "@context": { + ... + "ex": "http://example.com/vocab/", + "@language": "ja", + "name": { "@id": "ex:name", "@language": null }, + "occupation": { "@id": "ex:occupation" }, + "occupation_en": { "@id": "ex:occupation", "@language": "en" }, + "occupation_cs": { "@id": "ex:occupation", "@language": "cs" } + }, + "name": "Yagyū Muneyoshi", + "occupation": "忍者", + "occupation_en": "Ninja", + "occupation_cs": "Nindža", + ... +} +``` + +The example above would associate *忍者* with the specified default language tag `ja`, *Ninja* with the language tag `en`, and *Nindža* with the language tag `cs`. The value of `name`, *Yagyū Muneyoshi* wouldn\'t be associated with any language tag since `@language` was reset to [null](https://infra.spec.whatwg.org/#nulls) in the [expanded term definition](#dfn-expanded-term-definition). + +Note + +Language associations are only applied to plain [strings](https://infra.spec.whatwg.org/#javascript-string). [Typed values](#dfn-typed-value) or values that are subject to [type coercion](#type-coercion) are not language tagged. + +Just as in the example above, systems often need to express the value of a property in multiple languages. Typically, such systems also try to ensure that developers have a programmatically easy way to navigate the data structures for the language-specific data. In this case, [language maps](#dfn-language-map) may be utilized. + +[Example 71](#example-71-language-map-expressing-a-property-in-three-languages): Language map expressing a property in three languages + +``` nohighlight +{ + "@context": { + ... + "occupation": { "@id": "ex:occupation", "@container": "@language" } + }, + "name": "Yagyū Muneyoshi", + "occupation": { + "ja": "忍者", + "en": "Ninja", + "cs": "Nindža" + } + ... +} +``` + +The example above expresses exactly the same information as the previous example but consolidates all values in a single property. To access the value in a specific language in a programming language supporting dot-notation accessors for object properties, a developer may use the `property.language` pattern (when languages are limited to the primary language sub-tag, and do not depend on other sub-tags, such as `"en-us"`). For example, to access the occupation in English, a developer would use the following code snippet: `obj.occupation.en`. + +Third, it is possible to override the [default language](#dfn-default-language) by using a [value object](#dfn-value-object): + +[Example 72](#example-72-overriding-default-language-using-an-expanded-value): Overriding default language using an expanded value + +``` nohighlight +{ + "@context": { + ... + "@language": "ja" + }, + "name": "花澄", + "occupation": { + "@value": "Scientist", + "@language": "en" + } +} +``` + +This makes it possible to specify a plain string by omitting the `@language` tag or setting it to `null` when expressing it using a [value object](#dfn-value-object): + +[Example 73](#example-73-removing-language-information-using-an-expanded-value): Removing language information using an expanded value + +``` nohighlight +{ + "@context": { + ... + "@language": "ja" + }, + "name": { + "@value": "Frank" + }, + "occupation": { + "@value": "Ninja", + "@language": "en" + }, + "speciality": "手裏剣" +} +``` + +See [§ 9.8 Language Maps](#language-maps) for a description of using [language maps](#dfn-language-map) to set the language of mapped values. + +##### 4.2.4.1 Base Direction[](#base-direction) + +*This section is non-normative.* + +It is also possible to annotate a [string](https://infra.spec.whatwg.org/#javascript-string), or [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string), with its [base direction](#dfn-base-direction). As with language, it is possible to define a [default base direction](#dfn-base-direction) for a JSON-LD document by setting the `@direction` key in the [context](#dfn-context): + +[Example 74](#example-74-setting-the-default-base-direction-of-a-json-ld-document): Setting the default base direction of a JSON-LD document + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle (drops direction) + +Turtle (with datatype) + +Turtle (with bnode structure) + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22title%22%3A%20%22http%3A%2F%2Fexample.org%2Ftitle%22%2C%0A%20%20%20%20%22publisher%22%3A%20%22http%3A%2F%2Fexample.org%2Fpublisher%22%2C%0A%20%20%20%20%0A%20%20%20%20%22%40language%22%3A%20%22ar-EG%22%2C%0A%20%20%20%20%22%40direction%22%3A%20%22rtl%22%0A%20%20%7D%2C%0A%20%20%22title%22%3A%20%22HTML%20%D9%88%20CSS%3A%20%D8%AA%D8%B5%D9%85%D9%8A%D9%85%20%D9%88%20%D8%A5%D9%86%D8%B4%D8%A7%D8%A1%20%D9%85%D9%88%D8%A7%D9%82%D8%B9%20%D8%A7%D9%84%D9%88%D9%8A%D8%A8%22%2C%0A%20%20%22publisher%22%3A%20%22%D9%85%D9%83%D8%AA%D8%A8%D8%A9%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "title": "http://example.org/title", + "publisher": "http://example.org/publisher", + ... + "@language": "ar-EG", + "@direction": "rtl" + }, + "title": "HTML و CSS: تصميم و إنشاء مواقع الويب", + "publisher": "مكتبة" +} +``` + +``` {.expanded .result .nohighlight result-for="Setting the default base direction of a JSON-LD document-compacted"} +[{ + "http://example.org/title": [{"@value": "HTML و CSS: تصميم و إنشاء مواقع الويب", "@language": "ar-EG", "@direction": "rtl"}], + "http://example.org/publisher": [{"@value": "مكتبة", "@language": "ar-EG", "@direction": "rtl"}] +}] +``` + + Subject Property Value Language Direction + --------- ------------------------------ --------------------------------------- ---------- ----------- + \_:b0 http://example.org/title HTML و CSS: تصميم و إنشاء مواقع الويب ar-EG rtl + \_:b0 http://example.org/publisher مكتبة ar-EG rtl + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Setting the default base direction of a JSON-LD document-expanded" to-rdf=""} +@prefix ex: . + +# Note that this version drops the base direction. +[ + ex:title "HTML و CSS: تصميم و إنشاء مواقع الويب"@ar-EG; + ex:publisher "مكتبة"@ar-EG +] . +``` + +``` {.turtle-dt .nohighlight content-type="text/turtle" result-for="Setting the default base direction of a JSON-LD document-expanded" options="rdfDirection=i18n-datatype" to-rdf=""} +@prefix ex: . +@prefix i18n: . + +# Note that this version preserves the base direction using a datatype. +[ + ex:title "HTML و CSS: تصميم و إنشاء مواقع الويب"^^i18n:ar-EG_rtl; + ex:publisher "مكتبة"^^i18n:ar-EG_rtl +] . +``` + +``` {.turtle-bn .nohighlight content-type="text/turtle" result-for="Setting the default base direction of a JSON-LD document-expanded" options="rdfDirection=compound-literal" to-rdf=""} +@prefix ex: . + +# Note that this version preserves the base direction using a bnode structure. +[ + ex:title [ + rdf:value "HTML و CSS: تصميم و إنشاء مواقع الويب", + rdf:language "ar-EG", + rdf:direction "rtl" + ]; + ex:publisher [ + rdf:value "مكتبة", + rdf:language "ar-EG", + rdf:direction "rtl" + ] +] . +``` + +The example above would associate the `ar-EG` language tag and \"rtl\" base direction with the two [strings](https://infra.spec.whatwg.org/#javascript-string) *HTML و CSS: تصميم و إنشاء مواقع الويب* and *مكتبة*. The [default base direction](#dfn-base-direction) applies to all [string](https://infra.spec.whatwg.org/#javascript-string) values that are not [type coerced](#type-coercion). + +To clear the [default base direction](#dfn-base-direction) for a subtree, `@direction` can be set to `null` in an intervening context, such as a [scoped context](#dfn-scoped-context) as follows: + +[Example 75](#example-75-clearing-default-base-direction): Clearing default base direction + +``` nohighlight +{ + "@context": { + ... + "@version": 1.1, + "@vocab": "http://example.com/", + "@language": "ar-EG", + "@direction": "rtl", + "details": { + "@context": { + "@direction": null + } + } + }, + "title": "HTML و CSS: تصميم و إنشاء مواقع الويب", + "details": {"genre": "Technical Publication"} +} +``` + +Second, it is possible to associate a base direction with a specific [term](#dfn-term) using an [expanded term definition](#dfn-expanded-term-definition): + +[Example 76](#example-76-expanded-term-definition-with-language-and-direction): Expanded term definition with language and direction + +``` nohighlight +{ + "@context": { + ... + "@version": 1.1, + "@language": "ar-EG", + "@direction": "rtl", + "ex": "http://example.com/vocab/", + "publisher": { "@id": "ex:publisher", "@direction": null }, + "title": { "@id": "ex:title" }, + "title_en": { "@id": "ex:title", "@language": "en", "@direction": "ltr" } + }, + "publisher": "مكتبة", + "title": "HTML و CSS: تصميم و إنشاء مواقع الويب", + "title_en": "HTML and CSS: Design and Build Websites", + ... +} +``` + +The example above would create three properties: + + Subject Property Value Language Direction + --------- ------------------------------------ ----------------------------------------- ---------- ----------- + \_:b0 http://example.com/vocab/publisher مكتبة ar-EG + \_:b0 http://example.com/vocab/title HTML و CSS: تصميم و إنشاء مواقع الويب ar-EG `rtl` + \_:b0 http://example.com/vocab/title HTML and CSS: Design and Build Websites en `ltr` + +Note + +Base direction associations are only applied to plain [strings](https://infra.spec.whatwg.org/#javascript-string) and [language-tagged strings](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string). [Typed values](#dfn-typed-value) or values that are subject to [type coercion](#type-coercion) are not given a base direction. + +Third, it is possible to override the [default base direction](#dfn-base-direction) by using a [value object](#dfn-value-object): + +[Example 77](#example-77-overriding-default-language-and-default-base-direction-using-an-expanded-value): Overriding default language and default base direction using an expanded value + +``` nohighlight +{ + "@context": { + ... + "@language": "ar-EG", + "@direction": "rtl" + }, + "title": "HTML و CSS: تصميم و إنشاء مواقع الويب", + "author": { + "@value": "Jon Duckett", + "@language": "en", + "@direction": null + } +} +``` + +See [Strings on the Web: Language and Direction Metadata](https://www.w3.org/TR/string-meta/) \[[string-meta](#bib-string-meta "Strings on the Web: Language and Direction Metadata")\] for a deeper discussion of [base direction](#dfn-base-direction). + +### 4.3 Value Ordering[](#sets-and-lists) + +*This section is non-normative.* + +A JSON-LD author can express multiple values in a compact way by using [arrays](https://infra.spec.whatwg.org/#list). Since graphs do not describe ordering for links between nodes, arrays in JSON-LD do not convey any ordering of the contained elements by default. This is exactly the opposite from regular JSON arrays, which are ordered by default. For example, consider the following simple document: + +[Example 78](#example-78-multiple-values-with-no-inherent-order): Multiple values with no inherent order + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%22foaf%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%7D%2C%0A%20%20%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fpeople%23joebob%22%2C%0A%20%20%22foaf%3Anick%22%3A%20%5B%20%22joe%22%2C%20%22bob%22%2C%20%22JB%22%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": {"foaf": "http://xmlns.com/foaf/0.1/"}, + ... + "@id": "http://example.org/people#joebob", + "foaf:nick": [ "joe", "bob", "JB" ], + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Multiple values with no inherent order-compacted"} +[{ + "@id": "http://example.org/people#joebob", + "http://xmlns.com/foaf/0.1/nick": [ + {"@value": "joe"}, + {"@value": "bob"}, + {"@value": "JB"} + ] +}] +``` + + Subject Property Value + ---------------------------------- ----------- ------- + http://example.org/people#joebob foaf:nick joe + http://example.org/people#joebob foaf:nick bob + http://example.org/people#joebob foaf:nick JB + +``` {.turtle content-type="text/turtle" result-for="Multiple values with no inherent order-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . + + foaf:nick + "joe", "bob", "JB" . +``` + +Multiple values may also be expressed using the expanded form: + +[Example 79](#example-79-using-an-expanded-form-to-set-multiple-values): Using an expanded form to set multiple values + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%22dcterms%22%3A%20%22http%3A%2F%2Fpurl.org%2Fdc%2Fterms%2F%22%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Farticles%2F8%22%2C%0A%20%20%22dcterms%3Atitle%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22%40value%22%3A%20%22Das%20Kapital%22%2C%0A%20%20%20%20%20%20%22%40language%22%3A%20%22de%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22%40value%22%3A%20%22Capital%22%2C%0A%20%20%20%20%20%20%22%40language%22%3A%20%22en%22%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": {"dcterms": "http://purl.org/dc/terms/"}, + "@id": "http://example.org/articles/8", + "dcterms:title": [ + { + "@value": "Das Kapital", + "@language": "de" + }, + { + "@value": "Capital", + "@language": "en" + } + ] +} +``` + +``` {.expanded .result .nohighlight result-for="Using an expanded form to set multiple values-compacted"} +[{ + "@id": "http://example.org/articles/8", + "http://purl.org/dc/terms/title": [ + {"@value": "Das Kapital", "@language": "de"}, + {"@value": "Capital", "@language": "en"} + ] +}] +``` + + Subject Property Value Language + ------------------------------- --------------- ------------- ---------- + http://example.org/articles/8 dcterms:title Das Kapital de + http://example.org/articles/8 dcterms:title Capital en + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Using an expanded form to set multiple values-expanded" to-rdf=""} +@prefix dcterms: . + + dcterms:title + "Das Kapital"@de, "Capital"@en . +``` + +Note + +The example shown above would generates statement, again with no inherent order. + +Although multiple values of a property are typically of the same type, JSON-LD places no restriction on this, and a property may have values of different types: + +[Example 80](#example-80-multiple-array-values-of-different-types): Multiple array values of different types + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%22ex%22%3A%20%22http%3A%2F%2Fexample.org%2F%22%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fpeople%23michael%22%2C%0A%20%20%22ex%3Aname%22%3A%20%5B%0A%20%20%20%20%22Michael%22%2C%0A%20%20%20%20%7B%22%40value%22%3A%20%22Mike%22%7D%2C%0A%20%20%20%20%7B%22%40value%22%3A%20%22Miguel%22%2C%20%22%40language%22%3A%20%22es%22%7D%2C%0A%20%20%20%20%7B%20%22%40id%22%3A%20%22https%3A%2F%2Fwww.wikidata.org%2Fwiki%2FQ4927524%22%20%7D%2C%0A%20%20%20%2042%0A%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": {"ex": "http://example.org/"}, + "@id": "http://example.org/people#michael", + "ex:name": [ + "Michael", + {"@value": "Mike"}, + {"@value": "Miguel", "@language": "es"}, + { "@id": "https://www.wikidata.org/wiki/Q4927524" }, + 42 + ] +} +``` + +``` {.expanded .result .nohighlight result-for="Multiple array values of different types-compacted"} +[{ + "@id": "http://example.org/people#michael", + "http://example.org/name": [ + {"@value": "Michael"}, + {"@value": "Mike"}, + {"@value": "Miguel", "@language": "es"}, + {"@id": "https://www.wikidata.org/wiki/Q4927524" }, + {"@value": 42} + ] +}] +``` + + Subject Property Value Language Value Type + ----------------------------------- ------------------------- ---------------------------------------- ---------- ------------- + http://example.org/people#michael http://example.org/name Michael + http://example.org/people#michael http://example.org/name Mike + http://example.org/people#michael http://example.org/name Miguel es + http://example.org/people#michael http://example.org/name https://www.wikidata.org/wiki/Q4927524 + http://example.org/people#michael http://example.org/name 42   xsd:integer + +``` {.turtle content-type="text/turtle" result-for="Multiple array values of different types-expanded" to-rdf="" aria-busy="false"} +@prefix ex: . + + ex:name + "Michael", + "Mike", + "Miguel"@es, + , + 42 . +``` + +Note + +When viewed as statements, the values have no inherent order. + +#### 4.3.1 Lists[](#lists) + +*This section is non-normative.* + +As the notion of ordered collections is rather important in data modeling, it is useful to have specific language support. In JSON-LD, a list may be represented using the `@list` [keyword](#dfn-keyword) as follows: + +[Example 81](#example-81-an-ordered-collection-of-values-in-json-ld): An ordered collection of values in JSON-LD + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%22foaf%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%7D%2C%0A%20%20%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fpeople%23joebob%22%2C%0A%20%20%22foaf%3Anick%22%3A%20%7B%0A%20%20%20%20%22%40list%22%3A%20%5B%20%22joe%22%2C%20%22bob%22%2C%20%22jaybee%22%20%5D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": {"foaf": "http://xmlns.com/foaf/0.1/"}, + ... + "@id": "http://example.org/people#joebob", + "foaf:nick": { + "@list": [ "joe", "bob", "jaybee" ] + }, + ... +} +``` + +``` {.expanded .result .nohighlight result-for="An ordered collection of values in JSON-LD-compacted"} +[{ + "@id": "http://example.org/people#joebob", + "http://xmlns.com/foaf/0.1/nick": [{ + "@list": [ + {"@value": "joe"}, + {"@value": "bob"}, + {"@value": "jaybee"} + ] + }] +}] +``` + + Subject Property Value + ---------------------------------- ----------- --------- + http://example.org/people#joebob foaf:nick \_:b0 + \_:b0 rdf:first joe + \_:b0 rdf:rest \_:b1 + \_:b1 rdf:first bob + \_:b1 rdf:rest \_:b2 + \_:b2 rdf:first jaybee + \_:b2 rdf:rest rdf:nil + +``` {.turtle content-type="text/turtle" result-for="An ordered collection of values in JSON-LD-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . + + foaf:nick ("joe" "bob" "jaybee") . +``` + +This describes the use of this [array](https://infra.spec.whatwg.org/#list) as being ordered, and order is maintained when processing a document. If every use of a given multi-valued property is a list, this may be abbreviated by setting `@container` to `@list` in the [context](#dfn-context): + +[Example 82](#example-82-specifying-that-a-collection-is-ordered-in-the-context): Specifying that a collection is ordered in the context + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%0A%20%20%20%20%22nick%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fnick%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40list%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fpeople%23joebob%22%2C%0A%20%20%22nick%22%3A%20%5B%20%22joe%22%2C%20%22bob%22%2C%20%22jaybee%22%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + ... + "nick": { + "@id": "http://xmlns.com/foaf/0.1/nick", + "@container": "@list" + } + }, + ... + "@id": "http://example.org/people#joebob", + "nick": [ "joe", "bob", "jaybee" ], + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Specifying that a collection is ordered in the context-compacted"} +[{ + "@id": "http://example.org/people#joebob", + "http://xmlns.com/foaf/0.1/nick": [{ + "@list": [ + {"@value": "joe"}, + {"@value": "bob"}, + {"@value": "jaybee"} + ] + }] +}] +``` + + Subject Property Value + ---------------------------------- ----------- --------- + http://example.org/people#joebob foaf:nick \_:b0 + \_:b0 rdf:first joe + \_:b0 rdf:rest \_:b1 + \_:b1 rdf:first bob + \_:b1 rdf:rest \_:b2 + \_:b2 rdf:first jaybee + \_:b2 rdf:rest rdf:nil + +``` {.turtle content-type="text/turtle" result-for="Specifying that a collection is ordered in the context-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . + + foaf:nick ("joe" "bob" "jaybee") . +``` + +The implementation of [lists](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab) in RDF depends on linking anonymous nodes together using the properties `rdf:first` and `rdf:rest`, with the end of the list defined as the resource `rdf:nil`, as the \"statements\" tab illustrates. This allows order to be represented within an unordered set of statements. + +Both JSON-LD and Turtle provide shortcuts for representing ordered lists. + +In JSON-LD 1.1, lists of lists, where the value of a [list object](#dfn-list-object), may itself be a [list object](#dfn-list-object), are fully supported. + +Note that the `"@container": "@list"` definition recursively describes array values of lists as being, themselves, lists. For example, in [The GeoJSON Format](https://tools.ietf.org/html/rfc7946) (see \[[RFC7946](#bib-rfc7946 "The GeoJSON Format")\]), *coordinates* are an ordered list of *positions*, which are represented as an array of two or more numbers: + +[Example 83](#example-83-coordinates-expressed-in-geojson): Coordinates expressed in GeoJSON + +``` {.changed .nohighlight content-type="application/json"} +{ + "type": "Feature", + "bbox": [-10.0, -10.0, 10.0, 10.0], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [-10.0, -10.0], + [10.0, -10.0], + [10.0, 10.0], + [-10.0, -10.0] + ] + ] + } + //... +} +``` + +For these examples, it\'s important that values expressed within *bbox* and *coordinates* maintain their order, which requires the use of embedded list structures. In JSON-LD 1.1, we can express this using recursive lists, by simply adding the appropriate context definition: + +[Example 84](#example-84-coordinates-expressed-in-json-ld): Coordinates expressed in JSON-LD + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40vocab%22%3A%20%22https%3A%2F%2Fpurl.org%2Fgeojson%2Fvocab%23%22%2C%0A%20%20%20%20%22type%22%3A%20%22%40type%22%2C%0A%20%20%20%20%22bbox%22%3A%20%7B%22%40container%22%3A%20%22%40list%22%7D%2C%0A%20%20%20%20%22coordinates%22%3A%20%7B%22%40container%22%3A%20%22%40list%22%7D%0A%20%20%7D%2C%0A%20%20%22type%22%3A%20%22Feature%22%2C%0A%20%20%22bbox%22%3A%20%5B-10.0%2C%20-10.0%2C%2010.0%2C%2010.0%5D%2C%0A%20%20%22geometry%22%3A%20%7B%0A%20%20%20%20%22type%22%3A%20%22Polygon%22%2C%0A%20%20%20%20%22coordinates%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B-10.0%2C%20-10.0%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B10.0%2C%20-10.0%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B10.0%2C%2010.0%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B-10.0%2C%20-10.0%5D%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%5D%0A%20%20%7D%0A%20%20%0A%7D) + +``` {.compacted .input .selected .changed content-type="application/json" aria-busy="false"} +{ + "@context": { + "@vocab": "https://purl.org/geojson/vocab#", + "type": "@type", + "bbox": {"@container": "@list"}, + "coordinates": {"@container": "@list"} + }, + "type": "Feature", + "bbox": [-10.0, -10.0, 10.0, 10.0], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [-10.0, -10.0], + [10.0, -10.0], + [10.0, 10.0], + [-10.0, -10.0] + ] + ] + } + //... +} +``` + +``` {.expanded .result .nohighlight result-for="Coordinates expressed in JSON-LD-compacted"} +[{ + "@type": ["https://purl.org/geojson/vocab#Feature"], + "https://purl.org/geojson/vocab#bbox": [{ + "@list": [ + {"@value": -10.0}, + {"@value": -10.0}, + {"@value": 10.0}, + {"@value": 10.0} + ] + }], + "https://purl.org/geojson/vocab#geometry": [{ + "@type": ["https://purl.org/geojson/vocab#Polygon"], + "https://purl.org/geojson/vocab#coordinates": [{ + "@list": [{ + "@list": [ + {"@list": [{"@value": -10.0}, {"@value": -10.0}]}, + {"@list": [{"@value": 10.0}, {"@value": -10.0}]}, + {"@list": [{"@value": 10.0}, {"@value": 10.0}]}, + {"@list": [{"@value": -10.0}, {"@value": -10.0}]} + ] + }] + }] + }] +}] +``` + + Subject Property Value Value Type + --------- --------------------- ----------------- ------------- + \_:b0 rdf:type geojson:Feature + \_:b0 geojson:bbox \_:b1 + \_:b0 geojson:geometry \_:b5 + \_:b1 rdf:first -10 xsd:integer + \_:b1 rdf:rest \_:b2 + \_:b2 rdf:first -10 xsd:integer + \_:b2 rdf:rest \_:b3 + \_:b3 rdf:first 10 xsd:integer + \_:b3 rdf:rest \_:b4 + \_:b4 rdf:first 10 xsd:integer + \_:b4 rdf:rest rdf:nil + \_:b5 rdf:type geojson:Polygon + \_:b5 geojson:coordinates \_:b6 + \_:b6 rdf:first \_:b7 + \_:b6 rdf:rest rdf:nil + \_:b7 rdf:first \_:b8 + \_:b7 rdf:rest \_:b10 + \_:b8 rdf:first -10 xsd:integer + \_:b8 rdf:rest \_:b9 + \_:b9 rdf:first -10 xsd:integer + \_:b9 rdf:rest rdf:nil + \_:b10 rdf:first \_:b11 + \_:b10 rdf:rest \_:b13 + \_:b11 rdf:first 10 xsd:integer + \_:b11 rdf:rest \_:b12 + \_:b12 rdf:first -10 xsd:integer + \_:b12 rdf:rest rdf:nil + \_:b13 rdf:first \_:b14 + \_:b13 rdf:rest \_:b16 + \_:b14 rdf:first 10 xsd:integer + \_:b14 rdf:rest \_:b15 + \_:b15 rdf:first 10 xsd:integer + \_:b15 rdf:rest rdf:nil + \_:b16 rdf:first \_:b17 + \_:b16 rdf:rest rdf:nil + \_:b17 rdf:first -10 xsd:integer + \_:b17 rdf:rest \_:b18 + \_:b18 rdf:first -10 xsd:integer + \_:b18 rdf:rest rdf:nil + +``` {.turtle content-type="text/turtle" result-for="Coordinates expressed in JSON-LD-expanded" to-rdf="" aria-busy="false"} +@prefix geojson: . + +[ + a geojson:Feature ; + geojson:bbox (-10 -10 10 10) ; + geojson:geometry [ + a geojson:Polygon ; + geojson:coordinates ( + ( + (-10 -10) + (10 -10) + (10 10) + (-10 -10) + ) + ) + ] +] . +``` + +Note that *coordinates* includes three levels of lists. + +Values of terms associated with an `@list` container are always represented in the form of an [array](https://infra.spec.whatwg.org/#list), even if there is just a single value or no value at all. + +#### 4.3.2 Sets[](#sets) + +*This section is non-normative.* + +While `@list` is used to describe *ordered lists*, the `@set` keyword is used to describe *unordered sets*. The use of `@set` in the body of a JSON-LD document is optimized away when processing the document, as it is just syntactic sugar. However, `@set` is helpful when used within the context of a document. Values of terms associated with an `@set` container are always represented in the form of an [array](https://infra.spec.whatwg.org/#list), even if there is just a single value that would otherwise be optimized to a non-array form in compact form (see [§ 5.2 Compacted Document Form](#compacted-document-form)). This makes post-processing of JSON-LD documents easier as the data is always in array form, even if the array only contains a single value. + +[Example 85](#example-85-an-unordered-collection-of-values-in-json-ld): An unordered collection of values in JSON-LD + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%22foaf%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%7D%2C%0A%20%20%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fpeople%23joebob%22%2C%0A%20%20%22foaf%3Anick%22%3A%20%7B%0A%20%20%20%20%22%40set%22%3A%20%5B%20%22joe%22%2C%20%22bob%22%2C%20%22jaybee%22%20%5D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": {"foaf": "http://xmlns.com/foaf/0.1/"}, + ... + "@id": "http://example.org/people#joebob", + "foaf:nick": { + "@set": [ "joe", "bob", "jaybee" ] + }, + ... +} +``` + +``` {.expanded .result .nohighlight result-for="An unordered collection of values in JSON-LD-compacted"} +[{ + "@id": "http://example.org/people#joebob", + "http://xmlns.com/foaf/0.1/nick": [ + {"@value": "joe"}, + {"@value": "bob"}, + {"@value": "jaybee"} + ] +}] +``` + + Subject Property Value + ---------------------------------- ----------- -------- + http://example.org/people#joebob foaf:nick joe + http://example.org/people#joebob foaf:nick bob + http://example.org/people#joebob foaf:nick jaybee + +``` {.turtle content-type="text/turtle" result-for="An unordered collection of values in JSON-LD-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . + + foaf:nick "joe", "bob", "jaybee" . +``` + +This describes the use of this [array](https://infra.spec.whatwg.org/#list) as being unordered, and order may change when processing a document. By default, arrays of values are unordered, but this may be made explicit by setting `@container` to `@set` in the [context](#dfn-context): + +[Example 86](#example-86-specifying-that-a-collection-is-unordered-in-the-context): Specifying that a collection is unordered in the context + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%0A%20%20%20%20%22nick%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fnick%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40set%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fpeople%23joebob%22%2C%0A%20%20%22nick%22%3A%20%5B%20%22joe%22%2C%20%22bob%22%2C%20%22jaybee%22%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + ... + "nick": { + "@id": "http://xmlns.com/foaf/0.1/nick", + "@container": "@set" + } + }, + ... + "@id": "http://example.org/people#joebob", + "nick": [ "joe", "bob", "jaybee" ], + ... +} +``` + +``` {.expanded .result .nohighlight result-for="Specifying that a collection is unordered in the context-compacted"} +[{ + "@id": "http://example.org/people#joebob", + "http://xmlns.com/foaf/0.1/nick": [ + {"@value": "joe"}, + {"@value": "bob"}, + {"@value": "jaybee"} + ] +}] +``` + + Subject Property Value + ---------------------------------- ----------- -------- + http://example.org/people#joebob foaf:nick joe + http://example.org/people#joebob foaf:nick bob + http://example.org/people#joebob foaf:nick jaybee + +``` {.turtle content-type="text/turtle" result-for="Specifying that a collection is unordered in the context-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . + + foaf:nick "joe", "bob", "jaybee" . +``` + +Since JSON-LD 1.1, the `@set` keyword may be combined with other container specifications within an expanded term definition to similarly cause compacted values of indexes to be consistently represented using arrays. See [§ 4.6 Indexed Values](#indexed-values) for a further discussion. + +#### 4.3.3 Using `@set` with `@type`[](#using-set-with-type) + +*This section is non-normative.* + +Unless the [processing mode](#dfn-processing-mode) is set to `json-ld-1.0`, `@type` may be used with an [expanded term definition](#dfn-expanded-term-definition) with `@container` set to `@set`; no other [entries](https://infra.spec.whatwg.org/#map-entry) may be set within such an [expanded term definition](#dfn-expanded-term-definition). This is used by the [Compaction algorithm](https://www.w3.org/TR/json-ld11-api/#compaction-algorithm) to ensure that the values of `@type` (or an alias) are always represented in an [array](https://infra.spec.whatwg.org/#list). + +[Example 87](#example-87-setting-container-set-on-type): Setting \@container: \@set on \@type + +``` {aria-busy="false"} +{ + "@context": { + "@version": 1.1, + "@type": {"@container": "@set"} + }, + "@type": ["http:/example.org/type"] +} +``` + +### 4.4 Nested Properties[](#nested-properties) + +*This section is non-normative.* + +Many JSON APIs separate properties from their entities using an intermediate object; in JSON-LD these are called [nested properties](#dfn-nested-property). For example, a set of possible labels may be grouped under a common property: + +[Example 88](#example-88-nested-properties): Nested properties + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22skos%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23%22%2C%0A%20%20%20%20%22labels%22%3A%20%22%40nest%22%2C%0A%20%20%20%20%22main_label%22%3A%20%7B%22%40id%22%3A%20%22skos%3AprefLabel%22%7D%2C%0A%20%20%20%20%22other_label%22%3A%20%7B%22%40id%22%3A%20%22skos%3AaltLabel%22%7D%2C%0A%20%20%20%20%22homepage%22%3A%20%7B%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fhomepage%22%2C%20%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fmyresource%22%2C%0A%20%20%22homepage%22%3A%20%22http%3A%2F%2Fexample.org%22%2C%0A%20%20%22labels%22%3A%20%7B%0A%20%20%20%20%20%22main_label%22%3A%20%22This%20is%20the%20main%20label%20for%20my%20resource%22%2C%0A%20%20%20%20%20%22other_label%22%3A%20%22This%20is%20the%20other%20label%22%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "skos": "http://www.w3.org/2004/02/skos/core#", + "labels": "@nest", + "main_label": {"@id": "skos:prefLabel"}, + "other_label": {"@id": "skos:altLabel"}, + "homepage": {"@id": "http://xmlns.com/foaf/0.1/homepage", "@type": "@id"} + }, + "@id": "http://example.org/myresource", + "homepage": "http://example.org", + "labels": { + "main_label": "This is the main label for my resource", + "other_label": "This is the other label" + } +} +``` + +``` {.expanded .result .nohighlight result-for="Nested properties-compacted"} +[{ + "@id": "http://example.org/myresource", + "http://xmlns.com/foaf/0.1/homepage": [ + {"@id": "http://example.org"} + ], + "http://www.w3.org/2004/02/skos/core#prefLabel": [ + {"@value": "This is the main label for my resource"} + ], + "http://www.w3.org/2004/02/skos/core#altLabel": [ + {"@value": "This is the other label"} + ] +}] +``` + + Subject Property Value + ------------------------------- ---------------- ---------------------------------------- + http://example.org/myresource foaf:homepage http://example.org + http://example.org/myresource skos:prefLabel This is the main label for my resource + http://example.org/myresource skos:altLabel This is the other label + +``` {.turtle content-type="text/turtle" result-for="Nested properties-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . +@prefix skos: . + + + skos:prefLabel "This is the main label for my resource"; + skos:altLabel "This is the other label"; + foaf:homepage . +``` + +By defining *labels* using the [keyword](#dfn-keyword) `@nest`, a [JSON-LD processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor) will ignore the nesting created by using the *labels* property and process the contents as if it were declared directly within containing object. In this case, the *labels* property is semantically meaningless. Defining it as equivalent to `@nest` causes it to be ignored when expanding, making it equivalent to the following: + +[Example 89](#example-89-nested-properties-folded-into-containing-object): Nested properties folded into containing object + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22skos%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23%22%2C%0A%20%20%20%20%22main_label%22%3A%20%7B%22%40id%22%3A%20%22skos%3AprefLabel%22%7D%2C%0A%20%20%20%20%22other_label%22%3A%20%7B%22%40id%22%3A%20%22skos%3AaltLabel%22%7D%2C%0A%20%20%20%20%22homepage%22%3A%20%7B%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fhomepage%22%2C%20%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fmyresource%22%2C%0A%20%20%22homepage%22%3A%20%22http%3A%2F%2Fexample.org%22%2C%0A%20%20%22main_label%22%3A%20%22This%20is%20the%20main%20label%20for%20my%20resource%22%2C%0A%20%20%22other_label%22%3A%20%22This%20is%20the%20other%20label%22%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "skos": "http://www.w3.org/2004/02/skos/core#", + "main_label": {"@id": "skos:prefLabel"}, + "other_label": {"@id": "skos:altLabel"}, + "homepage": {"@id": "http://xmlns.com/foaf/0.1/homepage", "@type": "@id"} + }, + "@id": "http://example.org/myresource", + "homepage": "http://example.org", + "main_label": "This is the main label for my resource", + "other_label": "This is the other label" +} +``` + +``` {.expanded .result .nohighlight result-for="Nested properties folded into containing object-compacted"} +[{ + "@id": "http://example.org/myresource", + "http://xmlns.com/foaf/0.1/homepage": [ + {"@id": "http://example.org"} + ], + "http://www.w3.org/2004/02/skos/core#prefLabel": [ + {"@value": "This is the main label for my resource"} + ], + "http://www.w3.org/2004/02/skos/core#altLabel": [ + {"@value": "This is the other label"} + ] +}] +``` + + Subject Property Value + ------------------------------- ---------------- ---------------------------------------- + http://example.org/myresource foaf:homepage http://example.org + http://example.org/myresource skos:prefLabel This is the main label for my resource + http://example.org/myresource skos:altLabel This is the other label + +``` {.turtle content-type="text/turtle" result-for="Nested properties folded into containing object-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . +@prefix skos: . + + + skos:prefLabel "This is the main label for my resource"; + skos:altLabel "This is the other label"; + foaf:homepage . +``` + +Similarly, [term definitions](#dfn-term-definition) may contain a `@nest` property referencing a term aliased to `@nest` which will cause such properties to be nested under that aliased term when compacting. In the example below, both `main_label` and `other_label` are defined with `"@nest": "labels"`, which will cause them to be serialized under `labels` when compacting. + +[Example 90](#defining-property-nesting-expanded): Defining property nesting - Expanded Input + +``` {.expanded .input .preserve .nohighlight result-for="Defining property nesting-compacted"} +[{ + "@id": "http://example.org/myresource", + "http://xmlns.com/foaf/0.1/homepage": [ + {"@id": "http://example.org"} + ], + "http://www.w3.org/2004/02/skos/core#prefLabel": [ + {"@value": "This is the main label for my resource"} + ], + "http://www.w3.org/2004/02/skos/core#altLabel": [ + {"@value": "This is the other label"} + ] +}] +``` + +[Example 91](#defining-property-nesting-context): Defining property nesting - Context + +``` {.context .preserve .nohighlight} +{ + "@context": { + "@version": 1.1, + "skos": "http://www.w3.org/2004/02/skos/core#", + "labels": "@nest", + "main_label": {"@id": "skos:prefLabel", "@nest": "labels"}, + "other_label": {"@id": "skos:altLabel", "@nest": "labels"}, + "homepage": {"@id": "http://xmlns.com/foaf/0.1/homepage", "@type": "@id"} + } +} +``` + +[Example 92](#example-92-defining-property-nesting): Defining property nesting + +Compacted (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-compacted&json-ld=%5B%7B%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fmyresource%22%2C%0A%20%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fhomepage%22%3A%20%5B%0A%20%20%20%20%7B%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%22%7D%0A%20%20%5D%2C%0A%20%20%22http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23prefLabel%22%3A%20%5B%0A%20%20%20%20%7B%22%40value%22%3A%20%22This%20is%20the%20main%20label%20for%20my%20resource%22%7D%0A%20%20%5D%2C%0A%20%20%22http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23altLabel%22%3A%20%5B%0A%20%20%20%20%7B%22%40value%22%3A%20%22This%20is%20the%20other%20label%22%7D%0A%20%20%5D%0A%7D%5D&context=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22skos%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23%22%2C%0A%20%20%20%20%22labels%22%3A%20%22%40nest%22%2C%0A%20%20%20%20%22main_label%22%3A%20%7B%22%40id%22%3A%20%22skos%3AprefLabel%22%2C%20%22%40nest%22%3A%20%22labels%22%7D%2C%0A%20%20%20%20%22other_label%22%3A%20%7B%22%40id%22%3A%20%22skos%3AaltLabel%22%2C%20%22%40nest%22%3A%20%22labels%22%7D%2C%0A%20%20%20%20%22homepage%22%3A%20%7B%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fhomepage%22%2C%20%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .result .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "skos": "http://www.w3.org/2004/02/skos/core#", + "labels": "@nest", + "main_label": {"@id": "skos:prefLabel", "@nest": "labels"}, + "other_label": {"@id": "skos:altLabel", "@nest": "labels"}, + "homepage": {"@id": "http://xmlns.com/foaf/0.1/homepage", "@type": "@id"} + }, + "@id": "http://example.org/myresource", + "homepage": "http://example.org", + "labels": { + "main_label": "This is the main label for my resource", + "other_label": "This is the other label" + } +} +``` + + Subject Property Value + ------------------------------- ---------------- ---------------------------------------- + http://example.org/myresource foaf:homepage http://example.org + http://example.org/myresource skos:prefLabel This is the main label for my resource + http://example.org/myresource skos:altLabel This is the other label + +``` {.turtle content-type="text/turtle" result-for="Defining property nesting - Expanded Input" to-rdf="" aria-busy="false"} +@prefix foaf: . +@prefix skos: . + + + skos:prefLabel "This is the main label for my resource"; + skos:altLabel "This is the other label"; + foaf:homepage . +``` + +Note + +[Nested properties](#dfn-nested-property) are a new feature in JSON-LD 1.1. + +### 4.5 Embedding[](#embedding) + +*This section is non-normative.* + +Embedding is a JSON-LD feature that allows an author to use [node objects](#dfn-node-object) as [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) values. This is a commonly used mechanism for creating a parent-child relationship between two [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node). + +Without embedding, [node objects](#dfn-node-object) can be linked by referencing the identifier of another [node object](#dfn-node-object). For example: + +[Example 93](#example-93-referencing-node-objects): Referencing node objects + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%2C%0A%20%20%20%20%22knows%22%3A%20%7B%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%7D%2C%0A%20%20%22%40graph%22%3A%20%5B%7B%0A%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22knows%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%0A%20%20%7D%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@vocab": "http://xmlns.com/foaf/0.1/", + "knows": {"@type": "@id"} + }, + "@graph": [{ + "name": "Manu Sporny", + "@type": "Person", + "knows": "https://greggkellogg.net/foaf#me" + }, { + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg" + }] +} +``` + +``` {.expanded .result .nohighlight result-for="Referencing node objects-compacted"} +[{ + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "https://greggkellogg.net/foaf#me"} + ], + "http://xmlns.com/foaf/0.1/name": [ + {"@value": "Manu Sporny"} + ] +}, { + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [ + {"@value": "Gregg Kellogg"} + ] +}] +``` + + Subject Property Value + ---------------------------------- ------------ ---------------------------------- + \_:b0 rdf:type foaf:Person + \_:b0 foaf:name Manu Sporny + \_:b0 foaf:knows https://greggkellogg.net/foaf#me + https://greggkellogg.net/foaf#me rdf:type foaf:Person + https://greggkellogg.net/foaf#me foaf:name Gregg Kellogg + +``` {.turtle content-type="text/turtle" result-for="Referencing node objects-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . + +[ + a foaf:Person; + foaf:name "Manu Sporny"; + foaf:knows +] . + + a foaf:Person; + foaf:name "Gregg Kellogg" . +``` + +The previous example describes two [node objects](#dfn-node-object), for Manu and Gregg, with the `knows` property defined to treat string values as identifiers. [Embedding](#dfn-embedding) allows the [node object](#dfn-node-object) for Gregg to be *embedded* as a value of the `knows` property: + +[Example 94](#example-94-embedding-a-node-object-as-property-value-of-another-node-object): Embedding a node object as property value of another node object + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%0A%20%20%7D%2C%0A%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22knows%22%3A%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@vocab": "http://xmlns.com/foaf/0.1/" + }, + "@type": "Person", + "name": "Manu Sporny", + "knows": { + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg" + } +} +``` + +``` {.expanded .result .nohighlight result-for="Embedding a node object as property value of another node object-compacted"} +[{ + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/knows": [{ + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [ + {"@value": "Gregg Kellogg"} + ] + }], + "http://xmlns.com/foaf/0.1/name": [ + {"@value": "Manu Sporny"} + ] +}] +``` + + Subject Property Value + ---------------------------------- ------------ ---------------------------------- + \_:b0 rdf:type foaf:Person + \_:b0 foaf:name Manu Sporny + \_:b0 foaf:knows https://greggkellogg.net/foaf#me + https://greggkellogg.net/foaf#me rdf:type foaf:Person + https://greggkellogg.net/foaf#me foaf:name Gregg Kellogg + +``` {.turtle content-type="text/turtle" result-for="Embedding a node object as property value of another node object-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . + +[ + a foaf:Person; + foaf:name "Manu Sporny"; + foaf:knows +] . + + a foaf:Person; + foaf:name "Gregg Kellogg" . +``` + +A [node object](#dfn-node-object), like the one used above, may be used in any value position in the body of a JSON-LD document. + +While it is considered a best practice to identify nodes in a graph, at times this is impractical. In the data model, nodes without an explicit identifier are called [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), which can be represented in a serialization such as JSON-LD using a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier). In the previous example, the top-level node for Manu does not have an identifier, and does not need one to describe it within the data model. However, if we were to want to describe a *knows* relationship from Gregg to Manu, we would need to introduce a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) (here `_:b0`). + +[Example 95](#example-95-referencing-an-unidentified-node): Referencing an unidentified node + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22_%3Ab0%22%2C%0A%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22knows%22%3A%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%2C%0A%20%20%20%20%22knows%22%3A%20%7B%22%40id%22%3A%20%22_%3Ab0%22%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@vocab": "http://xmlns.com/foaf/0.1/" + }, + "@id": "_:b0", + "@type": "Person", + "name": "Manu Sporny", + "knows": { + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg", + "knows": {"@id": "_:b0"} + } +} +``` + +``` {.expanded .result .nohighlight result-for="Referencing an unidentified node-compacted"} +[{ + "@id": "_:b0", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/knows": [{ + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [ + {"@value": "Gregg Kellogg"} + ], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "_:b0"} + ] + }], + "http://xmlns.com/foaf/0.1/name": [ + {"@value": "Manu Sporny"} + ] +}] +``` + + Subject Property Value + ---------------------------------- ------------ ---------------------------------- + \_:b0 rdf:type foaf:Person + \_:b0 foaf:name Manu Sporny + \_:b0 foaf:knows https://greggkellogg.net/foaf#me + https://greggkellogg.net/foaf#me rdf:type foaf:Person + https://greggkellogg.net/foaf#me foaf:name Gregg Kellogg + https://greggkellogg.net/foaf#me foaf:knows \_:b0 + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Referencing an unidentified node-expanded" to-rdf=""} +@prefix foaf: . + +_:b0 a foaf:Person; + foaf:name "Manu Sporny"; + foaf:knows . + + a foaf:Person; + foaf:name "Gregg Kellogg"; + foaf:knows _:b0 . +``` + +[Blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) may be automatically introduced by algorithms such as [flattening](https://www.w3.org/TR/json-ld11-api/#dfn-flattened), but they are also useful for authors to describe such relationships directly. + +#### 4.5.1 Identifying Blank Nodes[](#identifying-blank-nodes) + +*This section is non-normative.* + +At times, it becomes necessary to be able to express information without being able to uniquely identify the [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) with an [IRI](https://tools.ietf.org/html/rfc3987#section-2). This type of node is called a [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). JSON-LD does not require all nodes to be identified using `@id`. However, some graph topologies may require identifiers to be serializable. Graphs containing loops, e.g., cannot be serialized using [embedding](#dfn-embedding) alone, `@id` must be used to connect the nodes. In these situations, one can use [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier), which look like [IRIs](https://tools.ietf.org/html/rfc3987#section-2) using an underscore (`_`) as scheme. This allows one to reference the node locally within the document, but makes it impossible to reference the node from an external document. The [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) is scoped to the document in which it is used. + +[Example 96](#example-96-specifying-a-local-blank-node-identifier): Specifying a local blank node identifier + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%0A%20%20%20%22%40id%22%3A%20%22_%3An1%22%2C%0A%20%20%20%22name%22%3A%20%22Secret%20Agent%201%22%2C%0A%20%20%20%22knows%22%3A%20%7B%0A%20%20%20%20%20%22name%22%3A%20%22Secret%20Agent%202%22%2C%0A%20%20%20%20%20%22knows%22%3A%20%7B%20%22%40id%22%3A%20%22_%3An1%22%20%7D%0A%20%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": "http://schema.org/", + ... + "@id": "_:n1", + "name": "Secret Agent 1", + "knows": { + "name": "Secret Agent 2", + "knows": { "@id": "_:n1" } + } +} +``` + +``` {.expanded .result .nohighlight result-for="Specifying a local blank node identifier-compacted"} +[{ + "@id": "_:n1", + "http://schema.org/name": [{"@value": "Secret Agent 1"}], + "http://schema.org/knows": [{ + "http://schema.org/name": [{"@value": "Secret Agent 2"}], + "http://schema.org/knows": [{"@id": "_:n1"}] + }] +}] +``` + + Subject Property Value + --------- -------------- ---------------- + \_:b0 schema:name Secret Agent 1 + \_:b0 schema:knows \_:b1 + \_:b1 schema:name Secret Agent 2 + \_:b1 schema:knows \_:b0 + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Specifying a local blank node identifier-expanded" to-rdf=""} +@prefix schema: . + +_:b0 schema:name "Secret Agent 1"; + schema:knows _:b1 . + +_:b1 schema:name "Secret Agent 2"; + schema:knows _:b0 . +``` + +The example above contains information about two secret agents that cannot be identified with an [IRI](https://tools.ietf.org/html/rfc3987#section-2). While expressing that *agent 1* knows *agent 2* is possible without using [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier), it is necessary to assign *agent 1* an identifier so that it can be referenced from *agent 2*. + +It is worth noting that blank node identifiers may be relabeled during processing. If a developer finds that they refer to the [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) more than once, they should consider naming the node using a dereferenceable [IRI](https://tools.ietf.org/html/rfc3987#section-2) so that it can also be referenced from other documents. + +### 4.6 Indexed Values[](#indexed-values) + +*This section is non-normative.* + +Sometimes multiple property values need to be accessed in a more direct fashion than iterating though multiple array values. JSON-LD provides an indexing mechanism to allow the use of an intermediate [map](https://infra.spec.whatwg.org/#ordered-map) to associate specific indexes with associated values. + +Data Indexing +: As described in [§ 4.6.1 Data Indexing](#data-indexing), data indexing allows an arbitrary key to reference a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) or value. + +Language Indexing +: As described in [§ 4.6.2 Language Indexing](#language-indexing), language indexing allows a language to reference a [string](https://infra.spec.whatwg.org/#javascript-string) and be interpreted as the language associated with that string. + +Node Identifier Indexing +: As described in [§ 4.6.3 Node Identifier Indexing](#node-identifier-indexing), node identifier indexing allows an [IRI](https://tools.ietf.org/html/rfc3987#section-2) to reference a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) and be interpreted as the identifier of that [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node). + +Node Type Indexing +: As described in [§ 4.6.4 Node Type Indexing](#node-type-indexing), node type indexing allows an [IRI](https://tools.ietf.org/html/rfc3987#section-2) to reference a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) and be interpreted as a type of that [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node). + +See [§ 4.9 Named Graphs](#named-graphs) for other uses of indexing in JSON-LD. + +#### 4.6.1 Data Indexing[](#data-indexing) + +*This section is non-normative.* + +Databases are typically used to make access to data more efficient. Developers often extend this sort of functionality into their application data to deliver similar performance gains. This data may have no meaning from a Linked Data standpoint, but is still useful for an application. + +JSON-LD introduces the notion of [index maps](#dfn-index-map) that can be used to structure data into a form that is more efficient to access. The data indexing feature allows an author to structure data using a simple key-value map where the keys do not map to [IRIs](https://tools.ietf.org/html/rfc3987#section-2). This enables direct access to data instead of having to scan an array in search of a specific item. In JSON-LD such data can be specified by associating the `@index` [keyword](#dfn-keyword) with a `@container` declaration in the context: + +[Example 97](#example-97-indexing-data-in-json-ld): Indexing data in JSON-LD + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%22body%22%3A%20%22schema%3AarticleBody%22%2C%0A%20%20%20%20%22athletes%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3Aathlete%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40index%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22position%22%3A%20%22schema%3AjobTitle%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%22schema%3ASportsTeam%22%2C%0A%20%20%22name%22%3A%20%22San%20Francisco%20Giants%22%2C%0A%20%20%22athletes%22%3A%20%7B%0A%20%20%20%20%22catcher%22%3A%20%7B%0A%20%20%20%20%20%20%22%40type%22%3A%20%22schema%3APerson%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Buster%20Posey%22%2C%0A%20%20%20%20%20%20%22position%22%3A%20%22Catcher%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22pitcher%22%3A%20%7B%0A%20%20%20%20%20%20%22%40type%22%3A%20%22schema%3APerson%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Madison%20Bumgarner%22%2C%0A%20%20%20%20%20%20%22position%22%3A%20%22Starting%20Pitcher%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "schema": "http://schema.org/", + "name": "schema:name", + "body": "schema:articleBody", + "athletes": { + "@id": "schema:athlete", + "@container": "@index" + }, + "position": "schema:jobTitle" + }, + "@id": "http://example.com/", + "@type": "schema:SportsTeam", + "name": "San Francisco Giants", + "athletes": { + "catcher": { + "@type": "schema:Person", + "name": "Buster Posey", + "position": "Catcher" + }, + "pitcher": { + "@type": "schema:Person", + "name": "Madison Bumgarner", + "position": "Starting Pitcher" + }, + .... + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing data in JSON-LD-compacted"} +[{ + "@id": "http://example.com/", + "@type": ["http://schema.org/SportsTeam"], + "http://schema.org/name": [{"@value": "San Francisco Giants"}], + "http://schema.org/athlete": [{ + "@type": ["http://schema.org/Person"], + "http://schema.org/name": [{"@value": "Buster Posey"}], + "http://schema.org/jobTitle": [{"@value": "Catcher"}], + "@index": "catcher" + }, { + "@type": ["http://schema.org/Person"], + "http://schema.org/name": [{"@value": "Madison Bumgarner"}], + "http://schema.org/jobTitle": [{"@value": "Starting Pitcher"}], + "@index": "pitcher" + }, + .... + ] +}] +``` + + Subject Property Value + --------------------- ----------------- ---------------------- + http://example.com/ rdf:type schema:SportsTeam + http://example.com/ schema:name San Francisco Giants + \_:b0 rdf:type schema:Person + \_:b0 schema:name Buster Posey + \_:b0 schema:jobTitle Catcher + http://example.com/ schema:athlete \_:b0 + \_:b1 rdf:type schema:Person + \_:b1 schema:name Madison Bumgarner + \_:b1 schema:jobTitle Starting Pitcher + http://example.com/ schema:athlete \_:b1 + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Indexing data in JSON-LD-expanded" to-rdf=""} +@prefix schema: . + + a schema:SportsTeam; + schema:name "San Francisco Giants"; + schema:athlete [ + a schema:Person; + schema:jobTitle "Catcher"; + schema:name "Buster Posey" + ], [ + a schema:Person; + schema:jobTitle "Starting Pitcher"; + schema:name "Madison Bumgarner" + ], + .... + . +``` + +In the example above, the **athletes** [term](#dfn-term) has been marked as an [index map](#dfn-index-map). The **catcher** and **pitcher** keys will be ignored semantically, but preserved syntactically, by the [JSON-LD Processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor). If used in JavaScript, this can allow a developer to access a particular athlete using the following code snippet: `obj.athletes.pitcher`. + +The interpretation of the data is expressed in the statements table. **Note how the index keys do not appear in the statements**, but would continue to exist if the document were compacted or expanded (see [§ 5.2 Compacted Document Form](#compacted-document-form) and [§ 5.1 Expanded Document Form](#expanded-document-form)) using a [JSON-LD processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor). + +Warning + +As data indexes are not preserved when round-tripping to RDF; this feature should be used judiciously. Often, other indexing mechanisms, which are preserved, are more appropriate. + +The value of `@container` can also be an array containing both `@index` and `@set`. When *compacting*, this ensures that a [JSON-LD Processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor) will use the [array](https://infra.spec.whatwg.org/#list) form for all values of indexes. + +Unless the [processing mode](#dfn-processing-mode) is set to `json-ld-1.0`, the special index `@none` is used for indexing data which does not have an associated index, which is useful to maintain a normalized representation. + +[Example 98](#example-98-indexing-data-using-none): Indexing data using \@none + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%22body%22%3A%20%22schema%3AarticleBody%22%2C%0A%20%20%20%20%22athletes%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3Aathlete%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40index%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22position%22%3A%20%22schema%3AjobTitle%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%22schema%3ASportsTeam%22%2C%0A%20%20%22name%22%3A%20%22San%20Francisco%20Giants%22%2C%0A%20%20%22athletes%22%3A%20%7B%0A%20%20%20%20%22catcher%22%3A%20%7B%0A%20%20%20%20%20%20%22%40type%22%3A%20%22schema%3APerson%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Buster%20Posey%22%2C%0A%20%20%20%20%20%20%22position%22%3A%20%22Catcher%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22pitcher%22%3A%20%7B%0A%20%20%20%20%20%20%22%40type%22%3A%20%22schema%3APerson%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Madison%20Bumgarner%22%2C%0A%20%20%20%20%20%20%22position%22%3A%20%22Starting%20Pitcher%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22%40none%22%3A%20%7B%0A%20%20%20%20%20%20%22name%22%3A%20%22Lou%20Seal%22%2C%0A%20%20%20%20%20%20%22position%22%3A%20%22Mascot%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "schema": "http://schema.org/", + "name": "schema:name", + "body": "schema:articleBody", + "athletes": { + "@id": "schema:athlete", + "@container": "@index" + }, + "position": "schema:jobTitle" + }, + "@id": "http://example.com/", + "@type": "schema:SportsTeam", + "name": "San Francisco Giants", + "athletes": { + "catcher": { + "@type": "schema:Person", + "name": "Buster Posey", + "position": "Catcher" + }, + "pitcher": { + "@type": "schema:Person", + "name": "Madison Bumgarner", + "position": "Starting Pitcher" + }, + "@none": { + "name": "Lou Seal", + "position": "Mascot" + }, + .... + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing data using @none-compacted"} +[{ + "@id": "http://example.com/", + "@type": ["http://schema.org/SportsTeam"], + "http://schema.org/name": [{"@value": "San Francisco Giants"}], + "http://schema.org/athlete": [{ + "@type": ["http://schema.org/Person"], + "http://schema.org/name": [{"@value": "Buster Posey"}], + "http://schema.org/jobTitle": [{"@value": "Catcher"}], + "@index": "catcher" + }, { + "@type": ["http://schema.org/Person"], + "http://schema.org/name": [{"@value": "Madison Bumgarner"}], + "http://schema.org/jobTitle": [{"@value": "Starting Pitcher"}], + "@index": "pitcher" + }, { + "http://schema.org/name": [{"@value": "Lou Seal"}], + "http://schema.org/jobTitle": [{"@value": "Mascot"}] + }, + .... + ] +}] +``` + + Subject Property Value + --------------------- ----------------- ---------------------- + http://example.com/ rdf:type schema:SportsTeam + http://example.com/ schema:name San Francisco Giants + \_:b0 rdf:type schema:Person + \_:b0 schema:name Buster Posey + \_:b0 schema:jobTitle Catcher + http://example.com/ schema:athlete \_:b0 + \_:b1 rdf:type schema:Person + \_:b1 schema:name Madison Bumgarner + \_:b1 schema:jobTitle Starting Pitcher + http://example.com/ schema:athlete \_:b1 + \_:b2 schema:name Lou Seal + \_:b2 schema:jobTitle Mascot + http://example.com/ schema:athlete \_:b2 + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Indexing data using @none-expanded" to-rdf=""} +@prefix schema: . + + a schema:SportsTeam; + schema:name "San Francisco Giants"; + schema:athlete [ + a schema:Person; + schema:jobTitle "Catcher"; + schema:name "Buster Posey" + ], [ + a schema:Person; + schema:jobTitle "Starting Pitcher"; + schema:name "Madison Bumgarner" + ], [ + schema:jobTitle "Mascot"; + schema:name "Lou Seal" + ], + .... + . +``` + +##### 4.6.1.1 Property-based data indexing[](#property-based-data-indexing) + +*This section is non-normative.* + +In its simplest form (as in the examples above), data indexing assigns no semantics to the keys of an [index map](#dfn-index-map). However, in some situations, the keys used to index objects are semantically linked to these objects, and should be preserved not only syntactically, but also semantically. + +Unless the [processing mode](#dfn-processing-mode) is set to `json-ld-1.0`, `"@container": "@index"` in a term description can be accompanied with an `"@index"` key. The value of that key must map to an [IRI](https://tools.ietf.org/html/rfc3987#section-2), which identifies the semantic property linking each object to its key. + +[Example 99](#example-99-property-based-data-indexing): Property-based data indexing + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%22body%22%3A%20%22schema%3AarticleBody%22%2C%0A%20%20%20%20%22athletes%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3Aathlete%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40index%22%2C%0A%20%20%20%20%20%20%22%40index%22%3A%20%22schema%3AjobTitle%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%22schema%3ASportsTeam%22%2C%0A%20%20%22name%22%3A%20%22San%20Francisco%20Giants%22%2C%0A%20%20%22athletes%22%3A%20%7B%0A%20%20%20%20%22Catcher%22%3A%20%7B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%22%40type%22%3A%20%22schema%3APerson%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Buster%20Posey%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22Starting%20Pitcher%22%3A%20%7B%0A%20%20%20%20%20%20%22%40type%22%3A%20%22schema%3APerson%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Madison%20Bumgarner%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "schema": "http://schema.org/", + "name": "schema:name", + "body": "schema:articleBody", + "athletes": { + "@id": "schema:athlete", + "@container": "@index", + "@index": "schema:jobTitle" + } + }, + "@id": "http://example.com/", + "@type": "schema:SportsTeam", + "name": "San Francisco Giants", + "athletes": { + "Catcher": { + ↑ "Catcher" will add `"schema:jobTitle": "Catcher"` when expanded + "@type": "schema:Person", + "name": "Buster Posey" + }, + "Starting Pitcher": { + "@type": "schema:Person", + "name": "Madison Bumgarner" + }, + .... + } +} +``` + +``` {.expanded .result .nohighlight ignore="" result-for="Property-based data indexing-compacted"} +[{ + "@id": "http://example.com/", + "@type": ["http://schema.org/SportsTeam"], + "http://schema.org/name": [{"@value": "San Francisco Giants"}], + "http://schema.org/athlete": [{ + "@type": ["http://schema.org/Person"], + "http://schema.org/name": [{"@value": "Buster Posey"}], + "http://schema.org/jobTitle": [{"@value": "Catcher"}] + }, { + "@type": ["http://schema.org/Person"], + "http://schema.org/name": [{"@value": "Madison Bumgarner"}], + "http://schema.org/jobTitle": [{"@value": "Starting Pitcher"}] + }, + .... + ] +}] +``` + + Subject Property Value + --------------------- ----------------- ---------------------- + http://example.com/ rdf:type schema:SportsTeam + http://example.com/ schema:name San Francisco Giants + \_:b0 rdf:type schema:Person + \_:b0 schema:name Buster Posey + \_:b0 schema:jobTitle Catcher + http://example.com/ schema:athlete \_:b0 + \_:b1 rdf:type schema:Person + \_:b1 schema:name Madison Bumgarner + \_:b1 schema:jobTitle Starting Pitcher + http://example.com/ schema:athlete \_:b1 + +``` {.turtle .nohighlight content-type="text/turtle" ignore="" result-for="Property-based data indexing-expanded" to-rdf=""} +@prefix schema: . + + a schema:SportsTeam; + schema:name "San Francisco Giants"; + schema:athlete [ + a schema:Person; + schema:jobTitle "Catcher"; + schema:name "Buster Posey" + ], [ + a schema:Person; + schema:jobTitle "Starting Pitcher"; + schema:name "Madison Bumgarner" + ], + .... + . +``` + +Note + +When using property-based data indexing, [index maps](#dfn-index-map) can only be used on [node objects](#dfn-node-object), not [value objects](#dfn-value-object) or [graph objects](#dfn-graph-object). [Value objects](#dfn-value-object) are restricted to have only certain keys and do not support arbitrary properties. + +#### 4.6.2 Language Indexing[](#language-indexing) + +*This section is non-normative.* + +JSON which includes string values in multiple languages may be represented using a [language map](#dfn-language-map) to allow for easily indexing property values by [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag). This enables direct access to language values instead of having to scan an array in search of a specific item. In JSON-LD such data can be specified by associating the `@language` [keyword](#dfn-keyword) with a `@container` declaration in the context: + +[Example 100](#example-100-indexing-languaged-tagged-strings-in-json-ld): Indexing languaged-tagged strings in JSON-LD + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22vocab%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%2F%22%2C%0A%20%20%20%20%22label%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22vocab%3Alabel%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40language%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fqueen%22%2C%0A%20%20%22label%22%3A%20%7B%0A%20%20%20%20%22en%22%3A%20%22The%20Queen%22%2C%0A%20%20%20%20%22de%22%3A%20%5B%20%22Die%20K%C3%B6nigin%22%2C%20%22Ihre%20Majest%C3%A4t%22%20%5D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected aria-busy="false"} +{ + "@context": { + "vocab": "http://example.com/vocab/", + "label": { + "@id": "vocab:label", + "@container": "@language" + } + }, + "@id": "http://example.com/queen", + "label": { + "en": "The Queen", + "de": [ "Die Königin", "Ihre Majestät" ] + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing languaged-tagged strings in JSON-LD-compacted"} +[{ + "@id": "http://example.com/queen", + "http://example.com/vocab/label": [ + {"@value": "The Queen", "@language": "en"}, + {"@value": "Die Königin", "@language": "de"}, + {"@value": "Ihre Majestät", "@language": "de"} + ] +}] +``` + + Subject Property Value Language + -------------------------- -------------------------------- --------------- ---------- + http://example.com/queen http://example.com/vocab/label The Queen en + http://example.com/queen http://example.com/vocab/label Die Königin de + http://example.com/queen http://example.com/vocab/label Ihre Majestät de + +``` {.turtle content-type="text/turtle" result-for="Indexing languaged-tagged strings in JSON-LD-expanded" to-rdf="" aria-busy="false"} +@prefix rdf: . + + + "Ihre Majestät"@de, + "Die Königin"@de, + "The Queen"@en . +``` + +In the example above, the **label** [term](#dfn-term) has been marked as a [language map](#dfn-language-map). The **en** and **de** keys are implicitly associated with their respective values by the [JSON-LD Processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor). This allows a developer to access the German version of the **label** using the following code snippet: `obj.label.de`, which, again, is only appropriate when languages are limited to the primary language sub-tag and do not depend on other sub-tags, such as `"de-at"`. + +The value of `@container` can also be an array containing both `@language` and `@set`. When *compacting*, this ensures that a [JSON-LD Processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor) will use the [array](https://infra.spec.whatwg.org/#list) form for all values of language tags. + +[Example 101](#example-101-indexing-languaged-tagged-strings-in-json-ld-with-set-representation): Indexing languaged-tagged strings in JSON-LD with \@set representation + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22vocab%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%2F%22%2C%0A%20%20%20%20%22label%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22vocab%3Alabel%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%5B%22%40language%22%2C%20%22%40set%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fqueen%22%2C%0A%20%20%22label%22%3A%20%7B%0A%20%20%20%20%22en%22%3A%20%5B%22The%20Queen%22%5D%2C%0A%20%20%20%20%22de%22%3A%20%5B%20%22Die%20K%C3%B6nigin%22%2C%20%22Ihre%20Majest%C3%A4t%22%20%5D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "vocab": "http://example.com/vocab/", + "label": { + "@id": "vocab:label", + "@container": ["@language", "@set"] + } + }, + "@id": "http://example.com/queen", + "label": { + "en": ["The Queen"], + "de": [ "Die Königin", "Ihre Majestät" ] + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing languaged-tagged strings in JSON-LD with @set representation-compacted"} +[{ + "@id": "http://example.com/queen", + "http://example.com/vocab/label": [ + {"@value": "The Queen", "@language": "en"}, + {"@value": "Die Königin", "@language": "de"}, + {"@value": "Ihre Majestät", "@language": "de"} + ] +}] +``` + + Subject Property Value Language + -------------------------- -------------------------------- --------------- ---------- + http://example.com/queen http://example.com/vocab/label The Queen en + http://example.com/queen http://example.com/vocab/label Die Königin de + http://example.com/queen http://example.com/vocab/label Ihre Majestät de + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Indexing languaged-tagged strings in JSON-LD with @set representation-expanded" to-rdf=""} +@prefix rdf: . + + + "Ihre Majestät"@de, + "Die Königin"@de, + "The Queen"@en . +``` + +Unless the [processing mode](#dfn-processing-mode) is set to `json-ld-1.0`, the special index `@none` is used for indexing strings which do not have a language; this is useful to maintain a normalized representation for string values not having a datatype. + +[Example 102](#example-102-indexing-languaged-tagged-strings-using-none-for-no-language): Indexing languaged-tagged strings using \@none for no language + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22vocab%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%2F%22%2C%0A%20%20%20%20%22label%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22vocab%3Alabel%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40language%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fqueen%22%2C%0A%20%20%22label%22%3A%20%7B%0A%20%20%20%20%22en%22%3A%20%22The%20Queen%22%2C%0A%20%20%20%20%22de%22%3A%20%5B%20%22Die%20K%C3%B6nigin%22%2C%20%22Ihre%20Majest%C3%A4t%22%20%5D%2C%0A%20%20%20%20%22%40none%22%3A%20%22The%20Queen%22%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "vocab": "http://example.com/vocab/", + "label": { + "@id": "vocab:label", + "@container": "@language" + } + }, + "@id": "http://example.com/queen", + "label": { + "en": "The Queen", + "de": [ "Die Königin", "Ihre Majestät" ], + "@none": "The Queen" + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing languaged-tagged strings using @none for no language-compacted"} +[{ + "@id": "http://example.com/queen", + "http://example.com/vocab/label": [ + {"@value": "The Queen", "@language": "en"}, + {"@value": "Die Königin", "@language": "de"}, + {"@value": "Ihre Majestät", "@language": "de"}, + {"@value": "The Queen"} + ] +}] +``` + + Subject Property Value Language + -------------------------- -------------------------------- --------------- ---------- + http://example.com/queen http://example.com/vocab/label The Queen en + http://example.com/queen http://example.com/vocab/label Die Königin de + http://example.com/queen http://example.com/vocab/label Ihre Majestät de + http://example.com/queen http://example.com/vocab/label The Queen + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Indexing languaged-tagged strings using @none for no language-expanded" to-rdf=""} +@prefix rdf: . + + + "Ihre Majestät"@de, + "Die Königin"@de, + "The Queen"@en, + "The Queen" . +``` + +#### 4.6.3 Node Identifier Indexing[](#node-identifier-indexing) + +*This section is non-normative.* + +In addition to [index maps](#dfn-index-map), JSON-LD introduces the notion of [id maps](#dfn-id-map) for structuring data. The id indexing feature allows an author to structure data using a simple key-value map where the keys map to [IRIs](https://tools.ietf.org/html/rfc3987#section-2). This enables direct access to associated [node objects](#dfn-node-object) instead of having to scan an array in search of a specific item. In JSON-LD such data can be specified by associating the `@id` [keyword](#dfn-keyword) with a `@container` declaration in the context: + +[Example 103](#example-103-indexing-data-in-json-ld-by-node-identifiers): Indexing data in JSON-LD by node identifiers + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%22body%22%3A%20%22schema%3AarticleBody%22%2C%0A%20%20%20%20%22words%22%3A%20%22schema%3AwordCount%22%2C%0A%20%20%20%20%22post%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3AblogPost%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40id%22%2C%0A%20%20%20%20%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22%40base%22%3A%20%22http%3A%2F%2Fexample.com%2Fposts%2F%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%22schema%3ABlog%22%2C%0A%20%20%22name%22%3A%20%22World%20Financial%20News%22%2C%0A%20%20%22post%22%3A%20%7B%0A%20%20%20%20%221%2Fen%22%3A%20%7B%0A%20%20%20%20%20%20%22body%22%3A%20%22World%20commodities%20were%20up%20today%20with%20heavy%20trading%20of%20crude%20oil...%22%2C%0A%20%20%20%20%20%20%22words%22%3A%201539%0A%20%20%20%20%7D%2C%0A%20%20%20%20%221%2Fde%22%3A%20%7B%0A%20%20%20%20%20%20%22body%22%3A%20%22Die%20Werte%20an%20Warenb%C3%B6rsen%20stiegen%20im%20Sog%20eines%20starken%20Handels%20von%20Roh%C3%B6l...%22%2C%0A%20%20%20%20%20%20%22words%22%3A%201204%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "schema": "http://schema.org/", + "name": "schema:name", + "body": "schema:articleBody", + "words": "schema:wordCount", + "post": { + "@id": "schema:blogPost", + "@container": "@id", + "@context": { + "@base": "http://example.com/posts/" + } + } + }, + "@id": "http://example.com/", + "@type": "schema:Blog", + "name": "World Financial News", + "post": { + "1/en": { + "body": "World commodities were up today with heavy trading of crude oil...", + "words": 1539 + }, + "1/de": { + "body": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl...", + "words": 1204 + } + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing data in JSON-LD by node identifiers-compacted"} +[{ + "@id": "http://example.com/", + "@type": ["http://schema.org/Blog"], + "http://schema.org/name": [{"@value": "World Financial News"}], + "http://schema.org/blogPost": [{ + "@id": "http://example.com/posts/1/en", + "http://schema.org/articleBody": [ + {"@value": "World commodities were up today with heavy trading of crude oil..."} + ], + "http://schema.org/wordCount": [{"@value": 1539}] + }, { + "@id": "http://example.com/posts/1/de", + "http://schema.org/articleBody": [ + {"@value": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."} + ], + "http://schema.org/wordCount": [{"@value": 1204}] + }] +}] +``` + + Subject Property Value Value Type + ------------------------------- -------------------- ----------------------------------------------------------------------------- ------------- + http://example.com/ rdf:type schema:Blog   + http://example.com/ schema:name World Financial News   + http://example.com/ schema:blogPost http://example.com/posts/1/de   + http://example.com/ schema:blogPost http://example.com/posts/1/en   + http://example.com/posts/1/de schema:articleBody Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl\...   + http://example.com/posts/1/de schema:wordCount 1204 xsd:integer + http://example.com/posts/1/en schema:articleBody World commodities were up today with heavy trading of crude oil\...   + http://example.com/posts/1/en schema:wordCount 1539 xsd:integer + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Indexing data in JSON-LD by node identifiers-expanded" to-rdf=""} +@prefix rdf: . +@prefix schema: . +@prefix xsd: . + + a schema:Blog; + schema:blogPost , + ; + schema:name "World Financial News" . + + schema:articleBody + "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."; + schema:wordCount 1204 . + + schema:articleBody + "World commodities were up today with heavy trading of crude oil..."; + schema:wordCount 1539 . +``` + +In the example above, the `post` [term](#dfn-term) has been marked as an [id map](#dfn-id-map). The `http://example.com/posts/1/en` and `http://example.com/posts/1/de` keys will be interpreted as the `@id` property of the [node object](#dfn-node-object) value. + +The interpretation of the data above is exactly the same as that in [§ 4.6.1 Data Indexing](#data-indexing) using a [JSON-LD processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor). + +The value of `@container` can also be an array containing both `@id` and `@set`. When *compacting*, this ensures that a [JSON-LD processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor) will use the [array](https://infra.spec.whatwg.org/#list) form for all values of node identifiers. + +[Example 104](#example-104-indexing-data-in-json-ld-by-node-identifiers-with-set-representation): Indexing data in JSON-LD by node identifiers with \@set representation + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%22body%22%3A%20%22schema%3AarticleBody%22%2C%0A%20%20%20%20%22words%22%3A%20%22schema%3AwordCount%22%2C%0A%20%20%20%20%22post%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3AblogPost%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%5B%22%40id%22%2C%20%22%40set%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%22schema%3ABlog%22%2C%0A%20%20%22name%22%3A%20%22World%20Financial%20News%22%2C%0A%20%20%22post%22%3A%20%7B%0A%20%20%20%20%22http%3A%2F%2Fexample.com%2Fposts%2F1%2Fen%22%3A%20%5B%7B%0A%20%20%20%20%20%20%22body%22%3A%20%22World%20commodities%20were%20up%20today%20with%20heavy%20trading%20of%20crude%20oil...%22%2C%0A%20%20%20%20%20%20%22words%22%3A%201539%0A%20%20%20%20%7D%5D%2C%0A%20%20%20%20%22http%3A%2F%2Fexample.com%2Fposts%2F1%2Fde%22%3A%20%5B%7B%0A%20%20%20%20%20%20%22body%22%3A%20%22Die%20Werte%20an%20Warenb%C3%B6rsen%20stiegen%20im%20Sog%20eines%20starken%20Handels%20von%20Roh%C3%B6l...%22%2C%0A%20%20%20%20%20%20%22words%22%3A%201204%0A%20%20%20%20%7D%5D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "schema": "http://schema.org/", + "name": "schema:name", + "body": "schema:articleBody", + "words": "schema:wordCount", + "post": { + "@id": "schema:blogPost", + "@container": ["@id", "@set"] + } + }, + "@id": "http://example.com/", + "@type": "schema:Blog", + "name": "World Financial News", + "post": { + "http://example.com/posts/1/en": [{ + "body": "World commodities were up today with heavy trading of crude oil...", + "words": 1539 + }], + "http://example.com/posts/1/de": [{ + "body": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl...", + "words": 1204 + }] + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing data in JSON-LD by node identifiers with @set representation-compacted"} +[{ + "@id": "http://example.com/", + "@type": ["http://schema.org/Blog"], + "http://schema.org/name": [{"@value": "World Financial News"}], + "http://schema.org/blogPost": [{ + "@id": "http://example.com/posts/1/en", + "http://schema.org/articleBody": [ + {"@value": "World commodities were up today with heavy trading of crude oil..."} + ], + "http://schema.org/wordCount": [{"@value": 1539}] + }, { + "@id": "http://example.com/posts/1/de", + "http://schema.org/articleBody": [ + {"@value": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."} + ], + "http://schema.org/wordCount": [{"@value": 1204}] + }] +}] +``` + + Subject Property Value Value Type + ------------------------------- -------------------- ----------------------------------------------------------------------------- ------------- + http://example.com/ rdf:type schema:Blog   + http://example.com/ schema:name World Financial News   + http://example.com/ schema:blogPost http://example.com/posts/1/de   + http://example.com/ schema:blogPost http://example.com/posts/1/en   + http://example.com/posts/1/de schema:articleBody Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl\...   + http://example.com/posts/1/de schema:wordCount 1204 xsd:integer + http://example.com/posts/1/en schema:articleBody World commodities were up today with heavy trading of crude oil\...   + http://example.com/posts/1/en schema:wordCount 1539 xsd:integer + +``` {.turtle content-type="text/turtle" result-for="Indexing data in JSON-LD by node identifiers with @set representation-expanded" to-rdf="" aria-busy="false"} +@prefix rdf: . +@prefix schema: . +@prefix xsd: . + + a schema:Blog; + schema:blogPost , + ; + schema:name "World Financial News" . + + schema:articleBody + "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."; + schema:wordCount 1204 . + + schema:articleBody + "World commodities were up today with heavy trading of crude oil..."; + schema:wordCount 1539 . +``` + +The special index `@none` is used for indexing [node objects](#dfn-node-object) which do not have an `@id`, which is useful to maintain a normalized representation. The `@none` index may also be a term which expands to `@none`, such as the term *none* used in the example below. + +[Example 105](#example-105-indexing-data-in-json-ld-by-node-identifiers-using-none): Indexing data in JSON-LD by node identifiers using \@none + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%22body%22%3A%20%22schema%3AarticleBody%22%2C%0A%20%20%20%20%22words%22%3A%20%22schema%3AwordCount%22%2C%0A%20%20%20%20%22post%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3AblogPost%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40id%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22none%22%3A%20%22%40none%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%22schema%3ABlog%22%2C%0A%20%20%22name%22%3A%20%22World%20Financial%20News%22%2C%0A%20%20%22post%22%3A%20%7B%0A%20%20%20%20%22http%3A%2F%2Fexample.com%2Fposts%2F1%2Fen%22%3A%20%7B%0A%20%20%20%20%20%20%22body%22%3A%20%22World%20commodities%20were%20up%20today%20with%20heavy%20trading%20of%20crude%20oil...%22%2C%0A%20%20%20%20%20%20%22words%22%3A%201539%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22http%3A%2F%2Fexample.com%2Fposts%2F1%2Fde%22%3A%20%7B%0A%20%20%20%20%20%20%22body%22%3A%20%22Die%20Werte%20an%20Warenb%C3%B6rsen%20stiegen%20im%20Sog%20eines%20starken%20Handels%20von%20Roh%C3%B6l...%22%2C%0A%20%20%20%20%20%20%22words%22%3A%201204%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22none%22%3A%20%7B%0A%20%20%20%20%20%20%22body%22%3A%20%22Description%20for%20object%20without%20an%20%40id%22%2C%0A%20%20%20%20%20%20%22words%22%3A%2020%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "schema": "http://schema.org/", + "name": "schema:name", + "body": "schema:articleBody", + "words": "schema:wordCount", + "post": { + "@id": "schema:blogPost", + "@container": "@id" + }, + "none": "@none" + }, + "@id": "http://example.com/", + "@type": "schema:Blog", + "name": "World Financial News", + "post": { + "http://example.com/posts/1/en": { + "body": "World commodities were up today with heavy trading of crude oil...", + "words": 1539 + }, + "http://example.com/posts/1/de": { + "body": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl...", + "words": 1204 + }, + "none": { + "body": "Description for object without an @id", + "words": 20 + } + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing data in JSON-LD by node identifiers using @none-compacted"} +[{ + "@id": "http://example.com/", + "@type": ["http://schema.org/Blog"], + "http://schema.org/name": [{"@value": "World Financial News"}], + "http://schema.org/blogPost": [{ + "@id": "http://example.com/posts/1/en", + "http://schema.org/articleBody": [ + {"@value": "World commodities were up today with heavy trading of crude oil..."} + ], + "http://schema.org/wordCount": [{"@value": 1539}] + }, { + "@id": "http://example.com/posts/1/de", + "http://schema.org/articleBody": [ + {"@value": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."} + ], + "http://schema.org/wordCount": [{"@value": 1204}] + }, { + "http://schema.org/articleBody": [ + {"@value": "Description for object without an @id"} + ], + "http://schema.org/wordCount": [{"@value": 20}] + }] +}] +``` + + Subject Property Value Value Type + ------------------------------- -------------------- ----------------------------------------------------------------------------- ------------- + http://example.com/ rdf:type schema:Blog   + http://example.com/ schema:name World Financial News   + http://example.com/ schema:blogPost http://example.com/posts/1/de   + http://example.com/ schema:blogPost http://example.com/posts/1/en   + http://example.com/ schema:blogPost \_:b0   + http://example.com/posts/1/de schema:articleBody Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl\...   + http://example.com/posts/1/de schema:wordCount 1204 xsd:integer + http://example.com/posts/1/en schema:articleBody World commodities were up today with heavy trading of crude oil\...   + http://example.com/posts/1/en schema:wordCount 1539 xsd:integer + \_:b0 schema:articleBody Description for object without an \@id   + \_:b0 schema:wordCount 20 xsd:integer + +``` {.turtle content-type="text/turtle" result-for="Indexing data in JSON-LD by node identifiers using @none-expanded" to-rdf="" aria-busy="false"} +@prefix rdf: . +@prefix schema: . +@prefix xsd: . + + a schema:Blog; + schema:blogPost , + , [ + schema:articleBody "Description for object without an @id"; + schema:wordCount 20 + ]; + schema:name "World Financial News" . + + schema:articleBody + "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."; + schema:wordCount 1204 . + + schema:articleBody + "World commodities were up today with heavy trading of crude oil..."; + schema:wordCount 1539 . +``` + +Note + +[Id maps](#dfn-id-map) are a new feature in JSON-LD 1.1. + +#### 4.6.4 Node Type Indexing[](#node-type-indexing) + +*This section is non-normative.* + +In addition to [id](#dfn-id-map) and [index maps](#dfn-index-map), JSON-LD introduces the notion of [type maps](#dfn-type-map) for structuring data. The type indexing feature allows an author to structure data using a simple key-value map where the keys map to [IRIs](https://tools.ietf.org/html/rfc3987#section-2). This enables data to be structured based on the `@type` of specific [node objects](#dfn-node-object). In JSON-LD such data can be specified by associating the `@type` [keyword](#dfn-keyword) with a `@container` declaration in the context: + +[Example 106](#example-106-indexing-data-in-json-ld-by-type): Indexing data in JSON-LD by type + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%22affiliation%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3Aaffiliation%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40type%22%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22affiliation%22%3A%20%7B%0A%20%20%20%20%22schema%3ACorporation%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fdigitalbazaar.com%2F%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Digital%20Bazaar%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22schema%3AProfessionalService%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fspec-ops.io%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Spec-Ops%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "schema": "http://schema.org/", + "name": "schema:name", + "affiliation": { + "@id": "schema:affiliation", + "@container": "@type" + } + }, + "name": "Manu Sporny", + "affiliation": { + "schema:Corporation": { + "@id": "https://digitalbazaar.com/", + "name": "Digital Bazaar" + }, + "schema:ProfessionalService": { + "@id": "https://spec-ops.io", + "name": "Spec-Ops" + } + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing data in JSON-LD by type-compacted"} +[{ + "http://schema.org/name": [{"@value": "Manu Sporny"}], + "http://schema.org/affiliation": [ + { + "@id": "https://digitalbazaar.com/", + "@type": ["http://schema.org/Corporation"], + "http://schema.org/name": [{"@value": "Digital Bazaar"}] + }, { + "@id": "https://spec-ops.io", + "@type": ["http://schema.org/ProfessionalService"], + "http://schema.org/name": [{"@value": "Spec-Ops"}] + } + ] +}] +``` + + Subject Property Value + ---------------------------- -------------------- ---------------------------- + https://digitalbazaar.com/ rdf:type schema:Corporation + https://digitalbazaar.com/ schema:name Digital Bazaar + https://spec-ops.io rdf:type schema:ProfessionalService + https://spec-ops.io schema:name Spec-Ops + \_:b0 schema:name Manu Sporny + \_:b0 schema:affiliation https://digitalbazaar.com/ + \_:b0 schema:affiliation https://spec-ops.io + +``` {.turtle content-type="text/turtle" result-for="Indexing data in JSON-LD by type-expanded" to-rdf="" aria-busy="false"} +@prefix rdf: . +@prefix schema: . +@prefix xsd: . + + a schema:Corporation; + schema:name "Digital Bazaar" . + + a schema:ProfessionalService; + schema:name "Spec-Ops" . + +[ + schema:affiliation , ; + schema:name "Manu Sporny" +] . +``` + +In the example above, the `affiliation` [term](#dfn-term) has been marked as a [type map](#dfn-type-map). The `schema:Corporation` and `schema:ProfessionalService` keys will be interpreted as the `@type` property of the [node object](#dfn-node-object) value. + +The value of `@container` can also be an array containing both `@type` and `@set`. When *compacting*, this ensures that a [JSON-LD processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor) will use the [array](https://infra.spec.whatwg.org/#list) form for all values of types. + +[Example 107](#example-107-indexing-data-in-json-ld-by-type-with-set-representation): Indexing data in JSON-LD by type with \@set representation + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%22affiliation%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3Aaffiliation%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%5B%22%40type%22%2C%20%22%40set%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22affiliation%22%3A%20%7B%0A%20%20%20%20%22schema%3ACorporation%22%3A%20%5B%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fdigitalbazaar.com%2F%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Digital%20Bazaar%22%0A%20%20%20%20%7D%5D%2C%0A%20%20%20%20%22schema%3AProfessionalService%22%3A%20%5B%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fspec-ops.io%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Spec-Ops%22%0A%20%20%20%20%7D%5D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "schema": "http://schema.org/", + "name": "schema:name", + "affiliation": { + "@id": "schema:affiliation", + "@container": ["@type", "@set"] + } + }, + "name": "Manu Sporny", + "affiliation": { + "schema:Corporation": [{ + "@id": "https://digitalbazaar.com/", + "name": "Digital Bazaar" + }], + "schema:ProfessionalService": [{ + "@id": "https://spec-ops.io", + "name": "Spec-Ops" + }] + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing data in JSON-LD by type with @set representation-compacted"} +[{ + "http://schema.org/name": [{"@value": "Manu Sporny"}], + "http://schema.org/affiliation": [ + { + "@id": "https://digitalbazaar.com/", + "@type": ["http://schema.org/Corporation"], + "http://schema.org/name": [{"@value": "Digital Bazaar"}] + }, { + "@id": "https://spec-ops.io", + "@type": ["http://schema.org/ProfessionalService"], + "http://schema.org/name": [{"@value": "Spec-Ops"}] + } + ] +}] +``` + + Subject Property Value + ---------------------------- -------------------- ---------------------------- + https://digitalbazaar.com/ rdf:type schema:Corporation + https://digitalbazaar.com/ schema:name Digital Bazaar + https://spec-ops.io rdf:type schema:ProfessionalService + https://spec-ops.io schema:name Spec-Ops + \_:b0 schema:name Manu Sporny + \_:b0 schema:affiliation https://digitalbazaar.com/ + \_:b0 schema:affiliation https://spec-ops.io + +``` {.turtle content-type="text/turtle" result-for="Indexing data in JSON-LD by type with @set representation-expanded" to-rdf="" aria-busy="false"} +@prefix rdf: . +@prefix schema: . +@prefix xsd: . + + a schema:Corporation; + schema:name "Digital Bazaar" . + + a schema:ProfessionalService; + schema:name "Spec-Ops" . + +[ + schema:affiliation , ; + schema:name "Manu Sporny" +] . +``` + +The special index `@none` is used for indexing [node objects](#dfn-node-object) which do not have an `@type`, which is useful to maintain a normalized representation. The `@none` index may also be a term which expands to `@none`, such as the term *none* used in the example below. + +[Example 108](#example-108-indexing-data-in-json-ld-by-type-using-none): Indexing data in JSON-LD by type using \@none + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%22affiliation%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3Aaffiliation%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%22%40type%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22none%22%3A%20%22%40none%22%0A%20%20%7D%2C%0A%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%22affiliation%22%3A%20%7B%0A%20%20%20%20%22schema%3ACorporation%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fdigitalbazaar.com%2F%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Digital%20Bazaar%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22schema%3AProfessionalService%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fspec-ops.io%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Spec-Ops%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22none%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2F%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "schema": "http://schema.org/", + "name": "schema:name", + "affiliation": { + "@id": "schema:affiliation", + "@container": "@type" + }, + "none": "@none" + }, + "name": "Manu Sporny", + "affiliation": { + "schema:Corporation": { + "@id": "https://digitalbazaar.com/", + "name": "Digital Bazaar" + }, + "schema:ProfessionalService": { + "@id": "https://spec-ops.io", + "name": "Spec-Ops" + }, + "none": { + "@id": "https://greggkellogg.net/", + "name": "Gregg Kellogg" + } + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing data in JSON-LD by type using @none-compacted"} +[{ + "http://schema.org/name": [{"@value": "Manu Sporny"}], + "http://schema.org/affiliation": [ + { + "@id": "https://digitalbazaar.com/", + "@type": ["http://schema.org/Corporation"], + "http://schema.org/name": [{"@value": "Digital Bazaar"}] + }, + { + "@id": "https://spec-ops.io", + "@type": ["http://schema.org/ProfessionalService"], + "http://schema.org/name": [{"@value": "Spec-Ops"}] + }, + { + "@id": "https://greggkellogg.net/", + "http://schema.org/name": [{"@value": "Gregg Kellogg"}] + } + ] +}] +``` + + Subject Property Value + ---------------------------- -------------------- ---------------------------- + https://digitalbazaar.com/ rdf:type schema:Corporation + https://digitalbazaar.com/ schema:name Digital Bazaar + https://spec-ops.io rdf:type schema:ProfessionalService + https://spec-ops.io schema:name Spec-Ops + https://greggkellogg.net/ schema:name Gregg Kellogg + \_:b0 schema:name Manu Sporny + \_:b0 schema:affiliation https://digitalbazaar.com/ + \_:b0 schema:affiliation https://spec-ops.io + \_:b0 schema:affiliation https://greggkellogg.net/ + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Indexing data in JSON-LD by type using @none-expanded" to-rdf=""} +@prefix rdf: . +@prefix schema: . +@prefix xsd: . + + a schema:Corporation; + schema:name "Digital Bazaar" . + + a schema:ProfessionalService; + schema:name "Spec-Ops" . + + schema:name "Gregg Kellogg" . + +[ + schema:affiliation + , + , + ; + schema:name "Manu Sporny" +] . +``` + +As with [id maps](#dfn-id-map), when used with `@type`, a container may also include `@set` to ensure that key values are always contained in an array. + +Note + +[Type maps](#dfn-type-map) are a new feature in JSON-LD 1.1. + +### 4.7 Included Nodes[](#included-nodes) + +*This section is non-normative.* + +Sometimes it is also useful to list node objects as part of another node object. For instance, to represent a set of resources which are used by some other resource. [Included blocks](#dfn-included-block) may be also be used to collect such secondary [node objects](#dfn-node-object) which can be referenced from a primary [node object](#dfn-node-object). For an example, consider a node object containing a list of different items, some of which share some common elements: + +[Example 109](#included-blocks-to-be-flattened): Included Blocks + +``` {.input aria-busy="false"} +{ + "@context": { + "@version": 1.1, + "@vocab": "http://example.org/", + "classification": {"@type": "@vocab"} + }, + "@id": "http://example.org/org-1", + "members": [{ + "@id":"http://example.org/person-1", + "name": "Manu Sporny", + "classification": "employee" + }, { + "@id":"http://example.org/person-2", + "name": "Dave Longley", + "classification": "employee" + }, { + "@id": "http://example.org/person-3", + "name": "Gregg Kellogg", + "classification": "contractor" + }], + "@included": [{ + "@id": "http://example.org/employee", + "label": "An Employee" + }, { + "@id": "http://example.org/contractor", + "label": "A Contractor" + }] +} +``` + +When [flattened](https://www.w3.org/TR/json-ld11-api/#dfn-flattened), this will move the `employee` and `contractor` elements from the [included block](#dfn-included-block) into the outer [array](https://infra.spec.whatwg.org/#list). + +[Example 110](#example-110-flattened-form-for-included-blocks): Flattened form for included blocks + +Flattened (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fexample.org%2F%22%2C%0A%20%20%20%20%22classification%22%3A%20%7B%22%40type%22%3A%20%22%40vocab%22%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Forg-1%22%2C%0A%20%20%22members%22%3A%20%5B%7B%0A%20%20%20%20%22%40id%22%3A%22http%3A%2F%2Fexample.org%2Fperson-1%22%2C%0A%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%20%20%22classification%22%3A%20%22employee%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40id%22%3A%22http%3A%2F%2Fexample.org%2Fperson-2%22%2C%0A%20%20%20%20%22name%22%3A%20%22Dave%20Longley%22%2C%0A%20%20%20%20%22classification%22%3A%20%22employee%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fperson-3%22%2C%0A%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%2C%0A%20%20%20%20%22classification%22%3A%20%22contractor%22%0A%20%20%7D%5D%2C%0A%20%20%22%40included%22%3A%20%5B%7B%0A%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Femployee%22%2C%0A%20%20%20%20%22label%22%3A%20%22An%20Employee%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Fcontractor%22%2C%0A%20%20%20%20%22label%22%3A%20%22A%20Contractor%22%0A%20%20%7D%5D%0A%7D) + +``` {.flattened .result .selected flatten="" result-for="Included Blocks" aria-busy="false"} + [{ + "@id": "http://example.org/org-1", + "http://example.org/members": [ + {"@id": "http://example.org/person-1"}, + {"@id": "http://example.org/person-2"}, + {"@id": "http://example.org/person-3"} + ] + }, { + "@id": "http://example.org/employee", + "http://example.org/label": [{"@value": "An Employee"}] + }, { + "@id": "http://example.org/contractor", + "http://example.org/label": [{"@value": "A Contractor"}] + }, { + "@id": "http://example.org/person-1", + "http://example.org/name": [{"@value": "Manu Sporny"}], + "http://example.org/classification": [ + {"@id": "http://example.org/employee"} + ] + }, { + "@id": "http://example.org/person-2", + "http://example.org/name": [{"@value": "Dave Longley"}], + "http://example.org/classification": [ + {"@id": "http://example.org/employee"} + ] + }, { + "@id": "http://example.org/person-3", + "http://example.org/name": [{"@value": "Gregg Kellogg"}], + "http://example.org/classification": [ + {"@id": "http://example.org/contractor"} + ] + } +] +``` + + Subject Property Value + ------------------------------- ----------------------------------- ------------------------------- + http://example.org/org-1 http://example.org/members http://example.org/person-1 + http://example.org/org-1 http://example.org/members http://example.org/person-2 + http://example.org/org-1 http://example.org/members http://example.org/person-3 + http://example.org/employee http://example.org/label An Employee + http://example.org/contractor http://example.org/label A Contractor + http://example.org/person-1 http://example.org/name Manu Sporny + http://example.org/person-1 http://example.org/classification http://example.org/employee + http://example.org/person-2 http://example.org/name Dave Longley + http://example.org/person-2 http://example.org/classification http://example.org/employee + http://example.org/person-3 http://example.org/name Gregg Kellogg + http://example.org/person-3 http://example.org/classification http://example.org/contractor + +``` {.turtle content-type="text/turtle" result-for="Flattened form for included blocks-flattened" to-rdf="" aria-busy="false"} +@prefix ex: . + +ex:org-1 ex:members ex:person-3, + ex:person-1, + ex:person-2 . + +ex:person-1 ex:classification ex:employee; + ex:name "Manu Sporny" . + +ex:person-2 ex:classification ex:employee; + ex:name "Dave Longley" . + +ex:person-3 ex:classification ex:contractor; + ex:name "Gregg Kellogg" . + +ex:employee ex:label "An Employee" . +ex:contractor ex:label "A Contractor" . +``` + +Included resources are described in [Inclusion of Related Resources](https://jsonapi.org/format/#fetching-includes) of [JSON API](https://jsonapi.org/format/) \[[JSON.API](#bib-json.api "JSON API")\] as a way to include related resources associated with some primary resource; `@included` provides an analogous possibility in JSON-LD. + +As a by product of the use of `@included` within [node objects](#dfn-node-object), a [map](https://infra.spec.whatwg.org/#ordered-map) may contain only `@included`, to provide a feature similar to that described in [§ 4.1 Advanced Context Usage](#advanced-context-usage), where `@graph` is used to described disconnected [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node). + +[Example 111](#example-111-describing-disconnected-nodes-with-included): Describing disconnected nodes with \@included + +Compacted (Input) + +Expanded (Result) + +Flattened + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22Person%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2FPerson%22%2C%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fname%22%2C%0A%20%20%20%20%22knows%22%3A%20%7B%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fknows%22%2C%20%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%7D%2C%0A%20%20%22%40included%22%3A%20%5B%7B%0A%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%20%20%22knows%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%2C%0A%20%20%20%20%22knows%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%0A%20%20%7D%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "Person": "http://xmlns.com/foaf/0.1/Person", + "name": "http://xmlns.com/foaf/0.1/name", + "knows": {"@id": "http://xmlns.com/foaf/0.1/knows", "@type": "@id"} + }, + "@included": [{ + "@id": "http://manu.sporny.org/about#manu", + "@type": "Person", + "name": "Manu Sporny", + "knows": "https://greggkellogg.net/foaf#me" + }, { + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg", + "knows": "http://manu.sporny.org/about#manu" + }] +} +``` + +``` {.expanded .result .nohighlight result-for="Describing disconnected nodes with @included-compacted"} +[{ + "@included": [{ + "@id": "http://manu.sporny.org/about#manu", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "https://greggkellogg.net/foaf#me"} + ] + }, { + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Gregg Kellogg"}], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "http://manu.sporny.org/about#manu"} + ] + }] +}] +``` + +``` {.flattened .nohighlight flatten="" result-for="Describing disconnected nodes with @included-expanded"} +[{ + "@id": "http://manu.sporny.org/about#manu", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "https://greggkellogg.net/foaf#me"} + ] +}, { + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Gregg Kellogg"}], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "http://manu.sporny.org/about#manu"} + ] +}] +``` + + Subject Property Value Value Type + ----------------------------------- ------------ ----------------------------------- ------------ + http://manu.sporny.org/about#manu rdf:type foaf:Person   + http://manu.sporny.org/about#manu foaf:name Manu Sporny   + http://manu.sporny.org/about#manu foaf:knows https://greggkellogg.net/foaf#me   + https://greggkellogg.net/foaf#me rdf:type foaf:Person   + https://greggkellogg.net/foaf#me foaf:name Gregg Kellogg   + https://greggkellogg.net/foaf#me foaf:knows http://manu.sporny.org/about#manu   + +``` {.turtle .nohighlight content-type="text/turtle" result-for="Describing disconnected nodes with @included-expanded" to-rdf=""} +@prefix foaf: . + + a foaf:Person; + foaf:name "Manu Sporny"; + foaf:knows . + + a foaf:Person; + foaf:name "Gregg Kellogg"; + foaf:knows . +``` + +However, in contrast to `@graph`, `@included` does not interact with other [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property) contained within the same [map](https://infra.spec.whatwg.org/#ordered-map), a feature discussed further in [§ 4.9 Named Graphs](#named-graphs). + +### 4.8 Reverse Properties[](#reverse-properties) + +*This section is non-normative.* + +JSON-LD serializes directed [graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). That means that every [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) points from a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) to another [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) or [value](#dfn-json-ld-value). However, in some cases, it is desirable to serialize in the reverse direction. Consider for example the case where a person and its children should be described in a document. If the used vocabulary does not provide a *children* [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) but just a *parent* [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property), every [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) representing a child would have to be expressed with a [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) pointing to the parent as in the following example. + +[Example 112](#example-112-a-document-with-children-linking-to-their-parent): A document with children linking to their parent + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%5B%0A%20%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22%23homer%22%2C%0A%20%20%20%20%22http%3A%2F%2Fexample.com%2Fvocab%23name%22%3A%20%22Homer%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22%23bart%22%2C%0A%20%20%20%20%22http%3A%2F%2Fexample.com%2Fvocab%23name%22%3A%20%22Bart%22%2C%0A%20%20%20%20%22http%3A%2F%2Fexample.com%2Fvocab%23parent%22%3A%20%7B%20%22%40id%22%3A%20%22%23homer%22%20%7D%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22%23lisa%22%2C%0A%20%20%20%20%22http%3A%2F%2Fexample.com%2Fvocab%23name%22%3A%20%22Lisa%22%2C%0A%20%20%20%20%22http%3A%2F%2Fexample.com%2Fvocab%23parent%22%3A%20%7B%20%22%40id%22%3A%20%22%23homer%22%20%7D%0A%20%20%7D%0A%5D) + +``` {.compacted .input .selected .nohighlight base="http://example.org/"} +[ + { + "@id": "#homer", + "http://example.com/vocab#name": "Homer" + }, { + "@id": "#bart", + "http://example.com/vocab#name": "Bart", + "http://example.com/vocab#parent": { "@id": "#homer" } + }, { + "@id": "#lisa", + "http://example.com/vocab#name": "Lisa", + "http://example.com/vocab#parent": { "@id": "#homer" } + } +] +``` + +``` {.expanded .result .nohighlight base="http://example.org/" result-for="A document with children linking to their parent-compacted"} +[{ + "@id": "http://example.org/#homer", + "http://example.com/vocab#name": [{"@value": "Homer"}] +}, { + "@id": "http://example.org/#bart", + "http://example.com/vocab#name": [{"@value": "Bart"}], + "http://example.com/vocab#parent": [{"@id": "http://example.org/#homer"}] +}, { + "@id": "http://example.org/#lisa", + "http://example.com/vocab#name": [{"@value": "Lisa"}], + "http://example.com/vocab#parent": [{"@id": "http://example.org/#homer"} + ] +}] +``` + + Subject Property Value + --------------------------- --------------------------------- --------------------------- + http://example.org/#homer http://example.com/vocab#name Homer + http://example.org/#bart http://example.com/vocab#name Bart + http://example.org/#bart http://example.com/vocab#parent http://example.org/#homer + http://example.org/#lisa http://example.com/vocab#name Lisa + http://example.org/#lisa http://example.com/vocab#parent http://example.org/#homer + +``` {.turtle content-type="text/turtle" result-for="A document with children linking to their parent-expanded" base="http://example.org/" to-rdf="" aria-busy="false"} +@base . +<#homer> "Homer" . + +<#bart> "Bart"; + <#homer> . + +<#lisa> "Lisa"; + <#homer> . +``` + +Expressing such data is much simpler by using JSON-LD\'s `@reverse` [keyword](#dfn-keyword): + +[Example 113](#example-113-a-person-and-its-children-using-a-reverse-property): A person and its children using a reverse property + +Compacted (Input) + +Expanded (Result) + +Flattened + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40id%22%3A%20%22%23homer%22%2C%0A%20%20%22http%3A%2F%2Fexample.com%2Fvocab%23name%22%3A%20%22Homer%22%2C%0A%20%20%22%40reverse%22%3A%20%7B%0A%20%20%20%20%22http%3A%2F%2Fexample.com%2Fvocab%23parent%22%3A%20%5B%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%22%40id%22%3A%20%22%23bart%22%2C%0A%20%20%20%20%20%20%20%20%22http%3A%2F%2Fexample.com%2Fvocab%23name%22%3A%20%22Bart%22%0A%20%20%20%20%20%20%7D%2C%20%7B%0A%20%20%20%20%20%20%20%20%22%40id%22%3A%20%22%23lisa%22%2C%0A%20%20%20%20%20%20%20%20%22http%3A%2F%2Fexample.com%2Fvocab%23name%22%3A%20%22Lisa%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight base="http://example.org/"} +{ + "@id": "#homer", + "http://example.com/vocab#name": "Homer", + "@reverse": { + "http://example.com/vocab#parent": [ + { + "@id": "#bart", + "http://example.com/vocab#name": "Bart" + }, { + "@id": "#lisa", + "http://example.com/vocab#name": "Lisa" + } + ] + } +} +``` + +``` {.expanded .result .nohighlight base="http://example.org/" result-for="A person and its children using a reverse property-compacted"} +[{ + "@id": "http://example.org/#homer", + "http://example.com/vocab#name": [{"@value": "Homer"}], + "@reverse": { + "http://example.com/vocab#parent": [{ + "@id": "http://example.org/#bart", + "http://example.com/vocab#name": [{"@value": "Bart"}] + }, { + "@id": "http://example.org/#lisa", + "http://example.com/vocab#name": [{"@value": "Lisa"}] + }] + } +}] +``` + +``` {.flattened .nohighlight base="http://example.org/" flatten="" result-for="A person and its children using a reverse property-expanded"} +[{ + "@id": "http://example.org/#homer", + "http://example.com/vocab#name": [{"@value": "Homer"}] +}, { + "@id": "http://example.org/#bart", + "http://example.com/vocab#name": [{"@value": "Bart"}], + "http://example.com/vocab#parent": [{"@id": "http://example.org/#homer"}] +}, { + "@id": "http://example.org/#lisa", + "http://example.com/vocab#name": [{"@value": "Lisa"}], + "http://example.com/vocab#parent": [{"@id": "http://example.org/#homer"} + ] +}] +``` + + Subject Property Value + --------------------------- --------------------------------- --------------------------- + http://example.org/#homer http://example.com/vocab#name Homer + http://example.org/#bart http://example.com/vocab#name Bart + http://example.org/#bart http://example.com/vocab#parent http://example.org/#homer + http://example.org/#lisa http://example.com/vocab#name Lisa + http://example.org/#lisa http://example.com/vocab#parent http://example.org/#homer + +``` {.turtle content-type="text/turtle" result-for="A person and its children using a reverse property-expanded" base="http://example.org/" to-rdf="" aria-busy="false"} +@base . +<#homer> "Homer" . + +<#bart> "Bart"; + <#homer> . + +<#lisa> "Lisa"; + <#homer> . +``` + +The `@reverse` [keyword](#dfn-keyword) can also be used in [expanded term definitions](#dfn-expanded-term-definition) to create reverse properties as shown in the following example: + +[Example 114](#example-114-using-reverse-to-define-reverse-properties): Using \@reverse to define reverse properties + +Compacted (Input) + +Expanded (Result) + +Flattened + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%20%22name%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%23name%22%2C%0A%20%20%20%20%22children%22%3A%20%7B%20%22%40reverse%22%3A%20%22http%3A%2F%2Fexample.com%2Fvocab%23parent%22%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22%23homer%22%2C%0A%20%20%22name%22%3A%20%22Homer%22%2C%0A%20%20%22children%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22%23bart%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Bart%22%0A%20%20%20%20%7D%2C%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22%23lisa%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Lisa%22%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight base="http://example.org/"} +{ + "@context": { "name": "http://example.com/vocab#name", + "children": { "@reverse": "http://example.com/vocab#parent" } + }, + "@id": "#homer", + "name": "Homer", + "children": [ + { + "@id": "#bart", + "name": "Bart" + }, { + "@id": "#lisa", + "name": "Lisa" + } + ] +} +``` + +``` {.expanded .result .nohighlight base="http://example.org/" result-for="Using @reverse to define reverse properties-compacted"} +[{ + "@id": "http://example.org/#homer", + "http://example.com/vocab#name": [{"@value": "Homer"}], + "@reverse": { + "http://example.com/vocab#parent": [{ + "@id": "http://example.org/#bart", + "http://example.com/vocab#name": [{"@value": "Bart"}] + }, { + "@id": "http://example.org/#lisa", + "http://example.com/vocab#name": [{"@value": "Lisa"}] + }] + } +}] +``` + +``` {.flattened .nohighlight base="http://example.org/" flatten="" result-for="Using @reverse to define reverse properties-expanded"} +[{ + "@id": "http://example.org/#homer", + "http://example.com/vocab#name": [{"@value": "Homer"}] +}, { + "@id": "http://example.org/#bart", + "http://example.com/vocab#name": [{"@value": "Bart"}], + "http://example.com/vocab#parent": [{"@id": "http://example.org/#homer"}] +}, { + "@id": "http://example.org/#lisa", + "http://example.com/vocab#name": [{"@value": "Lisa"}], + "http://example.com/vocab#parent": [{"@id": "http://example.org/#homer"} + ] +}] +``` + + Subject Property Value + --------------------------- --------------------------------- --------------------------- + http://example.org/#homer http://example.com/vocab#name Homer + http://example.org/#bart http://example.com/vocab#name Bart + http://example.org/#bart http://example.com/vocab#parent http://example.org/#homer + http://example.org/#lisa http://example.com/vocab#name Lisa + http://example.org/#lisa http://example.com/vocab#parent http://example.org/#homer + +``` {.turtle content-type="text/turtle" result-for="Using @reverse to define reverse properties-expanded" base="http://example.org/" to-rdf="" aria-busy="false"} +@base . +<#homer> "Homer" . + +<#bart> "Bart"; + <#homer> . + +<#lisa> "Lisa"; + <#homer> . +``` + +### 4.9 Named Graphs[](#named-graphs) + +*This section is non-normative.* + +At times, it is necessary to make statements about a [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) itself, rather than just a single [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node). This can be done by grouping a set of [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node) using the `@graph` [keyword](#dfn-keyword). A developer may also name data expressed using the `@graph` [keyword](#dfn-keyword) by pairing it with an `@id` [keyword](#dfn-keyword) as shown in the following example: + +[Example 115](#example-115-identifying-and-making-statements-about-a-graph): Identifying and making statements about a graph + +Compacted (Input) + +Expanded (Result) + +Statements + +TriG + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22generatedAt%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fwww.w3.org%2Fns%2Fprov%23generatedAtTime%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23dateTime%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22Person%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2FPerson%22%2C%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fname%22%2C%0A%20%20%20%20%22knows%22%3A%20%7B%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fknows%22%2C%20%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Ffoaf-graph%22%2C%0A%20%20%22generatedAt%22%3A%20%222012-04-09T00%3A00%3A00%22%2C%0A%20%20%22%40graph%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%20%20%20%20%22knows%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%0A%20%20%20%20%7D%2C%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%2C%0A%20%20%20%20%20%20%22knows%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "generatedAt": { + "@id": "http://www.w3.org/ns/prov#generatedAtTime", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "Person": "http://xmlns.com/foaf/0.1/Person", + "name": "http://xmlns.com/foaf/0.1/name", + "knows": {"@id": "http://xmlns.com/foaf/0.1/knows", "@type": "@id"} + }, + "@id": "http://example.org/foaf-graph", + "generatedAt": "2012-04-09T00:00:00", + "@graph": [ + { + "@id": "http://manu.sporny.org/about#manu", + "@type": "Person", + "name": "Manu Sporny", + "knows": "https://greggkellogg.net/foaf#me" + }, { + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg", + "knows": "http://manu.sporny.org/about#manu" + } + ] +} +``` + +``` {.expanded .result .nohighlight result-for="Identifying and making statements about a graph-compacted"} +[{ + "@id": "http://example.org/foaf-graph", + "http://www.w3.org/ns/prov#generatedAtTime": [{ + "@value": "2012-04-09T00:00:00", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }], + "@graph": [{ + "@id": "http://manu.sporny.org/about#manu", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "https://greggkellogg.net/foaf#me"} + ] + }, { + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Gregg Kellogg"}], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "http://manu.sporny.org/about#manu"} + ] + }] +}] +``` + + Graph Subject Property Value Value Type + ------------------------------- ----------------------------------- ---------------------- ----------------------------------- -------------- +   http://example.org/foaf-graph prov:generatedAtTime 2012-04-09T00:00:00 xsd:dateTime + http://example.org/foaf-graph http://manu.sporny.org/about#manu rdf:type foaf:Person   + http://example.org/foaf-graph http://manu.sporny.org/about#manu foaf:name Manu Sporny   + http://example.org/foaf-graph http://manu.sporny.org/about#manu foaf:knows https://greggkellogg.net/foaf#me   + http://example.org/foaf-graph https://greggkellogg.net/foaf#me rdf:type foaf:Person   + http://example.org/foaf-graph https://greggkellogg.net/foaf#me foaf:name Gregg Kellogg   + http://example.org/foaf-graph https://greggkellogg.net/foaf#me foaf:knows http://manu.sporny.org/about#manu   + +``` {.trig .nohighlight content-type="application/trig" result-for="Identifying and making statements about a graph-expanded" to-rdf=""} +@prefix foaf: . +@prefix prov: . +@prefix rdf: . +@prefix xsd: . + + prov:generatedAtTime "2012-04-09T00:00:00"^^xsd:dateTime . + + { + a foaf:Person; + foaf:name "Manu Sporny"; + foaf:knows . + + a foaf:Person; + foaf:name "Gregg Kellogg"; + foaf:knows . +} +``` + +The example above expresses a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) that is identified by the [IRI](https://tools.ietf.org/html/rfc3987#section-2) `http://example.org/foaf-graph`. That graph is composed of the statements about Manu and Gregg. Metadata about the graph itself is expressed via the `generatedAt` property, which specifies when the graph was generated. + +When a JSON-LD document\'s top-level structure is a [map](https://infra.spec.whatwg.org/#ordered-map) that contains no other keys than `@graph` and optionally `@context` (properties that are not mapped to an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or a [keyword](#dfn-keyword) are ignored), `@graph` is considered to express the otherwise implicit [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph). This mechanism can be useful when a number of [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node) exist at the document\'s top level that share the same [context](#dfn-context), which is, e.g., the case when a document is [flattened](#flattened-document-form). The `@graph` keyword collects such nodes in an [array](https://infra.spec.whatwg.org/#list) and allows the use of a shared context. + +[Example 116](#example-116-using-graph-to-explicitly-express-the-default-graph): Using \@graph to explicitly express the default graph + +Compacted (Input) + +Expanded (Result) + +Statements + +TriG + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%0A%20%20%7D%2C%0A%20%20%22%40graph%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%0A%20%20%20%20%7D%2C%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@vocab": "http://xmlns.com/foaf/0.1/" + }, + "@graph": [ + { + "@id": "http://manu.sporny.org/about#manu", + "@type": "Person", + "name": "Manu Sporny" + }, { + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg" + } + ] +} +``` + +``` {.expanded .result .nohighlight result-for="Using @graph to explicitly express the default graph-compacted"} +[{ + "@id": "http://manu.sporny.org/about#manu", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}] +}, +{ + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Gregg Kellogg"}] +}] +``` + + Subject Property Value + ----------------------------------- ----------- --------------- + http://manu.sporny.org/about#manu rdf:type foaf:Person + http://manu.sporny.org/about#manu foaf:name Manu Sporny + https://greggkellogg.net/foaf#me rdf:type foaf:Person + https://greggkellogg.net/foaf#me foaf:name Gregg Kellogg + +``` {.trig .nohighlight content-type="application/trig" result-for="Using @graph to explicitly express the default graph-expanded" to-rdf=""} +@prefix foaf: . + + a foaf:Person; + foaf:name "Gregg Kellogg" . + + a foaf:Person; + foaf:name "Manu Sporny" . +``` + +In this case, [embedding](#dfn-embedding) can not be used as the graph contains unrelated nodes. This is equivalent to using multiple [node objects](#dfn-node-object) in array and defining the `@context` within each [node object](#dfn-node-object): + +[Example 117](#example-117-context-needs-to-be-duplicated-if-graph-is-not-used): Context needs to be duplicated if \@graph is not used + +Compacted (Input) + +Expanded (Result) + +Statements + +TriG + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%5B%0A%20%20%7B%0A%20%20%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%2C%0A%20%20%20%20%20%20%22knows%22%3A%20%7B%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%20%20%22knows%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%0A%20%20%7D%2C%0A%20%20%7B%0A%20%20%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%22%2C%0A%20%20%20%20%20%20%22knows%22%3A%20%7B%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%2C%0A%20%20%20%20%22knows%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%0A%20%20%7D%0A%5D) + +``` {.compacted .input .selected .nohighlight} +[ + { + "@context": { + "@vocab": "http://xmlns.com/foaf/0.1/", + "knows": {"@type": "@id"} + }, + "@id": "http://manu.sporny.org/about#manu", + "@type": "Person", + "name": "Manu Sporny", + "knows": "https://greggkellogg.net/foaf#me" + }, + { + "@context": { + "@vocab": "http://xmlns.com/foaf/0.1/", + "knows": {"@type": "@id"} + }, + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg", + "knows": "http://manu.sporny.org/about#manu" + } +] +``` + +``` {.expanded .result .nohighlight result-for="Context needs to be duplicated if @graph is not used-compacted"} +[{ + "@id": "http://manu.sporny.org/about#manu", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "https://greggkellogg.net/foaf#me"} + ] +}, +{ + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Gregg Kellogg"}], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "http://manu.sporny.org/about#manu"} + ] +}] +``` + + Subject Property Value + ----------------------------------- ------------ ----------------------------------- + http://manu.sporny.org/about#manu rdf:type foaf:Person + http://manu.sporny.org/about#manu foaf:name Manu Sporny + http://manu.sporny.org/about#manu foaf:knows https://greggkellogg.net/foaf#me + https://greggkellogg.net/foaf#me rdf:type foaf:Person + https://greggkellogg.net/foaf#me foaf:name Gregg Kellogg + https://greggkellogg.net/foaf#me foaf:knows http://manu.sporny.org/about#manu + +``` {.trig .nohighlight content-type="application/trig" result-for="Context needs to be duplicated if @graph is not used-expanded" to-rdf=""} +@prefix foaf: . + + a foaf:Person; + foaf:knows ; + foaf:name "Gregg Kellogg" . + + a foaf:Person; + foaf:knows ; + foaf:name "Manu Sporny" . +``` + +#### 4.9.1 Graph Containers[](#graph-containers) + +*This section is non-normative.* + +In some cases, it is useful to logically partition data into separate graphs, without making this explicit within the JSON expression. For example, a JSON document may contain data against which other metadata is asserted and it is useful to separate this data in the data model using the notion of [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), without the syntactic overhead associated with the `@graph` keyword. + +An [expanded term definition](#dfn-expanded-term-definition) can use `@graph` as the value of `@container`. This indicates that values of this [term](#dfn-term) should be considered to be [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), where the [graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name) is an automatically assigned [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) creating an [implicitly named graph](#dfn-implicitly-named-graph). When expanded, these become [simple graph objects](#dfn-simple-graph-object). + +A different example uses an anonymously [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) as follows: + +[Example 118](#example-118-implicitly-named-graph): Implicitly named graph + +Compacted (Input) + +Expanded (Result) + +Statements + +TriG + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22%40base%22%3A%20%22http%3A%2F%2Fdbpedia.org%2Fresource%2F%22%2C%0A%20%20%20%20%22said%22%3A%20%22http%3A%2F%2Fexample.com%2Fsaid%22%2C%0A%20%20%20%20%22wrote%22%3A%20%7B%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fwrote%22%2C%20%22%40container%22%3A%20%22%40graph%22%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22William_Shakespeare%22%2C%0A%20%20%22wrote%22%3A%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22Richard_III_of_England%22%2C%0A%20%20%20%20%22said%22%3A%20%22My%20kingdom%20for%20a%20horse%22%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "@base": "http://dbpedia.org/resource/", + "said": "http://example.com/said", + "wrote": {"@id": "http://example.com/wrote", "@container": "@graph"} + }, + "@id": "William_Shakespeare", + "wrote": { + "@id": "Richard_III_of_England", + "said": "My kingdom for a horse" + } +} +``` + +``` {.expanded .result .nohighlight result-for="Implicitly named graph-compacted"} +[{ + "@id": "http://dbpedia.org/resource/William_Shakespeare", + "http://example.com/wrote": [{ + "@graph": [{ + "@id": "http://dbpedia.org/resource/Richard_III_of_England", + "http://example.com/said": [{"@value": "My kingdom for a horse"}] + }] + }] +}] +``` + + Graph Subject Property Value + ------- ---------------------------------------------------- -------------------------- ------------------------ + \_:b0 http://dbpedia.org/resource/Richard_III_of_England http://example.com/said My kingdom for a horse +   http://dbpedia.org/resource/William_Shakespeare http://example.com/wrote \_:b0 + +``` {.trig .nohighlight content-type="application/trig" result-for="Implicitly named graph-expanded" to-rdf=""} +@prefix dbp: . +@prefix ex: . + +dbp:William_Shakespeare ex:wrote _:b0 . + +_:b0 { + dbp:Richard_III_of_England ex:said "My kingdom for a horse" . +} +``` + +The example above expresses an anonymously [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) making a statement. The [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) includes a statement saying that the [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) wrote that statement. This is an example of separating statements into a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), and then making assertions about the statements contained within that [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph). + +Note + +Strictly speaking, the value of such a [term](#dfn-term) is not a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), rather it is the [graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name) associated with the [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), which exists separately within the [dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset). + +Note + +Graph Containers are a new feature in JSON-LD 1.1. + +#### 4.9.2 Named Graph Data Indexing[](#named-graph-data-indexing) + +*This section is non-normative.* + +In addition to indexing [node objects](#dfn-node-object) by index, [graph objects](#dfn-graph-object) may also be indexed by an index. By using the `@graph` container type, introduced in [§ 4.9.1 Graph Containers](#graph-containers) in addition to `@index`, an object value of such a property is treated as a key-value map where the keys do not map to [IRIs](https://tools.ietf.org/html/rfc3987#section-2), but are taken from an `@index` property associated with [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) which are their values. When expanded, these must be [simple graph objects](#dfn-simple-graph-object) + +The following example describes a [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) referencing multiple named graphs using an [index map](#dfn-index-map). + +[Example 119](#example-119-indexing-graph-data-in-json-ld): Indexing graph data in JSON-LD + +Compacted (Input) + +Expanded (Result) + +Statements + +TriG + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%20%22body%22%3A%20%22schema%3AarticleBody%22%2C%0A%20%20%20%20%20%22words%22%3A%20%22schema%3AwordCount%22%2C%0A%20%20%20%20%20%22post%22%3A%20%7B%0A%20%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3AblogPost%22%2C%0A%20%20%20%20%20%20%20%22%40container%22%3A%20%5B%22%40graph%22%2C%20%22%40index%22%5D%0A%20%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%22schema%3ABlog%22%2C%0A%20%20%22name%22%3A%20%22World%20Financial%20News%22%2C%0A%20%20%22post%22%3A%20%7B%0A%20%20%20%20%20%22en%22%3A%20%7B%0A%20%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fposts%2F1%2Fen%22%2C%0A%20%20%20%20%20%20%20%22body%22%3A%20%22World%20commodities%20were%20up%20today%20with%20heavy%20trading%20of%20crude%20oil...%22%2C%0A%20%20%20%20%20%20%20%22words%22%3A%201539%0A%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%22de%22%3A%20%7B%0A%20%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fposts%2F1%2Fde%22%2C%0A%20%20%20%20%20%20%20%22body%22%3A%20%22Die%20Werte%20an%20Warenb%C3%B6rsen%20stiegen%20im%20Sog%20eines%20starken%20Handels%20von%20Roh%C3%B6l...%22%2C%0A%20%20%20%20%20%20%20%22words%22%3A%201204%0A%20%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "schema": "http://schema.org/", + "name": "schema:name", + "body": "schema:articleBody", + "words": "schema:wordCount", + "post": { + "@id": "schema:blogPost", + "@container": ["@graph", "@index"] + } + }, + "@id": "http://example.com/", + "@type": "schema:Blog", + "name": "World Financial News", + "post": { + "en": { + "@id": "http://example.com/posts/1/en", + "body": "World commodities were up today with heavy trading of crude oil...", + "words": 1539 + }, + "de": { + "@id": "http://example.com/posts/1/de", + "body": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl...", + "words": 1204 + } + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing graph data in JSON-LD-compacted"} +[{ + "@id": "http://example.com/", + "@type": ["http://schema.org/Blog"], + "http://schema.org/name": [{"@value": "World Financial News"}], + "http://schema.org/blogPost": [{ + "@graph": [{ + "@id": "http://example.com/posts/1/en", + "http://schema.org/articleBody": [{ + "@value": "World commodities were up today with heavy trading of crude oil..." + }], + "http://schema.org/wordCount": [{"@value": 1539}] + }], + "@index": "en" + }, { + "@graph": [{ + "@id": "http://example.com/posts/1/de", + "http://schema.org/articleBody": [{ + "@value": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..." + }], + "http://schema.org/wordCount": [{"@value": 1204}] + }], + "@index": "de" + }] +}] +``` + + Graph Subject Property Value Value Type + ------- ------------------------------- -------------------- ----------------------------------------------------------------------------- ------------- +   http://example.com/ rdf:type schema:Blog +   http://example.com/ schema:name World Financial News +   http://example.com/ schema:blogPost \_:b1 +   http://example.com/ schema:blogPost \_:b2 + \_:b1 http://example.com/posts/1/de schema:articleBody Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl\... + \_:b1 http://example.com/posts/1/de schema:wordCount 1204 xsd:integer + \_:b2 http://example.com/posts/1/en schema:articleBody World commodities were up today with heavy trading of crude oil\... + \_:b2 http://example.com/posts/1/en schema:wordCount 1539 xsd:integer + +``` {.trig .nohighlight content-type="application/trig" result-for="Indexing graph data in JSON-LD-expanded" to-rdf=""} +@prefix rdf: . +@prefix schema: . +@prefix xsd: . + + a schema:Blog; + schema:name "World Financial News"; + schema:blogPost _:b0, _:b1 . + +_:b0 { + + schema:articleBody + "World commodities were up today with heavy trading of crude oil..."; + schema:wordCount 1539 . +} + +_:b1 { + + schema:articleBody + "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."; + schema:wordCount 1204 . +} +``` + +As with [index maps](#dfn-index-map), when used with `@graph`, a container may also include `@set` to ensure that key values are always contained in an array. + +The special index `@none` is used for indexing graphs which do not have an `@index` key, which is useful to maintain a normalized representation. Note, however, that compacting a document where multiple unidentified named graphs are compacted using the `@none` index will result in the content of those graphs being merged. To prevent this, give each graph a distinct `@index` key. + +[Example 120](#example-120-indexing-graphs-using-none-for-no-index): Indexing graphs using \@none for no index + +Compacted (Input) + +Expanded (Result) + +Statements + +TriG + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%20%22schema%22%3A%20%22http%3A%2F%2Fschema.org%2F%22%2C%0A%20%20%20%20%20%22name%22%3A%20%22schema%3Aname%22%2C%0A%20%20%20%20%20%22body%22%3A%20%22schema%3AarticleBody%22%2C%0A%20%20%20%20%20%22words%22%3A%20%22schema%3AwordCount%22%2C%0A%20%20%20%20%20%22post%22%3A%20%7B%0A%20%20%20%20%20%20%20%22%40id%22%3A%20%22schema%3AblogPost%22%2C%0A%20%20%20%20%20%20%20%22%40container%22%3A%20%5B%22%40graph%22%2C%20%22%40index%22%5D%0A%20%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2F%22%2C%0A%20%20%22%40type%22%3A%20%22schema%3ABlog%22%2C%0A%20%20%22name%22%3A%20%22World%20Financial%20News%22%2C%0A%20%20%22post%22%3A%20%7B%0A%20%20%20%20%20%22en%22%3A%20%7B%0A%20%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fposts%2F1%2Fen%22%2C%0A%20%20%20%20%20%20%20%22body%22%3A%20%22World%20commodities%20were%20up%20today%20with%20heavy%20trading%20of%20crude%20oil...%22%2C%0A%20%20%20%20%20%20%20%22words%22%3A%201539%0A%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%22%40none%22%3A%20%7B%0A%20%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.com%2Fposts%2F1%2Fno-language%22%2C%0A%20%20%20%20%20%20%20%22body%22%3A%20%22Die%20Werte%20an%20Warenb%C3%B6rsen%20stiegen%20im%20Sog%20eines%20starken%20Handels%20von%20Roh%C3%B6l...%22%2C%0A%20%20%20%20%20%20%20%22words%22%3A%201204%0A%20%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "schema": "http://schema.org/", + "name": "schema:name", + "body": "schema:articleBody", + "words": "schema:wordCount", + "post": { + "@id": "schema:blogPost", + "@container": ["@graph", "@index"] + } + }, + "@id": "http://example.com/", + "@type": "schema:Blog", + "name": "World Financial News", + "post": { + "en": { + "@id": "http://example.com/posts/1/en", + "body": "World commodities were up today with heavy trading of crude oil...", + "words": 1539 + }, + "@none": { + "@id": "http://example.com/posts/1/no-language", + "body": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl...", + "words": 1204 + } + } +} +``` + +``` {.expanded .result .nohighlight result-for="Indexing graphs using @none for no index-compacted"} +[{ + "@id": "http://example.com/", + "@type": ["http://schema.org/Blog"], + "http://schema.org/name": [{"@value": "World Financial News"}], + "http://schema.org/blogPost": [{ + "@graph": [{ + "@id": "http://example.com/posts/1/en", + "http://schema.org/articleBody": [{ + "@value": "World commodities were up today with heavy trading of crude oil..." + }], + "http://schema.org/wordCount": [{"@value": 1539}] + }], + "@index": "en" + }, { + "@graph": [{ + "@id": "http://example.com/posts/1/no-language", + "http://schema.org/articleBody": [{ + "@value": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..." + }], + "http://schema.org/wordCount": [{"@value": 1204}] + }] + }] +}] +``` + + Graph Subject Property Value Value Type + ------- ---------------------------------------- -------------------- ----------------------------------------------------------------------------- ------------- +   http://example.com/ rdf:type schema:Blog   +   http://example.com/ schema:name World Financial News   +   http://example.com/ schema:blogPost \_:b0   +   http://example.com/ schema:blogPost \_:b1   + \_:b0 http://example.com/posts/1/en schema:articleBody World commodities were up today with heavy trading of crude oil\...   + \_:b0 http://example.com/posts/1/en schema:wordCount 1539 xsd:integer + \_:b1 http://example.com/posts/1/no-language schema:articleBody Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl\...   + \_:b1 http://example.com/posts/1/no-language schema:wordCount 1204 xsd:integer + +``` {.trig .nohighlight content-type="application/trig" result-for="Indexing graphs using @none for no index-expanded" to-rdf=""} +@prefix rdf: . +@prefix schema: . +@prefix xsd: . + + a schema:Blog; + schema:blogPost _:b0, _:b1; + schema:name "World Financial News" . + +_:b0 { + + schema:articleBody + "World commodities were up today with heavy trading of crude oil..."; + schema:wordCount 1539 . +} + +_:b1 { + + schema:articleBody + "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."; + schema:wordCount 1204 . +} +``` + +Note + +Named Graph Data Indexing is a new feature in JSON-LD 1.1. + +#### 4.9.3 Named Graph Indexing[](#named-graph-indexing) + +*This section is non-normative.* + +In addition to indexing [node objects](#dfn-node-object) by identifier, [graph objects](#dfn-graph-object) may also be indexed by their [graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name). By using the `@graph` container type, introduced in [§ 4.9.1 Graph Containers](#graph-containers) in addition to `@id`, an object value of such a property is treated as a key-value map where the keys represent the identifiers of [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) which are their values. + +The following example describes a [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) referencing multiple named graphs using an [id map](#dfn-id-map). + +[Example 121](#example-121-referencing-named-graphs-using-an-id-map): Referencing named graphs using an id map + +Compacted (Input) + +Expanded (Result) + +Statements + +TriG + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22generatedAt%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fwww.w3.org%2Fns%2Fprov%23generatedAtTime%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23dateTime%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22Person%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2FPerson%22%2C%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fname%22%2C%0A%20%20%20%20%22knows%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fknows%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22%40id%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22graphMap%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2FgraphMap%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%5B%22%40graph%22%2C%20%22%40id%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Ffoaf-graph%22%2C%0A%20%20%22generatedAt%22%3A%20%222012-04-09T00%3A00%3A00%22%2C%0A%20%20%22graphMap%22%3A%20%7B%0A%20%20%20%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%20%20%20%20%22knows%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%2C%0A%20%20%20%20%20%20%22knows%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "generatedAt": { + "@id": "http://www.w3.org/ns/prov#generatedAtTime", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "Person": "http://xmlns.com/foaf/0.1/Person", + "name": "http://xmlns.com/foaf/0.1/name", + "knows": { + "@id": "http://xmlns.com/foaf/0.1/knows", + "@type": "@id" + }, + "graphMap": { + "@id": "http://example.org/graphMap", + "@container": ["@graph", "@id"] + } + }, + "@id": "http://example.org/foaf-graph", + "generatedAt": "2012-04-09T00:00:00", + "graphMap": { + "http://manu.sporny.org/about": { + "@id": "http://manu.sporny.org/about#manu", + "@type": "Person", + "name": "Manu Sporny", + "knows": "https://greggkellogg.net/foaf#me" + }, + "https://greggkellogg.net/foaf": { + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg", + "knows": "http://manu.sporny.org/about#manu" + } + } +} +``` + +``` {.expanded .result .nohighlight result-for="Referencing named graphs using an id map-compacted"} +[{ + "@id": "http://example.org/foaf-graph", + "http://www.w3.org/ns/prov#generatedAtTime": [{ + "@value": "2012-04-09T00:00:00", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }], + "http://example.org/graphMap": [{ + "@graph": [{ + "@id": "http://manu.sporny.org/about#manu", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "https://greggkellogg.net/foaf#me"} + ], + "http://xmlns.com/foaf/0.1/name": [ + {"@value": "Manu Sporny"} + ] + }], + "@id": "http://manu.sporny.org/about" + }, { + "@graph": [{ + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "http://manu.sporny.org/about#manu"} + ], + "http://xmlns.com/foaf/0.1/name": [ + {"@value": "Gregg Kellogg"} + ] + }], + "@id": "https://greggkellogg.net/foaf" + }] +}] +``` + + Graph Subject Property Value Value Type + ------------------------------- ----------------------------------- ----------------------------- ----------------------------------- -------------- +   http://example.org/foaf-graph http://example.org/graphMap https://greggkellogg.net/foaf   +   http://example.org/foaf-graph http://example.org/graphMap http://manu.sporny.org/about   +   http://example.org/foaf-graph prov:generatedAtTime 2012-04-09T00:00:00 xsd:dateTime + https://greggkellogg.net/foaf https://greggkellogg.net/foaf#me rdf:type foaf:Person   + https://greggkellogg.net/foaf https://greggkellogg.net/foaf#me foaf:name Gregg Kellogg   + https://greggkellogg.net/foaf https://greggkellogg.net/foaf#me foaf:knows http://manu.sporny.org/about#manu   + http://manu.sporny.org/about http://manu.sporny.org/about#manu rdf:type foaf:Person   + http://manu.sporny.org/about http://manu.sporny.org/about#manu foaf:name Manu Sporny   + http://manu.sporny.org/about http://manu.sporny.org/about#manu foaf:knows https://greggkellogg.net/foaf#me   + +``` {.trig .nohighlight content-type="application/trig" result-for="Referencing named graphs using an id map-expanded" to-rdf=""} +@prefix foaf: . +@prefix prov: . +@prefix rdf: . +@prefix xsd: . + + + + , + ; + prov:generatedAtTime "2012-04-09T00:00:00"^^xsd:dateTime . + + { + a foaf:Person; + foaf:knows ; + foaf:name "Gregg Kellogg" . +} + + { + a foaf:Person; + foaf:knows ; + foaf:name "Manu Sporny" . +} +``` + +As with [id maps](#dfn-id-map), when used with `@graph`, a container may also include `@set` to ensure that key values are always contained in an array. + +As with [id maps](#dfn-id-map), the special index `@none` is used for indexing [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) which do not have an `@id`, which is useful to maintain a normalized representation. The `@none` index may also be a term which expands to `@none`. Note, however, that if multiple graphs are represented without an `@id`, they will be merged on expansion. To prevent this, use `@none` judiciously, and consider giving graphs their own distinct identifier. + +[Example 122](#example-122-referencing-named-graphs-using-an-id-map-with-none): Referencing named graphs using an id map with \@none + +Compacted (Input) + +Expanded (Result) + +Statements + +TriG + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22generatedAt%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fwww.w3.org%2Fns%2Fprov%23generatedAtTime%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23dateTime%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22Person%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2FPerson%22%2C%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fname%22%2C%0A%20%20%20%20%22knows%22%3A%20%7B%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fknows%22%2C%20%22%40type%22%3A%20%22%40id%22%7D%2C%0A%20%20%20%20%22graphMap%22%3A%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2FgraphMap%22%2C%0A%20%20%20%20%20%20%22%40container%22%3A%20%5B%22%40graph%22%2C%20%22%40id%22%5D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Ffoaf-graph%22%2C%0A%20%20%22generatedAt%22%3A%20%222012-04-09T00%3A00%3A00%22%2C%0A%20%20%22graphMap%22%3A%20%7B%0A%20%20%20%20%22%40none%22%3A%20%5B%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%20%20%20%20%22knows%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%0A%20%20%20%20%7D%2C%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22https%3A%2F%2Fgreggkellogg.net%2Ffoaf%23me%22%2C%0A%20%20%20%20%20%20%22%40type%22%3A%20%22Person%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Gregg%20Kellogg%22%2C%0A%20%20%20%20%20%20%22knows%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%0A%20%20%20%20%7D%5D%0A%20%20%7D%0A%7D) + +``` {.compacted .input .selected .nohighlight} +{ + "@context": { + "@version": 1.1, + "generatedAt": { + "@id": "http://www.w3.org/ns/prov#generatedAtTime", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "Person": "http://xmlns.com/foaf/0.1/Person", + "name": "http://xmlns.com/foaf/0.1/name", + "knows": {"@id": "http://xmlns.com/foaf/0.1/knows", "@type": "@id"}, + "graphMap": { + "@id": "http://example.org/graphMap", + "@container": ["@graph", "@id"] + } + }, + "@id": "http://example.org/foaf-graph", + "generatedAt": "2012-04-09T00:00:00", + "graphMap": { + "@none": [{ + "@id": "http://manu.sporny.org/about#manu", + "@type": "Person", + "name": "Manu Sporny", + "knows": "https://greggkellogg.net/foaf#me" + }, { + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg", + "knows": "http://manu.sporny.org/about#manu" + }] + } +} +``` + +``` {.expanded .result .nohighlight result-for="Referencing named graphs using an id map with @none-compacted"} +[{ + "@id": "http://example.org/foaf-graph", + "http://www.w3.org/ns/prov#generatedAtTime": [{ + "@value": "2012-04-09T00:00:00", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }], + "http://example.org/graphMap": [{ + "@graph": [{ + "@id": "http://manu.sporny.org/about#manu", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "https://greggkellogg.net/foaf#me"} + ] + }] + }, + { + "@graph": [{ + "@id": "https://greggkellogg.net/foaf#me", + "@type": ["http://xmlns.com/foaf/0.1/Person"], + "http://xmlns.com/foaf/0.1/name": [{"@value": "Gregg Kellogg"}], + "http://xmlns.com/foaf/0.1/knows": [ + {"@id": "http://manu.sporny.org/about#manu"} + ] + }] + }] +}] +``` + + Graph Subject Property Value Value Type + ------- ----------------------------------- ----------------------------- ----------------------------------- -------------- +   http://example.org/foaf-graph prov:generatedAtTime 2012-04-09T00:00:00 xsd:dateTime +   http://example.org/foaf-graph http://example.org/graphMap \_:b0   +   http://example.org/foaf-graph http://example.org/graphMap \_:b1   + \_:b0 http://manu.sporny.org/about#manu rdf:type foaf:Person   + \_:b0 http://manu.sporny.org/about#manu foaf:name Manu Sporny   + \_:b0 http://manu.sporny.org/about#manu foaf:knows https://greggkellogg.net/foaf#me   + \_:b1 https://greggkellogg.net/foaf#me rdf:type foaf:Person   + \_:b1 https://greggkellogg.net/foaf#me foaf:name Gregg Kellogg   + \_:b1 https://greggkellogg.net/foaf#me foaf:knows http://manu.sporny.org/about#manu   + +``` {.trig .nohighlight content-type="application/trig" result-for="Referencing named graphs using an id map with @none-expanded" to-rdf=""} +@prefix foaf: . +@prefix prov: . +@prefix rdf: . +@prefix xsd: . + + _:b0, _:b1; + prov:generatedAtTime "2012-04-09T00:00:00"^^xsd:dateTime . + +_:b0 { + a foaf:Person; + foaf:name "Manu Sporny"; + foaf:knows . +} + +_:b1 { + a foaf:Person; + foaf:name "Gregg Kellogg"; + foaf:knows . +} +``` + +Note + +Graph Containers are a new feature in JSON-LD 1.1. + +### 4.10 Loading Documents[](#loading-documents) + +*This section is non-normative.* + +The JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\] defines the interface to a [JSON-LD Processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor) and includes a number of methods used for manipulating different forms of JSON-LD (see [§ 5. Forms of JSON-LD](#forms-of-json-ld)). This includes a general mechanism for loading remote documents, including referenced JSON-LD documents and remote contexts, and potentially extracting embedded JSON-LD from other formats such as \[[HTML](#bib-html "HTML Standard")\]. This is more fully described in [Remote Document and Context Retrieval](https://www.w3.org/TR/json-ld11-api/#remote-document-and-context-retrieval) in \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\]. + +A [documentLoader](https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-documentloader) can be useful in a number of contexts where loading remote documents can be problematic: + +- Remote context documents should be cached to prevent overloading the location of the remote context for each request. Normally, an HTTP caching infrastructure might be expected to handle this, but in some contexts this might not be feasible. A [documentLoader](https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-documentloader) implementation might provide separate logic for performing such caching. +- Non-standard URL schemes may not be widely implemented, or may have behavior specific to a given application domain. A [documentLoader](https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-documentloader) can be defined to implement document retrieval semantics. +- Certain well-known contexts may be statically cached within a [documentLoader](https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-documentloader) implementation. This might be particularly useful in embedded applications, where it is not feasible, or even possible, to access remote documents. +- For security purposes, the act of remotely retrieving a document may provide a signal of application behavior. The judicious use of a [documentLoader](https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-documentloader) can isolate the application and reduce its online fingerprint. + +## 5. Forms of JSON-LD[](#forms-of-json-ld) + +*This section is non-normative.* + +As with many data formats, there is no single correct way to describe data in JSON-LD. However, as JSON-LD is used for describing graphs, certain transformations can be used to change the shape of the data, without changing its meaning as Linked Data. + +Expanded Document Form +: [Expansion](https://www.w3.org/TR/json-ld11-api/#dfn-expanded) is the process of taking a JSON-LD document and applying a [context](#dfn-context) so that the `@context` is no longer necessary. This process is described further in [§ 5.1 Expanded Document Form](#expanded-document-form). + +Compacted Document Form +: [Compaction](https://www.w3.org/TR/json-ld11-api/#dfn-compact) is the process of applying a provided [context](#dfn-context) to an existing JSON-LD document. This process is described further in [§ 5.2 Compacted Document Form](#compacted-document-form). + +Flattened Document Form +: [Flattening](https://www.w3.org/TR/json-ld11-api/#dfn-flattened) is the process of extracting embedded nodes to the top level of the JSON tree, and replacing the embedded node with a reference, creating blank node identifiers as necessary. This process is described further in [§ 5.3 Flattened Document Form](#flattened-document-form). + +Framed Document Form +: [Framing](https://www.w3.org/TR/json-ld11-framing/#dfn-framing) is used to shape the data in a JSON-LD document, using an example [frame](https://www.w3.org/TR/json-ld11-framing/#dfn-frame) document which is used to both match the [flattened](https://www.w3.org/TR/json-ld11-api/#dfn-flattened) data and show an example of how the resulting data should be shaped. This process is described further in [§ 5.4 Framed Document Form](#framed-document-form). + +### 5.1 Expanded Document Form[](#expanded-document-form) + +*This section is non-normative.* + +The JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\] defines a method for *expanding* a JSON-LD document. [Expansion](https://www.w3.org/TR/json-ld11-api/#dfn-expanded) is the process of taking a JSON-LD document and applying a [context](#dfn-context) such that all IRIs, types, and values are expanded so that the `@context` is no longer necessary. + +For example, assume the following JSON-LD input document: + +[Example 123](#sample-json-ld-document-to-be-expanded): Sample JSON-LD document to be expanded + +``` {.input aria-busy="false"} +{ + "@context": { + "name": "http://xmlns.com/foaf/0.1/name", + "homepage": { + "@id": "http://xmlns.com/foaf/0.1/homepage", + "@type": "@id" + } + }, + "name": "Manu Sporny", + "homepage": "http://manu.sporny.org/" +} +``` + +Running the JSON-LD [Expansion algorithm](https://www.w3.org/TR/json-ld11-api/#expansion-algorithm) against the JSON-LD input document provided above would result in the following output: + +[Example 124](#example-124-expanded-form-for-the-previous-example): Expanded form for the previous example + +Expanded (Result) + +Statements + +Turtle + +[Open in playground](https://json-ld.org/playground/#startTab=tab-expand&json-ld=%7B%0A%20%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fname%22%2C%0A%20%20%20%20%20%20%22homepage%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fhomepage%22%2C%0A%20%20%20%20%20%20%20%20%22%40type%22%3A%20%22%40id%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%7D%2C%0A%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%2C%0A%20%20%20%22homepage%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2F%22%0A%7D) + +``` {.expanded .result .selected result-for="Sample JSON-LD document to be expanded" aria-busy="false"} +[ + { + "http://xmlns.com/foaf/0.1/name": [ + { "@value": "Manu Sporny" } + ], + "http://xmlns.com/foaf/0.1/homepage": [ + { "@id": "http://manu.sporny.org/" } + ] + } +] +``` + + Subject Property Value + --------- --------------- ------------------------- + \_:b0 foaf:name Manu Sporny + \_:b0 foaf:homepage http://manu.sporny.org/ + +``` {.turtle content-type="text/turtle" result-for="Expanded form for the previous example-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . + +[ + foaf:name "Manu Sporny"; + foaf:homepage +] . +``` + +[JSON-LD\'s media type](#application-ld-json) defines a `profile` parameter which can be used to signal or request expanded document form. The profile URI identifying [expanded document form](#dfn-expanded-document-form) is `http://www.w3.org/ns/json-ld#expanded`. + +### 5.2 Compacted Document Form[](#compacted-document-form) + +*This section is non-normative.* + +The JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\] defines a method for *compacting* a JSON-LD document. [Compaction](https://www.w3.org/TR/json-ld11-api/#dfn-compact) is the process of applying a developer-supplied [context](#dfn-context) to shorten [IRIs](https://tools.ietf.org/html/rfc3987#section-2) to [terms](#dfn-term) or [compact IRIs](#dfn-compact-iri) and JSON-LD values expressed in expanded form to simple values such as [strings](https://infra.spec.whatwg.org/#javascript-string) or [numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value). Often this makes it simpler to work with document as the data is expressed in application-specific terms. Compacted documents are also typically easier to read for humans. + +For example, assume the following JSON-LD input document: + +[Example 125](#sample-expanded-json-ld-document): Sample expanded JSON-LD document + +``` {.input aria-busy="false"} +[ + { + "http://xmlns.com/foaf/0.1/name": [ "Manu Sporny" ], + "http://xmlns.com/foaf/0.1/homepage": [ + { + "@id": "http://manu.sporny.org/" + } + ] + } +] +``` + +Additionally, assume the following developer-supplied JSON-LD context: + +[Example 126](#sample-context): Sample context + +``` {.context context-for="Sample expanded JSON-LD document" aria-busy="false"} +{ + "@context": { + "name": "http://xmlns.com/foaf/0.1/name", + "homepage": { + "@id": "http://xmlns.com/foaf/0.1/homepage", + "@type": "@id" + } + } +} +``` + +Running the JSON-LD [Compaction algorithm](https://www.w3.org/TR/json-ld11-api/#compaction-algorithm) given the [context](#dfn-context) supplied above against the JSON-LD input document provided above would result in the following output: + +[Example 127](#example-127-compact-form-of-the-sample-document-once-sample-context-has-been-applied): Compact form of the sample document once sample context has been applied + +``` {.selected .original result-for="Sample expanded JSON-LD document" data-compact="" context="Sample context" aria-busy="false"} +{ + "@context": { + "name": "http://xmlns.com/foaf/0.1/name", + "homepage": { + "@id": "http://xmlns.com/foaf/0.1/homepage", + "@type": "@id" + } + }, + "name": "Manu Sporny", + "homepage": "http://manu.sporny.org/" +} +``` + +[JSON-LD\'s media type](#application-ld-json) defines a `profile` parameter which can be used to signal or request compacted document form. The profile URI identifying [compacted document form](#dfn-compacted-document-form) is `http://www.w3.org/ns/json-ld#compacted`. + +The details of Compaction are described in the [Compaction algorithm](https://www.w3.org/TR/json-ld11-api/#compaction-algorithm) in \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\]. This section provides a short description of how the algorithm operates as a guide to authors creating [contexts](#dfn-context) to be used for *compacting* JSON-LD documents. + +The purpose of compaction is to apply the [term definitions](#dfn-term-definition), [vocabulary mapping](#dfn-vocabulary-mapping), [default language](#dfn-default-language), and [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) to an existing JSON-LD document to cause it to be represented in a form that is tailored to the use of the JSON-LD document directly as JSON. This includes representing values as [strings](https://infra.spec.whatwg.org/#javascript-string), rather than [value objects](#dfn-value-object), where possible, shortening the use of [list objects](#dfn-list-object) into simple [arrays](https://infra.spec.whatwg.org/#list), reversing the relationship between [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node), and using data maps to index into multiple values instead of representing them as an array of values. + +#### 5.2.1 Shortening IRIs[](#shortening-iris) + +*This section is non-normative.* + +In an expanded JSON-LD document, [IRIs](https://tools.ietf.org/html/rfc3987#section-2) are always represented as absolute [IRIs](https://tools.ietf.org/html/rfc3987#section-2). In many cases, it is preferable to use a shorter version, either a [relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5), [compact IRI](#dfn-compact-iri), or [term](#dfn-term). Compaction uses a combination of elements in a context to create a shorter form of these IRIs. See [§ 4.1.2 Default Vocabulary](#default-vocabulary), [§ 4.1.3 Base IRI](#base-iri), and [§ 4.1.5 Compact IRIs](#compact-iris) for more details. + +The [vocabulary mapping](#dfn-vocabulary-mapping) can be used to shorten IRIs that may be *vocabulary relative* by removing the IRI prefix that matches the [vocabulary mapping](#dfn-vocabulary-mapping). This is done whenever an IRI is determined to be vocabulary relative, i.e., used as a [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property), or a value of `@type`, or as the value of a [term](#dfn-term) described as `"@type": "@vocab"`. + +[Example 128](#example-128-compacting-using-a-default-vocabulary): Compacting using a default vocabulary + +Given the following expanded document: + +``` {#compacting-default-expanded .expanded .input aria-busy="false"} +[{ + "@id": "http://example.org/places#BrewEats", + "@type": ["http://example.org/Restaurant"], + "http://example.org/name": [{"@value": "Brew Eats"}] +}] +``` + +And the following context: + +``` {#compacting-default-context .context .nohighlight context-for="Compacting using a default vocabulary-expanded"} +{ + "@context": { + "@vocab": "http://example.org/" + } +} +``` + +The compaction algorithm will shorten all vocabulary-relative IRIs that begin with `http://xmlns.com/foaf/0.1/`: + +``` {.compacted .result .nohighlight result-for="Compacting using a default vocabulary-expanded" context="Compacting using a default vocabulary-context" data-compact=""} +{ + "@context": { + "@vocab": "http://example.org/" + }, + "@id": "http://example.org/places#BrewEats", + "@type": "Restaurant", + "name": "Brew Eats" +} +``` + +Note that two IRIs were shortened, unnecessary arrays are removed, and simple string values are replaced with the string. + +See [Security Considerations](#iana-security) in [§ C. IANA Considerations](#iana-considerations) for a discussion on how string vocabulary-relative IRI resolution via concatenation. + +[Example 129](#example-129-compacting-using-a-base-iri): Compacting using a base IRI + +Given the following expanded document: + +``` {.expanded .input aria-busy="false"} +[{ + "@id": "http://example.com/document.jsonld", + "http://www.w3.org/2000/01/rdf-schema#label": [{"@value": "Just a simple document"}] +}] +``` + +And the following context: + +``` {.context .nohighlight context-for="Compacting using a base IRI-expanded"} +{ + "@context": { + "@base": "http://example.com/", + "label": "http://www.w3.org/2000/01/rdf-schema#label" + } +} +``` + +The compaction algorithm will shorten all document-relative IRIs that begin with `http://example.com/`: + +``` {.compacted .result .nohighlight result-for="Compacting using a base IRI-expanded" context="Compacting using a base IRI-context" data-compact=""} +{ + "@context": { + "@base": "http://example.com/", + "label": "http://www.w3.org/2000/01/rdf-schema#label" + }, + "@id": "document.jsonld", + "label": "Just a simple document" +} +``` + +#### 5.2.2 Representing Values as Strings[](#representing-values-as-strings) + +*This section is non-normative.* + +To be unambiguous, the [expanded document form](#dfn-expanded-document-form) always represents [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node) and values using [node objects](#dfn-node-object) and [value objects](#dfn-value-object). Moreover, property values are always contained within an array, even when there is only one value. Sometimes this is useful to maintain a uniformity of access, but most JSON data use the simplest possible representation, meaning that [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property) have single values, which are represented as [strings](https://infra.spec.whatwg.org/#javascript-string) or as structured values such as [node objects](#dfn-node-object). By default, [compaction](https://www.w3.org/TR/json-ld11-api/#dfn-compact) will represent values which are simple strings as [strings](https://infra.spec.whatwg.org/#javascript-string), but sometimes a value is an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a date, or some other [typed value](#dfn-typed-value) for which a simple string representation would loose information. By specifying this within a [term definition](#dfn-term-definition), the semantics of a string value can be inferred from the definition of the [term](#dfn-term) used as a [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property). See [§ 4.2 Describing Values](#describing-values) for more details. + +[Example 130](#example-130-coercing-values-to-strings): Coercing Values to Strings + +Given the following expanded document: + +``` {.expanded .input aria-busy="false"} +[{ + "http://example.com/plain": [ + {"@value": "string"}, + {"@value": true}, + {"@value": 1} + ], + "http://example.com/date": [ + { + "@value": "2018-02-16", + "@type": "http://www.w3.org/2001/XMLSchema#date" + } + ], + "http://example.com/en": [ + {"@value": "English", "@language": "en"} + ], + "http://example.com/iri": [ + {"@id": "http://example.com/some-location"} + ] +}] +``` + +And the following context: + +``` {.context context-for="Coercing Values to Strings-expanded" aria-busy="false"} +{ + "@context": { + "@vocab": "http://example.com/", + "date": {"@type": "http://www.w3.org/2001/XMLSchema#date"}, + "en": {"@language": "en"}, + "iri": {"@type": "@id"} + } +} +``` + +The compacted version will use string values for the defined terms when the values match the [term definition](#dfn-term-definition). Note that there is no term defined for \"plain\", that is created automatically using the [vocabulary mapping](#dfn-vocabulary-mapping). Also, the other native values, `1` and `true`, can be represented without defining a specific type mapping. + +``` {.compacted result-for="Coercing Values to Strings-expanded" context="Coercing Values to Strings-context" data-compact="" aria-busy="false"} +{ + "@context": { + "@vocab": "http://example.com/", + "date": {"@type": "http://www.w3.org/2001/XMLSchema#date"}, + "en": {"@language": "en"}, + "iri": {"@type": "@id"} + }, + "plain": ["string", true, 1], + "date": "2018-02-16", + "en": "English", + "iri": "http://example.com/some-location" +} +``` + +#### 5.2.3 Representing Lists as Arrays[](#representing-lists-as-arrays) + +*This section is non-normative.* + +As described in [§ 4.3.1 Lists](#lists), JSON-LD has an expanded syntax for representing ordered values, using the `@list` keyword. To simplify the representation in JSON-LD, a term can be defined with `"@container": "@list"` which causes all values of a property using such a term to be considered ordered. + +[Example 131](#example-131-using-arrays-for-lists): Using Arrays for Lists + +Given the following expanded document: + +``` {.expanded .input aria-busy="false"} +[{ + "http://xmlns.com/foaf/0.1/nick": [{ + "@list": [ + {"@value": "joe"}, + {"@value": "bob"}, + {"@value": "jaybee"} + ] + }] +}] +``` + +And the following context: + +``` {.context .nohighlight context-for="Using Arrays for Lists-expanded"} +{ + "@context": { + "nick": { + "@id": "http://xmlns.com/foaf/0.1/nick", + "@container": "@list" + } + } +} +``` + +The compacted version eliminates the explicit [list object](#dfn-list-object). + +``` {.compacted result-for="Using Arrays for Lists-expanded" context="Using Arrays for Lists-context" data-compact="" aria-busy="false"} +{ + "@context": { + "nick": { + "@id": "http://xmlns.com/foaf/0.1/nick", + "@container": "@list" + } + }, + "nick": [ "joe", "bob", "jaybee" ] +} +``` + +#### 5.2.4 Reversing Node Relationships[](#reversing-node-relationships) + +*This section is non-normative.* + +In some cases, the property used to relate two nodes may be better expressed if the nodes have a reverse direction, for example, when describing a relationship between two people and a common parent. See [§ 4.8 Reverse Properties](#reverse-properties) for more details. + +[Example 132](#example-132-reversing-node-relationships): Reversing Node Relationships + +Given the following expanded document: + +``` {.expanded .input aria-busy="false"} +[{ + "@id": "http://example.org/#homer", + "http://example.com/vocab#name": [{"@value": "Homer"}], + "@reverse": { + "http://example.com/vocab#parent": [{ + "@id": "http://example.org/#bart", + "http://example.com/vocab#name": [{"@value": "Bart"}] + }, { + "@id": "http://example.org/#lisa", + "http://example.com/vocab#name": [{"@value": "Lisa"}] + }] + } +}] +``` + +And the following context: + +``` {.context context-for="Reversing Node Relationships-expanded" aria-busy="false"} +{ + "@context": { + "name": "http://example.com/vocab#name", + "children": { "@reverse": "http://example.com/vocab#parent" } + } +} +``` + +The compacted version eliminates the `@reverse` property by describing \"children\" as the reverse of \"parent\". + +``` {.compacted result-for="Reversing Node Relationships-expanded" context="Reversing Node Relationships-context" base="http://example.org/" data-compact="" aria-busy="false"} +{ + "@context": { + "name": "http://example.com/vocab#name", + "children": { "@reverse": "http://example.com/vocab#parent" } + }, + "@id": "#homer", + "name": "Homer", + "children": [ + { "@id": "#bart", "name": "Bart"}, + { "@id": "#lisa", "name": "Lisa"} + ] +} +``` + +Reverse properties can be even more useful when combined with [framing](https://www.w3.org/TR/json-ld11-framing/#dfn-framing), which can actually make [node objects](#dfn-node-object) defined at the top-level of a document to become embedded nodes. JSON-LD provides a means to index such values, by defining an appropriate \@container definition within a term definition. + +#### 5.2.5 Indexing Values[](#indexing-values) + +*This section is non-normative.* + +Properties with multiple values are typically represented using an unordered [array](https://infra.spec.whatwg.org/#list). This means that an application working on an internalized representation of that JSON would need to iterate through the values of the array to find a value matching a particular pattern, such as a [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) using the language `en`. + +[Example 133](#example-133-indexing-language-tagged-strings): Indexing language-tagged strings + +Given the following expanded document: + +``` {.expanded .input aria-busy="false"} +[{ + "@id": "http://example.com/queen", + "http://example.com/vocab/label": [ + {"@value": "The Queen", "@language": "en"}, + {"@value": "Die Königin", "@language": "de"}, + {"@value": "Ihre Majestät", "@language": "de"} + ] +}] +``` + +And the following context: + +``` {.context context-for="Indexing language-tagged strings-expanded" aria-busy="false"} +{ + "@context": { + "vocab": "http://example.com/vocab/", + "label": { + "@id": "vocab:label", + "@container": "@language" + } + } +} +``` + +The compacted version uses a [map](https://infra.spec.whatwg.org/#ordered-map) value for \"label\", with the keys representing the [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) and the values are the [strings](https://infra.spec.whatwg.org/#javascript-string) associated with the relevant [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag). + +``` {.compacted result-for="Indexing language-tagged strings-expanded" context="Indexing language-tagged strings-context" base="http://example.org/" data-compact="" aria-busy="false"} +{ + "@context": { + "vocab": "http://example.com/vocab/", + "label": { + "@id": "vocab:label", + "@container": "@language" + } + }, + "@id": "http://example.com/queen", + "label": { + "en": "The Queen", + "de": [ "Die Königin", "Ihre Majestät" ] + } +} +``` + +Data can be indexed on a number of different keys, including \@id, \@type, \@language, \@index and more. See [§ 4.6 Indexed Values](#indexed-values) and [§ 4.9 Named Graphs](#named-graphs) for more details. + +#### 5.2.6 Normalizing Values as Objects[](#normalizing-values-as-objects) + +*This section is non-normative.* + +Sometimes it\'s useful to compact a document, but keep the node object and value object representations. For this, a term definition can set `"@type": "@none"`. This causes the [Value Compaction](https://www.w3.org/TR/json-ld11-api/#value-compaction) algorithm to always use the object form of values, although components of that value may be compacted. + +[Example 134](#example-134-forcing-object-values): Forcing Object Values + +Given the following expanded document: + +``` {.expanded .input aria-busy="false"} +[{ + "http://example.com/notype": [ + {"@value": "string"}, + {"@value": true}, + {"@value": false}, + {"@value": 1}, + {"@value": 10.0}, + {"@value": "plain"}, + {"@value": "false", "@type": "http://www.w3.org/2001/XMLSchema#boolean"}, + {"@value": "english", "@language": "en"}, + {"@value": "2018-02-17", "@type": "http://www.w3.org/2001/XMLSchema#date"}, + {"@id": "http://example.com/iri"} + ] +}] +``` + +And the following context: + +``` {.context context-for="Forcing Object Values-expanded" aria-busy="false"} +{ + "@context": { + "@version": 1.1, + "xsd": "http://www.w3.org/2001/XMLSchema#", + "notype": {"@id": "http://example.com/notype", "@type": "@none"} + } +} +``` + +The compacted version will use string values for the defined terms when the values match the [term definition](#dfn-term-definition). Also, the other native values, `1` and `true`, can be represented without defining a specific type mapping. + +``` {.compacted result-for="Forcing Object Values-expanded" context="Forcing Object Values-context" data-compact="" aria-busy="false"} +{ + "@context": { + "@version": 1.1, + "xsd": "http://www.w3.org/2001/XMLSchema#", + "notype": {"@id": "http://example.com/notype", "@type": "@none"} + }, + "notype": [ + {"@value": "string"}, + {"@value": true}, + {"@value": false}, + {"@value": 1}, + {"@value": 10.0}, + {"@value": "plain"}, + {"@value": "false", "@type": "xsd:boolean"}, + {"@value": "english", "@language": "en"}, + {"@value": "2018-02-17", "@type": "xsd:date"}, + {"@id": "http://example.com/iri"} + ] +} +``` + +#### 5.2.7 Representing Singular Values as Arrays[](#representing-singular-values-as-arrays) + +*This section is non-normative.* + +Generally, when compacting, properties having only one value are represented as strings or [maps](https://infra.spec.whatwg.org/#ordered-map), while properties having multiple values are represented as an array of strings or [maps](https://infra.spec.whatwg.org/#ordered-map). This means that applications accessing such properties need to be prepared to accept either representation. To force all values to be represented using an array, a term definition can set `"@container": "@set"`. Moreover, `@set` can be used in combination with other container settings, for example looking at our language-map example from [§ 5.2.5 Indexing Values](#indexing-values): + +[Example 135](#example-135-indexing-language-tagged-strings-and-set): Indexing language-tagged strings and \@set + +Given the following expanded document: + +``` {.expanded .input aria-busy="false"} +[{ + "@id": "http://example.com/queen", + "http://example.com/vocab/label": [ + {"@value": "The Queen", "@language": "en"}, + {"@value": "Die Königin", "@language": "de"}, + {"@value": "Ihre Majestät", "@language": "de"} + ] +}] +``` + +And the following context: + +``` {.context context-for="Indexing language-tagged strings and @set-expanded" aria-busy="false"} +{ + "@context": { + "@version": 1.1, + "@vocab": "http://example.com/vocab/", + "label": { + "@container": ["@language", "@set"] + } + } +} +``` + +The compacted version uses a [map](https://infra.spec.whatwg.org/#ordered-map) value for \"label\" as before, and the values are the relevant [strings](https://infra.spec.whatwg.org/#javascript-string) but always represented using an [array](https://infra.spec.whatwg.org/#list). + +``` {.compacted .result result-for="Indexing language-tagged strings and @set-expanded" context="Indexing language-tagged strings and @set-context" base="http://example.org/" data-compact="" aria-busy="false"} +{ + "@context": { + "@version": 1.1, + "@vocab": "http://example.com/vocab/", + "label": { + "@container": ["@language", "@set"] + } + }, + "@id": "http://example.com/queen", + "label": { + "en": ["The Queen"], + "de": [ "Die Königin", "Ihre Majestät" ] + } +} +``` + +#### 5.2.8 Term Selection[](#term-selection) + +*This section is non-normative.* + +When compacting, the [Compaction algorithm](https://www.w3.org/TR/json-ld11-api/#compaction-algorithm) will compact using a term for a property only when the values of that property match the `@container`, `@type`, and `@language` specifications for that [term definition](#dfn-term-definition). This can actually split values between different properties, all of which have the same [IRI](https://tools.ietf.org/html/rfc3987#section-2). In case there is no matching [term definition](#dfn-term-definition), the compaction algorithm will compact using the absolute [IRI](https://tools.ietf.org/html/rfc3987#section-2) of the property. + +[Example 136](#example-136-term-selection): Term Selection + +Given the following expanded document: + +``` {.expanded .input aria-busy="false"} +[{ + "http://example.com/vocab/property": [ + {"@value": "string"}, + {"@value": true}, + {"@value": 1}, + {"@value": "false", "@type": "http://www.w3.org/2001/XMLSchema#boolean"}, + {"@value": "10", "@type": "http://www.w3.org/2001/XMLSchema#integer"}, + {"@value": "english", "@language": "en"}, + {"@value": "2018-02-17", "@type": "http://www.w3.org/2001/XMLSchema#date"}, + {"@id": "http://example.com/some-location"} + ] +}] +``` + +And the following context: + +``` {.context context-for="Term Selection-expanded" aria-busy="false"} +{ + "@context": { + "vocab": "http://example.com/vocab/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "integer": {"@id": "vocab:property", "@type": "xsd:integer"}, + "date": {"@id": "vocab:property", "@type": "xsd:date"}, + "english": {"@id": "vocab:property", "@language": "en"}, + "list": {"@id": "vocab:property", "@container": "@list"}, + "iri": {"@id": "vocab:property", "@type": "@id"} + } +} +``` + +Note that the values that match the \"integer\", \"english\", \"date\", and \"iri\" terms are properly matched, and that everything that does not explicitly match is added to a property created using a [compact IRI](#dfn-compact-iri). + +``` {.compacted .result result-for="Term Selection-expanded" context="Term Selection-context" base="http://example.org/" data-compact="" aria-busy="false"} +{ + "@context": { + "vocab": "http://example.com/vocab/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "integer": {"@id": "vocab:property", "@type": "xsd:integer"}, + "date": {"@id": "vocab:property", "@type": "xsd:date"}, + "english": {"@id": "vocab:property", "@language": "en"}, + "list": {"@id": "vocab:property", "@container": "@list"}, + "iri": {"@id": "vocab:property", "@type": "@id"} + }, + "vocab:property": [ + "string", true, 1, + {"@value": "false", "@type": "xsd:boolean"} + ], + "integer": "10", + "english": "english", + "date": "2018-02-17", + "iri": "http://example.com/some-location" +} +``` + +### 5.3 Flattened Document Form[](#flattened-document-form) + +*This section is non-normative.* + +The JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\] defines a method for *flattening* a JSON-LD document. [Flattening](https://www.w3.org/TR/json-ld11-api/#dfn-flattened) collects all properties of a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) in a single [map](https://infra.spec.whatwg.org/#ordered-map) and labels all [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) with [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier). This ensures a shape of the data and consequently may drastically simplify the code required to process JSON-LD in certain applications. + +For example, assume the following JSON-LD input document: + +[Example 137](#sample-expanded-json-ld-document-to-be-flattened): Sample JSON-LD document to be flattened + +``` {.input aria-busy="false"} +{ + "@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": [ + { + "@id": "http://manu.sporny.org/about#manu", + "name": "Manu Sporny" + }, { + "name": "Dave Longley" + } + ] +} +``` + +Running the JSON-LD [Flattening algorithm](https://www.w3.org/TR/json-ld11-api/#flattening-algorithm) against the JSON-LD input document in the example above and using the same context would result in the following output: + +[Example 138](#example-138-flattened-and-compacted-form-for-the-previous-example): Flattened and compacted form for the previous example + +[Open in playground](https://json-ld.org/playground/#startTab=tab-flattened&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fname%22%2C%0A%20%20%20%20%22knows%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fknows%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fme.markus-lanthaler.com%2F%22%2C%0A%20%20%22name%22%3A%20%22Markus%20Lanthaler%22%2C%0A%20%20%22knows%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%0A%20%20%20%20%7D%2C%20%7B%0A%20%20%20%20%20%20%22name%22%3A%20%22Dave%20Longley%22%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D&context=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22name%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fname%22%2C%0A%20%20%20%20%22knows%22%3A%20%22http%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2Fknows%22%0A%20%20%7D%2C%0A%20%20%22%40id%22%3A%20%22http%3A%2F%2Fme.markus-lanthaler.com%2F%22%2C%0A%20%20%22name%22%3A%20%22Markus%20Lanthaler%22%2C%0A%20%20%22knows%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fmanu.sporny.org%2Fabout%23manu%22%2C%0A%20%20%20%20%20%20%22name%22%3A%20%22Manu%20Sporny%22%0A%20%20%20%20%7D%2C%20%7B%0A%20%20%20%20%20%20%22name%22%3A%20%22Dave%20Longley%22%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D) + +``` {.selected .original flatten="" context="Sample JSON-LD document to be flattened" result-for="Sample JSON-LD document to be flattened" aria-busy="false"} +{ + "@context": { + "name": "http://xmlns.com/foaf/0.1/name", + "knows": "http://xmlns.com/foaf/0.1/knows" + }, + "@graph": [{ + "@id": "http://me.markus-lanthaler.com/", + "name": "Markus Lanthaler", + "knows": [ + { "@id": "http://manu.sporny.org/about#manu" }, + { "@id": "_:b0" } + ] + }, { + "@id": "http://manu.sporny.org/about#manu", + "name": "Manu Sporny" + }, { + "@id": "_:b0", + "name": "Dave Longley" + }] +} +``` + +[JSON-LD\'s media type](#application-ld-json) defines a `profile` parameter which can be used to signal or request flattened document form. The profile URI identifying [flattened document form](#dfn-flattened-document-form) is `http://www.w3.org/ns/json-ld#flattened`. It can be combined with the profile URI identifying [expanded document form](#dfn-expanded-document-form) or [compacted document form](#dfn-compacted-document-form). + +### 5.4 Framed Document Form[](#framed-document-form) + +*This section is non-normative.* + +The JSON-LD 1.1 Framing specification \[[JSON-LD11-FRAMING](#bib-json-ld11-framing "JSON-LD 1.1 Framing")\] defines a method for *framing* a JSON-LD document. [Framing](https://www.w3.org/TR/json-ld11-framing/#dfn-framing) is used to shape the data in a JSON-LD document, using an example [frame](https://www.w3.org/TR/json-ld11-framing/#dfn-frame) document which is used to both match the [flattened](https://www.w3.org/TR/json-ld11-api/#dfn-flattened) data and show an example of how the resulting data should be shaped. + +For example, assume the following JSON-LD frame: + +[Example 139](#sample-library-frame): Sample library frame + +``` {.frame aria-busy="false"} +{ + "@context": { + "@version": 1.1, + "@vocab": "http://example.org/" + }, + "@type": "Library", + "contains": { + "@type": "Book", + "contains": { + "@type": "Chapter" + } + } +} +``` + +This [frame](https://www.w3.org/TR/json-ld11-framing/#dfn-frame) document describes an embedding structure that would place objects with type *Library* at the top, with objects of type *Book* that were linked to the library object using the *contains* property embedded as property values. It also places objects of type *Chapter* within the referencing *Book* object as embedded values of the *Book* object. + +When using a flattened set of objects that match the frame components: + +[Example 140](#sample-flattened-library-objects): Flattened library objects + +``` {.input aria-busy="false"} +{ + "@context": { + "@vocab": "http://example.org/", + "contains": {"@type": "@id"} + }, + "@graph": [{ + "@id": "http://example.org/library", + "@type": "Library", + "contains": "http://example.org/library/the-republic" + }, { + "@id": "http://example.org/library/the-republic", + "@type": "Book", + "creator": "Plato", + "title": "The Republic", + "contains": "http://example.org/library/the-republic#introduction" + }, { + "@id": "http://example.org/library/the-republic#introduction", + "@type": "Chapter", + "description": "An introductory chapter on The Republic.", + "title": "The Introduction" + }] +} +``` + +The Frame Algorithm can create a new document which follows the structure of the frame: + +[Example 141](#example-141-framed-library-objects): Framed library objects + +[Open in playground](https://json-ld.org/playground/#startTab=tab-framed&json-ld=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fexample.org%2F%22%2C%0A%20%20%20%20%22contains%22%3A%20%7B%22%40type%22%3A%20%22%40id%22%7D%0A%20%20%7D%2C%0A%20%20%22%40graph%22%3A%20%5B%7B%0A%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Flibrary%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Library%22%2C%0A%20%20%20%20%22contains%22%3A%20%22http%3A%2F%2Fexample.org%2Flibrary%2Fthe-republic%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Flibrary%2Fthe-republic%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Book%22%2C%0A%20%20%20%20%22creator%22%3A%20%22Plato%22%2C%0A%20%20%20%20%22title%22%3A%20%22The%20Republic%22%2C%0A%20%20%20%20%22contains%22%3A%20%22http%3A%2F%2Fexample.org%2Flibrary%2Fthe-republic%23introduction%22%0A%20%20%7D%2C%20%7B%0A%20%20%20%20%22%40id%22%3A%20%22http%3A%2F%2Fexample.org%2Flibrary%2Fthe-republic%23introduction%22%2C%0A%20%20%20%20%22%40type%22%3A%20%22Chapter%22%2C%0A%20%20%20%20%22description%22%3A%20%22An%20introductory%20chapter%20on%20The%20Republic.%22%2C%0A%20%20%20%20%22title%22%3A%20%22The%20Introduction%22%0A%20%20%7D%5D%0A%7D&context=%7B%7D&frame=%7B%0A%20%20%22%40context%22%3A%20%7B%0A%20%20%20%20%22%40version%22%3A%201.1%2C%0A%20%20%20%20%22%40vocab%22%3A%20%22http%3A%2F%2Fexample.org%2F%22%0A%20%20%7D%2C%0A%20%20%22%40type%22%3A%20%22Library%22%2C%0A%20%20%22contains%22%3A%20%7B%0A%20%20%20%20%22%40type%22%3A%20%22Book%22%2C%0A%20%20%20%20%22contains%22%3A%20%7B%0A%20%20%20%20%20%20%22%40type%22%3A%20%22Chapter%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) + +``` {.selected .original .nohighlight title="Framed library objects" data-frame="Sample library frame" result-for="Flattened library objects"} +{ + "@context": { + "@version": 1.1, + "@vocab": "http://example.org/" + }, + "@id": "http://example.org/library", + "@type": "Library", + "contains": { + "@id": "http://example.org/library/the-republic", + "@type": "Book", + "contains": { + "@id": "http://example.org/library/the-republic#introduction", + "@type": "Chapter", + "description": "An introductory chapter on The Republic.", + "title": "The Introduction" + }, + "creator": "Plato", + "title": "The Republic" + } +} +``` + +[JSON-LD\'s media type](#application-ld-json) defines a `profile` parameter which can be used to signal or request framed document form. The profile URI identifying [framed document form](#dfn-framed-document-form) is `http://www.w3.org/ns/json-ld#framed`. + +[JSON-LD\'s media type](#application-ld-json) also defines a `profile` parameter which can be used to identify a [script element](https://html.spec.whatwg.org/multipage/scripting.html#the-script-element) in an HTML document containing a frame. The first [script element](https://html.spec.whatwg.org/multipage/scripting.html#the-script-element) of type `application/ld+json;profile=http://www.w3.org/ns/json-ld#frame` will be used to find a [frame](https://www.w3.org/TR/json-ld11-framing/#dfn-frame).. + +## 6. Modifying Behavior with Link Relationships[](#modifying-behavior-with-link-relationships) + +Certain aspects of JSON-LD processing can be modified using [HTTP Link Headers](https://tools.ietf.org/html/rfc8288#section-3) \[[RFC8288](#bib-rfc8288 "Web Linking")\]. These can be used when retrieving resources that are not, themselves, JSON-LD, but can be interpreted as JSON-LD by using information in a [Link Relation](https://en.wikipedia.org/wiki/Link_relation). + +When processing normal JSON documents, a link relation can be specified using the [HTTP Link Header](https://tools.ietf.org/html/rfc8288#section-3) returned when fetching a remote document, as described in [§ 6.1 Interpreting JSON as JSON-LD](#interpreting-json-as-json-ld). + +In other cases, a resource may be returned using a representation that cannot easily be interpreted as JSON-LD. Normally, [HTTP content negotiation](https://en.wikipedia.org/wiki/Content_negotiation) would be used to allow a client to specify a preference for JSON-LD over another representation, but in certain situations, it is not possible or practical for a server to respond appropriately to such requests. For this, an [HTTP Link Header](https://tools.ietf.org/html/rfc8288#section-3) can be used to provide an alternate location for a document to be used in place of the originally requested resource, as described in [§ 6.2 Alternate Document Location](#alternate-document-location). + +### 6.1 Interpreting JSON as JSON-LD[](#interpreting-json-as-json-ld) + +Ordinary JSON documents can be interpreted as JSON-LD by providing an explicit JSON-LD [context](#dfn-context) document. One way to provide this is by using referencing a JSON-LD [context](#dfn-context) document in an [HTTP Link Header](https://tools.ietf.org/html/rfc8288#section-3). Doing so allows JSON to be unambiguously machine-readable without requiring developers to drastically change their documents and provides an upgrade path for existing infrastructure without breaking existing clients that rely on the `application/json` media type or a media type with a `+json` suffix as defined in \[[RFC6839](#bib-rfc6839 "Additional Media Type Structured Syntax Suffixes")\]. + +In order to use an external context with an ordinary JSON document, when retrieving an ordinary JSON document via HTTP, processors *MUST* attempt to retrieve any [JSON-LD document](#dfn-json-ld-document) referenced by a [Link Header](https://tools.ietf.org/html/rfc8288#section-3) with: + +- `rel="http://www.w3.org/ns/json-ld#context"`, and +- `type="application/ld+json"`. + +The referenced document *MUST* have a top-level [JSON object](https://tools.ietf.org/html/rfc8259#section-4). The `@context` [entry](https://infra.spec.whatwg.org/#map-entry) within that object is added to the top-level [JSON object](https://tools.ietf.org/html/rfc8259#section-4) of the referencing document. If an [array](https://infra.spec.whatwg.org/#list) is at the top-level of the referencing document and its items are [JSON objects](https://tools.ietf.org/html/rfc8259#section-4), the `@context` subtree is added to all [array](https://infra.spec.whatwg.org/#list) items. All extra information located outside of the `@context` subtree in the referenced document *MUST* be discarded. Effectively this means that the [active context](#dfn-active-context) is initialized with the referenced external [context](#dfn-context). A response *MUST NOT* contain more than one [HTTP Link Header](https://tools.ietf.org/html/rfc8288#section-3) using the `http://www.w3.org/ns/json-ld#context` link relation. + +Other mechanisms for providing a JSON-LD Context *MAY* be described for other URI schemes. + +The JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\] provides for an [expandContext](https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-expandcontext) option for specifying a [context](#dfn-context) to use when expanding JSON documents programmatically. + +The following example demonstrates the use of an external context with an ordinary JSON document over HTTP: + +[Example 142](#example-142-referencing-a-json-ld-context-from-a-json-document-via-an-http-link-header): Referencing a JSON-LD context from a JSON document via an HTTP Link Header + +``` {.nohighlight content-type="http" ignore=""} +GET /ordinary-json-document.json HTTP/1.1 +Host: example.com +Accept: application/ld+json,application/json,*/*;q=0.1 + +==================================== + +HTTP/1.1 200 OK +... +Content-Type: application/json +Link: ; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json" + +{ + "name": "Markus Lanthaler", + "homepage": "http://www.markus-lanthaler.com/", + "image": "http://twitter.com/account/profile_image/markuslanthaler" +} +``` + +Please note that [JSON-LD documents](#dfn-json-ld-document) served with the `application/ld+json` media type *MUST* have all context information, including references to external contexts, within the body of the document. Contexts linked via a `http://www.w3.org/ns/json-ld#context` [HTTP Link Header](https://tools.ietf.org/html/rfc8288#section-3) *MUST* be ignored for such documents. + +### 6.2 Alternate Document Location[](#alternate-document-location) + +Documents which can\'t be directly interpreted as JSON-LD can provide an alternate location containing JSON-LD. One way to provide this is by referencing a JSON-LD document in an [HTTP Link Header](https://tools.ietf.org/html/rfc8288#section-3). This might be useful, for example, when the URL associated with a namespace naturally contains an HTML document, but the JSON-LD context associated with that URL is located elsewhere. + +To specify an alternate location, a non-JSON resource (i.e., one using a media type other than `application/json` or a derivative) can return the alternate location using a [Link Header](https://tools.ietf.org/html/rfc8288#section-3) with: + +- `rel="alternate"`, and +- `type="application/ld+json"`. + +A response *MUST NOT* contain more than one [HTTP Link Header](https://tools.ietf.org/html/rfc8288#section-3) using the `alternate` link relation with `type="application/ld+json"` . + +Other mechanisms for providing an alternate location *MAY* be described for other URI schemes. + +The following example demonstrates the use of an alternate location with an ordinary HTTP document over HTTP: + +[Example 143](#example-143-specifying-an-alternate-location-via-an-http-link-header): Specifying an alternate location via an HTTP Link Header + +``` {.nohighlight content-type="http" ignore=""} +GET /index.html HTTP/1.1 +Host: example.com +Accept: application/ld+json,application/json,*/*;q=0.1 + +==================================== + +HTTP/1.1 200 OK +... +Content-Type: text/html +Link: ; rel="alternate"; type="application/ld+json" + + + + Primary Entrypoint + + +

This is the primary entrypoint for a vocabulary

+ + +``` + +A processor seeing a non-JSON result will note the presence of the link header and load that document instead. + +## 7. Embedding JSON-LD in HTML Documents[](#embedding-json-ld-in-html-documents) + +Note + +This section describes features available with a [documentLoader](https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-documentloader) supporting [HTML script extraction](https://www.w3.org/TR/json-ld11-api/#extract-script-content). See [Remote Document and Context Retrieval](https://www.w3.org/TR/json-ld11-api/#remote-document-and-context-retrieval) for more information. + +JSON-LD content can be easily embedded in HTML \[[HTML](#bib-html "HTML Standard")\] by placing it in a [script element](https://html.spec.whatwg.org/multipage/scripting.html#the-script-element) with the `type` attribute set to `application/ld+json`. Doing so creates a [data block](https://html.spec.whatwg.org/multipage/scripting.html#data-block). + +[Example 144](#example-144-embedding-json-ld-in-html): Embedding JSON-LD in HTML + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +``` {.compacted .input .selected .nohighlight content-type="text/html"} + +``` + +``` {.expanded .result result-for="Embedding JSON-LD in HTML-compacted" aria-busy="false"} +[{ + "@id": "http://dbpedia.org/resource/John_Lennon", + "http://xmlns.com/foaf/0.1/name": [{"@value": "John Lennon"}], + "http://schema.org/birthDate": [ + {"@value": "1940-10-09", "@type": "http://www.w3.org/2001/XMLSchema#date"} + ], + "http://schema.org/spouse": [ + {"@id": "http://dbpedia.org/resource/Cynthia_Lennon"} + ] +}] +``` + + Subject Property Value Value Type + ----------------------------------------- ------------------ -------------------------------------------- ------------ + http://dbpedia.org/resource/John_Lennon foaf:name John Lennon   + http://dbpedia.org/resource/John_Lennon schema:birthDate 1940-10-09 xsd:date + http://dbpedia.org/resource/John_Lennon schema:spouse http://dbpedia.org/resource/Cynthia_Lennon   + +``` {.turtle content-type="text/turtle" result-for="Embedding JSON-LD in HTML-expanded" to-rdf="" aria-busy="false"} +@prefix foaf: . +@prefix schema: . +@prefix xsd: . + + foaf:name "John Lennon"; + schema:birthDate "1940-10-09"^^xsd:date; + schema:spouse . +``` + +Defining how such data may be used is beyond the scope of this specification. The embedded JSON-LD document might be extracted as is or, e.g., be interpreted as RDF. + +If JSON-LD content is extracted as RDF \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\], it *MUST* be expanded into an [RDF Dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) using the [Deserialize JSON-LD to RDF Algorithm](https://www.w3.org/TR/json-ld11-api/#deserialize-json-ld-to-rdf-algorithm) \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\]. Unless a specific script is targeted (see [§ 7.3 Locating a Specific JSON-LD Script Element](#locating-a-specific-json-ld-script-element)), all [script elements](https://html.spec.whatwg.org/multipage/scripting.html#the-script-element) with `type` `application/ld+json` *MUST* be processed and merged into a single [dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) with equivalent [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) contained in separate script elements treated as if they were in a single document (i.e., blank nodes are shared between different JSON-LD script elements). + +[Example 145](#example-145-combining-multiple-json-ld-script-elements-into-a-single-dataset): Combining multiple JSON-LD script elements into a single dataset + +HTML Embedded (Input) + +Statements + +Turtle (Result) + +``` {.compacted .input .selected content-type="text/html" aria-busy="false"} +

Data describing Dave

+ + +

Data describing Gregg

+ +``` + + Subject Property Value + -------------------------------------------- ------------- --------------- + https://digitalbazaar.com/author/dlongley/ rdf:type schema:Person + https://digitalbazaar.com/author/dlongley/ schema:name Dave Longley + https://greggkellogg.net/foaf#me rdf:type schema:Person + https://greggkellogg.net/foaf#me schema:name Gregg Kellogg + +``` {.turtle content-type="text/turtle" result-for="Combining multiple JSON-LD script elements into a single dataset-compacted" to-rdf="" aria-busy="false"} +@prefix schema: . + + a schema:Person; + schema:name "Dave Longley" . + + a schema:Person; + schema:name "Gregg Kellogg" . +``` + +### 7.1 Inheriting base IRI from HTML\'s `base` element[](#inheriting-base-iri-from-html-s-base-element) + +When processing a JSON-LD [script element](https://html.spec.whatwg.org/multipage/scripting.html#the-script-element), the [Document Base URL](https://html.spec.whatwg.org/multipage/urls-and-fetching.html#document-base-url) of the containing HTML document, as defined in \[[HTML](#bib-html "HTML Standard")\], is used to establish the default [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) of the enclosed JSON-LD content. + +[Example 146](#example-146-using-the-document-base-url-to-establish-the-default-base-iri): Using the document base URL to establish the default base IRI + +Compacted (Input) + +Expanded (Result) + +Statements + +Turtle + +``` {.compacted .input .selected content-type="text/html" aria-busy="false"} + + + + + + +``` + +``` {.expanded .result result-for="Using the document base URL to establish the default base IRI-compacted" aria-busy="false"} +[{ + "@id": "http://dbpedia.org/resource/John_Lennon", + "http://xmlns.com/foaf/0.1/name": [{"@value": "John Lennon"}], + "http://schema.org/birthDate": [ + {"@value": "1940-10-09", "@type": "http://www.w3.org/2001/XMLSchema#date"} + ], + "http://schema.org/spouse": [ + {"@id": "http://dbpedia.org/resource/Cynthia_Lennon"} + ] +}] +``` + + Subject Property Value Value Type + ----------------------------------------- ------------------ -------------------------------------------- ------------ + http://dbpedia.org/resource/John_Lennon foaf:name John Lennon   + http://dbpedia.org/resource/John_Lennon schema:birthDate 1940-10-09 xsd:date + http://dbpedia.org/resource/John_Lennon schema:spouse http://dbpedia.org/resource/Cynthia_Lennon   + +``` {.turtle content-type="text/turtle" result-for="Using the document base URL to establish the default base IRI-expanded" to-rdf="" aria-busy="false"} +@base . +@prefix foaf: . +@prefix schema: . +@prefix xsd: . + + foaf:name "John Lennon"; + schema:birthDate "1940-10-09"^^xsd:date; + schema:spouse . +``` + +HTML allows for [Dynamic changes to base URLs](https://html.spec.whatwg.org/multipage/urls-and-fetching.html#dynamic-changes-to-base-urls). This specification does not require any specific behavior, and to ensure that all systems process the [base IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-base-iri) equivalently, authors *SHOULD* either use [IRIs](https://tools.ietf.org/html/rfc3987#section-2), or explicitly as defined in [§ 4.1.3 Base IRI](#base-iri). Implementations (particularly those natively operating in the \[[DOM](#bib-dom "DOM Standard")\]) *MAY* take into consideration [Dynamic changes to base URLs](https://html.spec.whatwg.org/multipage/urls-and-fetching.html#dynamic-changes-to-base-urls). + +### 7.2 Restrictions for contents of JSON-LD `script` elements[](#restrictions-for-contents-of-json-ld-script-elements) + +*This section is non-normative.* + +Due to the HTML [Restrictions for contents of ` +``` + +``` {.expanded .result result-for="Embedding JSON-LD containing HTML in HTML-compacted" aria-busy="false"} +[{ + "@type": ["http://schema.org/WebPageElement"], + "http://schema.org/name": [{"@value": "Encoding Issues"}], + "http://schema.org/description": [ + {"@value": "Issues list such as unescaped </script> or -->"} + ] +}] +``` + +``` {.turtle content-type="text/turtle" result-for="Embedding JSON-LD containing HTML in HTML-expanded" to-rdf="" aria-busy="false"} +@prefix schema: . + +[ a schema:WebPageElement; + schema:name "Encoding Issues"; + schema:description "Issues list such as unescaped </script> or -->" +] . +``` + +### 7.3 Locating a Specific JSON-LD Script Element[](#locating-a-specific-json-ld-script-element) + +A specific [script element](https://html.spec.whatwg.org/multipage/scripting.html#the-script-element) within an HTML document may be located using a fragment identifier matching the [unique identifier](https://dom.spec.whatwg.org/#concept-id) of the script element within the HTML document located by a URL (see \[[DOM](#bib-dom "DOM Standard")\]). A [JSON-LD processor](https://www.w3.org/TR/json-ld11-api/#dfn-json-ld-processor) *MUST* extract only the specified data block\'s contents parsing it as a standalone [JSON-LD document](#dfn-json-ld-document) and *MUST NOT* merge the result with any other markup from the same HTML document. + +For example, given an HTML document located at `http://example.com/document`, a script element identified by \"dave\" can be targeted using the URL `http://example.com/document#dave`. + +[Example 148](#example-148-targeting-a-specific-script-element-by-id): Targeting a specific script element by id + +Compacted (Input) + +Statements + +Turtle + +Targeting a script element with id \"gregg\" + +``` {.compacted .input .selected .nohighlight content-type="text/html"} +

Data describing Dave

+ + +

Data describing Gregg

+ +``` + + Subject Property Value + ---------------------------------- ------------- --------------- + https://greggkellogg.net/foaf#me rdf:type schema:Person + https://greggkellogg.net/foaf#me schema:name Gregg Kellogg + +``` {.turtle content-type="text/turtle" result-for="Targeting a specific script element by id-compacted" to-rdf="" data-target="#gregg" aria-busy="false"} +@prefix schema: . + + a schema:Person; + schema:name "Gregg Kellogg" . +``` + +## 8. Data Model[](#data-model) + +JSON-LD is a serialization format for Linked Data based on JSON. It is therefore important to distinguish between the syntax, which is defined by JSON in \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\], and the data model which is an extension of the [RDF data model](https://www.w3.org/TR/rdf11-concepts/#data-model) \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\]. The precise details of how JSON-LD relates to the RDF data model are given in [§ 10. Relationship to RDF](#relationship-to-rdf). + +To ease understanding for developers unfamiliar with the RDF model, the following summary is provided: + +- A [JSON-LD document](#dfn-json-ld-document) serializes a [RDF Dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\], which is a collection of [graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) that comprises exactly one [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) and zero or more [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph). +- The [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) does not have a name and *MAY* be empty. +- Each [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) is a pair consisting of an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) (the [graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name)) and a [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). Whenever practical, the [graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name) *SHOULD* be an [IRI](https://tools.ietf.org/html/rfc3987#section-2). +- A [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) is a labeled directed graph, i.e., a set of [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node) connected by directed-arcs. +- Every directed-arc is labeled with an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier). Within the JSON-LD syntax these arc labels are called [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property). Whenever practical, a directed-arc *SHOULD* be labeled with an [IRI](https://tools.ietf.org/html/rfc3987#section-2). + Note + + The use of [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) to label properties is obsolete, and may be removed in a future version of JSON-LD. Consider using a document-relative IRI, instead, such as `#`. +- Every [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) is an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), or a [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal), although syntactically [lists](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab) and native JSON values may be represented directly. +- A [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) having an outgoing edge *MUST* be an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or a [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). +- A [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) *MUST NOT* contain unconnected [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node), i.e., nodes which are not connected by an [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) to any other [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node). + [Example 149](#example-149-illegal-unconnected-node): Illegal Unconnected Node + + ``` {ignore="" aria-busy="false"} + { + "@id": "http://example.org/1" + } + ``` + + Note + + This effectively just prohibits unnested, empty [node objects](#dfn-node-object) and unnested [node objects](#dfn-node-object) that contain only an `@id`. A document may have [nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-node) which are unrelated, as long as one or more properties are defined, or the [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) is referenced from another [node object](#dfn-node-object). +- An [IRI](https://tools.ietf.org/html/rfc3987#section-2) (Internationalized Resource Identifier) is a string that conforms to the syntax defined in \[[RFC3987](#bib-rfc3987 "Internationalized Resource Identifiers (IRIs)")\]. [IRIs](https://tools.ietf.org/html/rfc3987#section-2) used within a [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) *SHOULD* return a Linked Data document describing the resource denoted by that [IRI](https://tools.ietf.org/html/rfc3987#section-2) when being dereferenced. +- A [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) is a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) which is neither an [IRI](https://tools.ietf.org/html/rfc3987#section-2), nor a [JSON-LD value](#dfn-json-ld-value), nor a [list](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab). A blank node is identified using a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier). +- A [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) is a string that can be used as an identifier for a [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) within the scope of a [JSON-LD document](#dfn-json-ld-document). Blank node identifiers begin with `_:`. +- A [JSON-LD value](#dfn-json-ld-value) is a [typed value](#dfn-typed-value), a [string](https://infra.spec.whatwg.org/#javascript-string) (which is interpreted as a [typed value](#dfn-typed-value) with type `xsd:string`), a [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value) ([numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value) with a non-zero fractional part, i.e., the result of a modulo‑1 operation, or which are too large to represent as integers (see [Data Round Tripping](https://www.w3.org/TR/json-ld11-api/#data-round-tripping)) in \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\]), are interpreted as [typed values](#dfn-typed-value) with type `xsd:double`, all other [numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value) are interpreted as [typed values](#dfn-typed-value) with type `xsd:integer`), `true` or `false` (which are interpreted as [typed values](#dfn-typed-value) with type `xsd:boolean`), or a [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string). +- A [typed value](#dfn-typed-value) consists of a value, which is a string, and a type, which is an [IRI](https://tools.ietf.org/html/rfc3987#section-2). +- A [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) consists of a string and a non-empty [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) as defined by \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\]. The language tag *MUST* be well-formed according to section [2.2.9 Classes of Conformance](https://tools.ietf.org/html/bcp47#section-2.2.9) of \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\]. Processors *MAY* normalize [language tags](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) to lowercase. +- Either [strings](https://infra.spec.whatwg.org/#javascript-string), or [language-tagged strings](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) may include a [base direction](#dfn-base-direction), which represents an extension to the underlying [RDF data model](https://www.w3.org/TR/rdf11-concepts/#data-model). +- A [list](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab) is a sequence of zero or more [IRIs](https://tools.ietf.org/html/rfc3987#section-2), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), and [JSON-LD values](#dfn-json-ld-value). [Lists](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab) are interpreted as [RDF list structures](https://www.w3.org/TR/rdf11-mt/#rdf-collections) \[[RDF11-MT](#bib-rdf11-mt "RDF 1.1 Semantics")\]. + +[JSON-LD documents](#dfn-json-ld-document) *MAY* contain data that cannot be represented by the [data model](#dfn-data-model) defined above. Unless otherwise specified, such data is ignored when a [JSON-LD document](#dfn-json-ld-document) is being processed. One result of this rule is that properties which are not mapped to an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node), or [keyword](#dfn-keyword) will be ignored. + +Additionally, the JSON serialization format is internally represented using the [JSON-LD internal representation](https://www.w3.org/TR/json-ld11-api/#dfn-internal-representation), which uses the generic concepts of [lists](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab), [maps](https://infra.spec.whatwg.org/#ordered-map), [strings](https://infra.spec.whatwg.org/#javascript-string), [numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), [booleans](https://infra.spec.whatwg.org/#boolean), and [null](https://infra.spec.whatwg.org/#nulls) to describe the data represented by a JSON document. + +The image depicts a linked data dataset with a default graph and two named graphs. + +Figure 1 An illustration of a linked data dataset.\ +A [description of the linked data dataset diagram](#fig-linked-data-graph-descr) is available in the Appendix. Image available in [SVG](linked-data-graph.svg "SVG image of a linked data dataset") and [PNG](linked-data-graph.png "PNG image of a linked data dataset") formats. + +The dataset described in this figure can be represented as follows: + +[Example 150](#example-150-linked-data-dataset): Linked Data Dataset + +Compacted (Input) + +Expanded (Result) + +Statements + +TriG + +``` {.compacted .input .selected aria-busy="false"} +{ + "@context": [ + "http://schema.org/", + {"@base": "http://example.com/"} + ], + "@graph": [{ + "@id": "people/alice", + "gender": [ + {"@value": "weiblich", "@language": "de"}, + {"@value": "female", "@language": "en"} + ], + "knows": {"@id": "people/bob"}, + "name": "Alice" + }, { + "@id": "graphs/1", + "@graph": { + "@id": "people/alice", + "parent": { + "@id": "people/bob", + "name": "Bob" + } + } + }, { + "@id": "graphs/2", + "@graph": { + "@id": "people/bob", + "sibling": { + "name": "Mary", + "sibling": {"@id": "people/bob"} + } + } + }] +} +``` + +``` {.expanded .result result-for="Linked Data Dataset-compacted" aria-busy="false"} +[{ + "@id": "http://example.com/people/alice", + "http://schema.org/name": [{"@value": "Alice"}], + "http://schema.org/gender": [ + {"@value": "weiblich","@language": "de"}, + {"@value": "female","@language": "en"} + ], + "http://schema.org/knows": [ + {"@id": "http://example.com/people/bob"} + ] +}, { + "@id": "http://example.com/graphs/1", + "@graph": [{ + "@id": "http://example.com/people/alice", + "http://schema.org/parent": [{ + "@id": "http://example.com/people/bob", + "http://schema.org/name": [{"@value": "Bob"}] + }] + }] +}, { + "@id": "http://example.com/graphs/2", + "@graph": [{ + "@id": "http://example.com/people/bob", + "http://schema.org/sibling": [{ + "http://schema.org/name": [{"@value": "Mary"}], + "http://schema.org/sibling": [ + {"@id": "http://example.com/people/bob"} + ] + }] + }] +}] +``` + + Graph Subject Property Value Language + ----------------------------- --------------------------------- ---------------- ------------------------------- ---------- +   http://example.com/people/alice schema:name Alice +   http://example.com/people/alice schema:gender weiblich de +   http://example.com/people/alice schema:gender female en +   http://example.com/people/alice schema:knows http://example.com/people/bob + http://example.com/graphs/1 http://example.com/people/bob schema:name Bob + http://example.com/graphs/1 http://example.com/people/alice schema:parent http://example.com/people/bob + http://example.com/graphs/2 http://example.com/people/bob schema:sibling \_:b0 + http://example.com/graphs/2 \_:b0 schema:name Mary + http://example.com/graphs/2 \_:b0 schema:sibling http://example.com/people/bob + +``` {.trig content-type="application/trig" result-for="Linked Data Dataset-expanded" to-rdf="" aria-busy="false"} +@prefix schema: . + + schema:knows ; + schema:name "Alice"; + schema:gender "weiblich"@de, "female"@en . + + { + schema:parent . + schema:name "Bob" . +} + + { + schema:sibling [ + schema:name "Mary"; + schema:sibling + ] . +} +``` + +Note + +Note the use of `@graph` at the outer-most level to describe three top-level resources (two of them [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph)). The named graphs use `@graph` in addition to `@id` to provide the name for each graph. + +## 9. JSON-LD Grammar[](#json-ld-grammar) + +This section restates the syntactic conventions described in the previous sections more formally. + +A [JSON-LD document](#dfn-json-ld-document) *MUST* be valid [JSON text](https://tools.ietf.org/html/rfc8259#section-2) as described in \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\], or some format that can be represented in the [JSON-LD internal representation](https://www.w3.org/TR/json-ld11-api/#dfn-internal-representation) that is equivalent to valid [JSON text](https://tools.ietf.org/html/rfc8259#section-2). + +A [JSON-LD document](#dfn-json-ld-document) *MUST* be a single [node object](#dfn-node-object), a [map](https://infra.spec.whatwg.org/#ordered-map) consisting of only the [entries](https://infra.spec.whatwg.org/#map-entry) `@context` and/or `@graph`, or an [array](https://infra.spec.whatwg.org/#list) of zero or more [node objects](#dfn-node-object). + +In contrast to JSON, in JSON-LD the keys in [objects](https://tools.ietf.org/html/rfc8259#section-4) *MUST* be unique. + +Whenever a [keyword](#dfn-keyword) is discussed in this grammar, the statements also apply to an alias for that [keyword](#dfn-keyword). + +Note + +JSON-LD allows [keywords](#dfn-keyword) to be aliased (see [§ 4.1.6 Aliasing Keywords](#aliasing-keywords) for details). For example, if the [active context](#dfn-active-context) defines the [term](#dfn-term) `id` as an alias for `@id`, that alias may be legitimately used as a substitution for `@id`. Note that [keyword](#dfn-keyword) aliases are not expanded during context processing. + +### 9.1 Terms[](#terms) + +A [term](#dfn-term) is a short-hand [string](https://infra.spec.whatwg.org/#javascript-string) that expands to an [IRI](https://tools.ietf.org/html/rfc3987#section-2), [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier), or [keyword](#dfn-keyword). + +A [term](#dfn-term) *MUST NOT* equal any of the JSON-LD [keywords](#dfn-keyword), other than `@type`. + +When used as the [prefix](#dfn-prefix) in a [Compact IRI](#dfn-compact-iri), to avoid the potential ambiguity of a [prefix](#dfn-prefix) being confused with an IRI scheme, [terms](#dfn-term) *SHOULD NOT* come from the list of URI schemes as defined in \[[IANA-URI-SCHEMES](#bib-iana-uri-schemes "Uniform Resource Identifier (URI) Schemes")\]. Similarly, to avoid confusion between a [Compact IRI](#dfn-compact-iri) and a [term](#dfn-term), terms *SHOULD NOT* include a colon (`:`) and *SHOULD* be restricted to the form of [`isegment-nz-nc`](https://tools.ietf.org/html/rfc3987#section-2.2) as defined in \[[RFC3987](#bib-rfc3987 "Internationalized Resource Identifiers (IRIs)")\]. + +To avoid forward-compatibility issues, a [term](#dfn-term) *SHOULD NOT* start with an `@` character followed exclusively by one or more *ALPHA* characters (see \[[RFC5234](#bib-rfc5234 "Augmented BNF for Syntax Specifications: ABNF")\]) as future versions of JSON-LD may introduce additional [keywords](#dfn-keyword). Furthermore, the term *MUST NOT* be an empty [string](https://infra.spec.whatwg.org/#javascript-string) (`""`) as not all programming languages are able to handle empty JSON keys. + +See [§ 3.1 The Context](#the-context) and [§ 3.2 IRIs](#iris) for further discussion on mapping [terms](#dfn-term) to [IRIs](https://tools.ietf.org/html/rfc3987#section-2). + +### 9.2 Node Objects[](#node-objects) + +A [node object](#dfn-node-object) represents zero or more properties of a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) in the [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) serialized by the [JSON-LD document](#dfn-json-ld-document). A [map](https://infra.spec.whatwg.org/#ordered-map) is a [node object](#dfn-node-object) if it exists outside of a JSON-LD [context](#dfn-context) and: + +- it is not the top-most [map](https://infra.spec.whatwg.org/#ordered-map) in the JSON-LD document consisting of no other [entries](https://infra.spec.whatwg.org/#map-entry) than `@graph` and `@context`, +- it does not contain the `@value`, `@list`, or `@set` keywords, and +- it is not a [graph object](#dfn-graph-object). + +The [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property) of a [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node) in a [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) may be spread among different [node objects](#dfn-node-object) within a document. When that happens, the keys of the different [node objects](#dfn-node-object) need to be merged to create the properties of the resulting [node](https://www.w3.org/TR/rdf11-concepts/#dfn-node). + +A [node object](#dfn-node-object) *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map). All keys which are not [IRIs](https://tools.ietf.org/html/rfc3987#section-2), [compact IRIs](#dfn-compact-iri), [terms](#dfn-term) valid in the [active context](#dfn-active-context), or one of the following [keywords](#dfn-keyword) (or alias of such a keyword) *MUST* be ignored when processed: + +- `@context`, +- `@id`, +- `@included`, +- `@graph`, +- `@nest`, +- `@type`, +- `@reverse`, or +- `@index` + +If the [node object](#dfn-node-object) contains the `@context` key, its value *MUST* be [null](https://infra.spec.whatwg.org/#nulls), an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), a [context definition](#dfn-context-definition), or an [array](https://infra.spec.whatwg.org/#list) composed of any of these. + +If the [node object](#dfn-node-object) contains the `@id` key, its value *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), or a [compact IRI](#dfn-compact-iri) (including [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier)). See [§ 3.3 Node Identifiers](#node-identifiers), [§ 4.1.5 Compact IRIs](#compact-iris), and [§ 4.5.1 Identifying Blank Nodes](#identifying-blank-nodes) for further discussion on `@id` values. + +If the [node object](#dfn-node-object) contains the `@graph` key, its value *MUST* be a [node object](#dfn-node-object) or an [array](https://infra.spec.whatwg.org/#list) of zero or more [node objects](#dfn-node-object). If the [node object](#dfn-node-object) also contains an `@id` keyword, its value is used as the [graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name) of a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph). See [§ 4.9 Named Graphs](#named-graphs) for further discussion on `@graph` values. As a special case, if a [map](https://infra.spec.whatwg.org/#ordered-map) contains no keys other than `@graph` and `@context`, and the [map](https://infra.spec.whatwg.org/#ordered-map) is the root of the JSON-LD document, the [map](https://infra.spec.whatwg.org/#ordered-map) is not treated as a [node object](#dfn-node-object); this is used as a way of defining [node objects](#dfn-node-object) that may not form a connected graph. This allows a [context](#dfn-context) to be defined which is shared by all of the constituent [node objects](#dfn-node-object). + +If the [node object](#dfn-node-object) contains the `@type` key, its value *MUST* be either an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), a [compact IRI](#dfn-compact-iri) (including [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier)), a [term](#dfn-term) defined in the [active context](#dfn-active-context) expanding into an [IRI](https://tools.ietf.org/html/rfc3987#section-2), or an [array](https://infra.spec.whatwg.org/#list) of any of these. See [§ 3.5 Specifying the Type](#specifying-the-type) for further discussion on `@type` values. + +If the [node object](#dfn-node-object) contains the `@reverse` key, its value *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map) containing [entries](https://infra.spec.whatwg.org/#map-entry) representing reverse properties. Each value of such a reverse property *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), a [compact IRI](#dfn-compact-iri), a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier), a [node object](#dfn-node-object) or an [array](https://infra.spec.whatwg.org/#list) containing a combination of these. + +If the [node object](#dfn-node-object) contains the `@included` key, its value *MUST* be an [included block](#dfn-included-block). See [§ 9.13 Included Blocks](#included-blocks) for further discussion on [included blocks](#dfn-included-block). + +If the [node object](#dfn-node-object) contains the `@index` key, its value *MUST* be a [string](https://infra.spec.whatwg.org/#javascript-string). See [§ 4.6.1 Data Indexing](#data-indexing) for further discussion on `@index` values. + +If the [node object](#dfn-node-object) contains the `@nest` key, its value *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map) or an [array](https://infra.spec.whatwg.org/#list) of [map](https://infra.spec.whatwg.org/#ordered-map) which *MUST NOT* include a [value object](#dfn-value-object). See [§ 9.14 Property Nesting](#property-nesting) for further discussion on `@nest` values. + +Keys in a [node object](#dfn-node-object) that are not [keywords](#dfn-keyword) *MAY* expand to an [IRI](https://tools.ietf.org/html/rfc3987#section-2) using the [active context](#dfn-active-context). The values associated with keys that expand to an [IRI](https://tools.ietf.org/html/rfc3987#section-2) *MUST* be one of the following: + +- [string](https://infra.spec.whatwg.org/#javascript-string), +- [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), +- `true`, +- `false`, +- [null](https://infra.spec.whatwg.org/#nulls), +- [node object](#dfn-node-object), +- [graph object](#dfn-graph-object), +- [value object](#dfn-value-object), +- [list object](#dfn-list-object), +- [set object](#dfn-set-object), +- an [array](https://infra.spec.whatwg.org/#list) of zero or more of any of the possibilities above, +- a [language map](#dfn-language-map), +- an [index map](#dfn-index-map), +- an [included block](#dfn-included-block) +- an [id map](#dfn-id-map), or +- a [type map](#dfn-type-map) + +### 9.3 Frame Objects[](#frame-objects) + +When [framing](https://www.w3.org/TR/json-ld11-framing/#dfn-framing), a [frame object](https://www.w3.org/TR/json-ld11-framing/#dfn-frame-object) extends a [node object](#dfn-node-object) to allow [entries](https://infra.spec.whatwg.org/#map-entry) used specifically for [framing](https://www.w3.org/TR/json-ld11-framing/#dfn-framing). + +- A [frame object](https://www.w3.org/TR/json-ld11-framing/#dfn-frame-object) *MAY* include a [default object](#dfn-default-object) as the value of any key which is not a [keyword](#dfn-keyword). Values of `@default` *MAY* include the value `@null`, or an [array](https://infra.spec.whatwg.org/#list) containing only `@null`, in addition to other values allowed in the grammar for values of [entry](https://infra.spec.whatwg.org/#map-entry) keys expanding to [IRIs](https://tools.ietf.org/html/rfc3987#section-2). +- The values of `@id` and `@type` *MAY* additionally be an empty [map](https://infra.spec.whatwg.org/#ordered-map) ([wildcard](https://www.w3.org/TR/json-ld11-framing/#dfn-wildcard)), an [array](https://infra.spec.whatwg.org/#list) containing only an empty [map](https://infra.spec.whatwg.org/#ordered-map), an empty [array](https://infra.spec.whatwg.org/#list) ([match none](https://www.w3.org/TR/json-ld11-framing/#dfn-match-none)) an [array](https://infra.spec.whatwg.org/#list) of [IRIs](https://tools.ietf.org/html/rfc3987#section-2). +- A [frame object](https://www.w3.org/TR/json-ld11-framing/#dfn-frame-object) *MAY* include an [entry](https://infra.spec.whatwg.org/#map-entry) with the key `@embed` with any value from `@always`, `@once`, and `@never`. +- A [frame object](https://www.w3.org/TR/json-ld11-framing/#dfn-frame-object) *MAY* include [entries](https://infra.spec.whatwg.org/#map-entry) with the boolean valued keys `@explicit`, `@omitDefault`, or `@requireAll` +- In addition to other property values, a property of a [frame object](https://www.w3.org/TR/json-ld11-framing/#dfn-frame-object) *MAY* include a [value pattern](https://www.w3.org/TR/json-ld11-framing/#dfn-value-pattern) (See [§ 9.6 Value Patterns](#value-patterns)). + +See \[[JSON-LD11-FRAMING](#bib-json-ld11-framing "JSON-LD 1.1 Framing")\] for a description of how [frame objects](https://www.w3.org/TR/json-ld11-framing/#dfn-frame-object) are used. + +### 9.4 Graph Objects[](#graph-objects) + +A [graph object](#dfn-graph-object) represents a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), which *MAY* include an explicit [graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name). A [map](https://infra.spec.whatwg.org/#ordered-map) is a [graph object](#dfn-graph-object) if it exists outside of a JSON-LD [context](#dfn-context), it contains an `@graph` [entry](https://infra.spec.whatwg.org/#map-entry) (or an alias of that [keyword](#dfn-keyword)), it is not the top-most [map](https://infra.spec.whatwg.org/#ordered-map) in the JSON-LD document, and it consists of no [entries](https://infra.spec.whatwg.org/#map-entry) other than `@graph`, `@index`, `@id` and `@context`, or an alias of one of these [keywords](#dfn-keyword). + +If the [graph object](#dfn-graph-object) contains the `@context` key, its value *MUST* be [null](https://infra.spec.whatwg.org/#nulls), an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), a [context definition](#dfn-context-definition), or an [array](https://infra.spec.whatwg.org/#list) composed of any of these. + +If the [graph object](#dfn-graph-object) contains the `@id` key, its value is used as the identifier ([graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name)) of a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), and *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), or a [compact IRI](#dfn-compact-iri) (including [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier)). See [§ 3.3 Node Identifiers](#node-identifiers), [§ 4.1.5 Compact IRIs](#compact-iris), and [§ 4.5.1 Identifying Blank Nodes](#identifying-blank-nodes) for further discussion on `@id` values. + +A [graph object](#dfn-graph-object) without an `@id` [entry](https://infra.spec.whatwg.org/#map-entry) is also a [simple graph object](#dfn-simple-graph-object) and represents a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) without an explicit identifier, although in the data model it still has a [graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name), which is an implicitly allocated [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier). + +The value of the `@graph` key *MUST* be a [node object](#dfn-node-object) or an [array](https://infra.spec.whatwg.org/#list) of zero or more [node objects](#dfn-node-object). See [§ 4.9 Named Graphs](#named-graphs) for further discussion on `@graph` values.. + +### 9.5 Value Objects[](#value-objects) + +A [value object](#dfn-value-object) is used to explicitly associate a type or a language with a value to create a [typed value](#dfn-typed-value) or a [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) and possibly associate a [base direction](#dfn-base-direction). + +A [value object](#dfn-value-object) *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map) containing the `@value` key. It *MAY* also contain an `@type`, an `@language`, an `@direction`, an `@index`, or an `@context` key but *MUST NOT* contain both an `@type` and either `@language` or `@direction` keys at the same time. A [value object](#dfn-value-object) *MUST NOT* contain any other keys that expand to an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or [keyword](#dfn-keyword). + +The value associated with the `@value` key *MUST* be either a [string](https://infra.spec.whatwg.org/#javascript-string), a [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), `true`, `false` or [null](https://infra.spec.whatwg.org/#nulls). If the value associated with the `@type` key is `@json`, the value *MAY* be either an [array](https://infra.spec.whatwg.org/#list) or an [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object). + +The value associated with the `@type` key *MUST* be a [term](#dfn-term), an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [compact IRI](#dfn-compact-iri), a string which can be turned into an [IRI](https://tools.ietf.org/html/rfc3987#section-2) using the [vocabulary mapping](#dfn-vocabulary-mapping), `@json`, or [null](https://infra.spec.whatwg.org/#nulls). + +The value associated with the `@language` key *MUST* have the [lexical form](https://tools.ietf.org/html/bcp47#section-2.1.1) described in \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\], or be [null](https://infra.spec.whatwg.org/#nulls). + +The value associated with the `@direction` key *MUST* be one of `"ltr"` or `"rtl"`, or be [null](https://infra.spec.whatwg.org/#nulls). + +The value associated with the `@index` key *MUST* be a [string](https://infra.spec.whatwg.org/#javascript-string). + +See [§ 4.2.1 Typed Values](#typed-values) and [§ 4.2.4 String Internationalization](#string-internationalization) for more information on [value objects](#dfn-value-object). + +### 9.6 Value Patterns[](#value-patterns) + +When [framing](https://www.w3.org/TR/json-ld11-framing/#dfn-framing), a [value pattern](https://www.w3.org/TR/json-ld11-framing/#dfn-value-pattern) extends a [value object](#dfn-value-object) to allow [entries](https://infra.spec.whatwg.org/#map-entry) used specifically for [framing](https://www.w3.org/TR/json-ld11-framing/#dfn-framing). + +- The values of `@value`, `@language`, `@direction` and `@type` *MAY* additionally be an empty [map](https://infra.spec.whatwg.org/#ordered-map) ([wildcard](https://www.w3.org/TR/json-ld11-framing/#dfn-wildcard)), an [array](https://infra.spec.whatwg.org/#list) containing only an empty [map](https://infra.spec.whatwg.org/#ordered-map), an empty [array](https://infra.spec.whatwg.org/#list) ([match none](https://www.w3.org/TR/json-ld11-framing/#dfn-match-none)), an [array](https://infra.spec.whatwg.org/#list) of [strings](https://infra.spec.whatwg.org/#javascript-string). + +### 9.7 Lists and Sets[](#lists-and-sets) + +A [list](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab) represents an *ordered* set of values. A set represents an *unordered* set of values. Unless otherwise specified, [arrays](https://infra.spec.whatwg.org/#list) are unordered in JSON-LD. As such, the `@set` keyword, when used in the body of a JSON-LD document, represents just syntactic sugar which is optimized away when processing the document. However, it is very helpful when used within the context of a document. Values of terms associated with an `@set` or `@list` container will always be represented in the form of an [array](https://infra.spec.whatwg.org/#list) when a document is processed---even if there is just a single value that would otherwise be optimized to a non-array form in [compacted document form](#dfn-compacted-document-form). This simplifies post-processing of the data as the data is always in a deterministic form. + +A [list object](#dfn-list-object) *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map) that contains no keys that expand to an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or [keyword](#dfn-keyword) other than `@list` and `@index`. + +A [set object](#dfn-set-object) *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map) that contains no keys that expand to an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or [keyword](#dfn-keyword) other than `@set` and `@index`. Please note that the `@index` key will be ignored when being processed. + +In both cases, the value associated with the keys `@list` and `@set` *MUST* be one of the following types: + +- [string](https://infra.spec.whatwg.org/#javascript-string), +- [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), +- `true`, +- `false`, +- [null](https://infra.spec.whatwg.org/#nulls), +- [node object](#dfn-node-object), +- [value object](#dfn-value-object), or +- an [array](https://infra.spec.whatwg.org/#list) of zero or more of the above possibilities + +See [§ 4.3 Value Ordering](#sets-and-lists) for further discussion on sets and lists. + +### 9.8 Language Maps[](#language-maps) + +A [language map](#dfn-language-map) is used to associate a language with a value in a way that allows easy programmatic access. A [language map](#dfn-language-map) may be used as a term value within a [node object](#dfn-node-object) if the [term](#dfn-term) is defined with `@container` set to `@language`, or an array containing both `@language` and `@set` . The keys of a [language map](#dfn-language-map) *MUST* be [strings](https://infra.spec.whatwg.org/#javascript-string) representing \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\] language tags, the [keyword](#dfn-keyword) `@none`, or a [term](#dfn-term) which expands to `@none`, and the values *MUST* be any of the following types: + +- [null](https://infra.spec.whatwg.org/#nulls), +- [string](https://infra.spec.whatwg.org/#javascript-string), or +- an [array](https://infra.spec.whatwg.org/#list) of zero or more of the [strings](https://infra.spec.whatwg.org/#javascript-string) + +See [§ 4.2.4 String Internationalization](#string-internationalization) for further discussion on language maps. + +### 9.9 Index Maps[](#index-maps) + +An [index map](#dfn-index-map) allows keys that have no semantic meaning, but should be preserved regardless, to be used in JSON-LD documents. An [index map](#dfn-index-map) may be used as a [term](#dfn-term) value within a [node object](#dfn-node-object) if the term is defined with `@container` set to `@index`, or an array containing both `@index` and `@set` . The values of the [entries](https://infra.spec.whatwg.org/#map-entry) of an [index map](#dfn-index-map) *MUST* be one of the following types: + +- [string](https://infra.spec.whatwg.org/#javascript-string), +- [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), +- `true`, +- `false`, +- [null](https://infra.spec.whatwg.org/#nulls), +- [node object](#dfn-node-object), +- [value object](#dfn-value-object), +- [list object](#dfn-list-object), +- [set object](#dfn-set-object), +- an [array](https://infra.spec.whatwg.org/#list) of zero or more of the above possibilities + +See [§ 4.6.1 Data Indexing](#data-indexing) for further information on this topic. + +[Index Maps](#dfn-index-map) may also be used to map indexes to associated [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), if the term is defined with `@container` set to an array containing both `@graph` and `@index`, and optionally including `@set`. The value consists of the [node objects](#dfn-node-object) contained within the [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) which is indexed using the referencing key, which can be represented as a [simple graph object](#dfn-simple-graph-object) if the value does not include `@id`, or a [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) if it includes `@id`. + +### 9.10 Property-based Index Maps[](#property-based-index-maps) + +A property-based [index map](#dfn-index-map) is a variant of [index map](#dfn-index-map) were indexes are semantically preserved in the graph as property values. A property-based [index map](#dfn-index-map) may be used as a term value within a [node object](#dfn-node-object) if the [term](#dfn-term) is defined with `@container` set to `@index`, or an array containing both `@index` and `@set`, and with `@index` set to a [string](https://infra.spec.whatwg.org/#javascript-string). The values of a property-based [index map](#dfn-index-map) *MUST* be [node objects](#dfn-node-object) or [strings](https://infra.spec.whatwg.org/#javascript-string) which expand to [node objects](#dfn-node-object). + +When expanding, if the [active context](#dfn-active-context) contains a [term definition](#dfn-term-definition) for the value of `@index`, this [term definition](#dfn-term-definition) will be used to expand the keys of the [index map](#dfn-index-map). Otherwise, the keys will be expanded as simple [value objects](#dfn-value-object). Each [node object](#dfn-node-object) in the expanded values of the [index map](#dfn-index-map) will be added an additional property value, where the property is the expanded value of `@index`, and the value is the expanded referencing key. + +See [§ 4.6.1.1 Property-based data indexing](#property-based-data-indexing) for further information on this topic. + +### 9.11 Id Maps[](#id-maps) + +An [id map](#dfn-id-map) is used to associate an [IRI](https://tools.ietf.org/html/rfc3987#section-2) with a value that allows easy programmatic access. An [id map](#dfn-id-map) may be used as a term value within a [node object](#dfn-node-object) if the [term](#dfn-term) is defined with `@container` set to `@id`, or an array containing both `@id` and `@set`. The keys of an [id map](#dfn-id-map) *MUST* be [IRIs](https://tools.ietf.org/html/rfc3987#section-2) ([IRI references](https://tools.ietf.org/html/rfc3987#section-1.3) or [compact IRIs](#dfn-compact-iri) (including [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier))), the [keyword](#dfn-keyword) `@none`, or a [term](#dfn-term) which expands to `@none`, and the values *MUST* be [node objects](#dfn-node-object). + +If the value contains a property expanding to `@id`, its value *MUST* be equivalent to the referencing key. Otherwise, the property from the value is used as the `@id` of the [node object](#dfn-node-object) value when expanding. + +[Id Maps](#dfn-id-map) may also be used to map [graph names](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-name) to their [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), if the term is defined with `@container` set to an array containing both `@graph` and `@id`, and optionally including `@set`. The value consists of the [node objects](#dfn-node-object) contained within the [named graph](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph) which is named using the referencing key. + +### 9.12 Type Maps[](#type-maps) + +A [type map](#dfn-type-map) is used to associate an [IRI](https://tools.ietf.org/html/rfc3987#section-2) with a value that allows easy programmatic access. A [type map](#dfn-type-map) may be used as a term value within a [node object](#dfn-node-object) if the [term](#dfn-term) is defined with `@container` set to `@type`, or an array containing both `@type` and `@set`. The keys of a [type map](#dfn-type-map) *MUST* be [IRIs](https://tools.ietf.org/html/rfc3987#section-2) ([IRI references](https://tools.ietf.org/html/rfc3987#section-1.3) or [compact IRI](#dfn-compact-iri) (including [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier))), [terms](#dfn-term), or the [keyword](#dfn-keyword) `@none`, and the values *MUST* be [node objects](#dfn-node-object) or [strings](https://infra.spec.whatwg.org/#javascript-string) which expand to [node objects](#dfn-node-object). + +If the value contains a property expanding to `@type`, and its value is contains the referencing key after suitable expansion of both the referencing key and the value, then the [node object](#dfn-node-object) already contains the type. Otherwise, the property from the value is added as a `@type` of the [node object](#dfn-node-object) value when expanding. + +### 9.13 Included Blocks[](#included-blocks) + +An [included block](#dfn-included-block) is used to provide a set of [node objects](#dfn-node-object). An [included block](#dfn-included-block) *MAY* appear as the value of a member of a node object with either the key of `@included` or an alias of `@included`. An [included block](#dfn-included-block) is either a [node object](#dfn-node-object) or an array of [node objects](#dfn-node-object). + +When [expanding](https://www.w3.org/TR/json-ld11-api/#dfn-expanded), multiple [included blocks](#dfn-included-block) will be coalesced into a single [included block](#dfn-included-block). + +### 9.14 Property Nesting[](#property-nesting) + +A [nested property](#dfn-nested-property) is used to gather [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property) of a [node object](#dfn-node-object) in a separate [map](https://infra.spec.whatwg.org/#ordered-map), or [array](https://infra.spec.whatwg.org/#list) of [maps](https://infra.spec.whatwg.org/#ordered-map) which are not [value objects](#dfn-value-object). It is semantically transparent and is removed during the process of [expansion](https://www.w3.org/TR/json-ld11-api/#dfn-expanded). Property nesting is recursive, and collections of nested properties may contain further nesting. + +Semantically, nesting is treated as if the properties and values were declared directly within the containing [node object](#dfn-node-object). + +### 9.15 Context Definitions[](#context-definitions) + +A context definition defines a [local context](#dfn-local-context) in a [node object](#dfn-node-object). + +A [context definition](#dfn-context-definition) *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map) whose keys *MUST* be either [terms](#dfn-term), [compact IRIs](#dfn-compact-iri), [IRIs](https://tools.ietf.org/html/rfc3987#section-2), or one of the [keywords](#dfn-keyword) `@base`, `@import`, `@language`, `@propagate`, `@protected`, `@type`, `@version`, or `@vocab`. + +If the [context definition](#dfn-context-definition) has an `@base` key, its value *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), or [null](https://infra.spec.whatwg.org/#nulls). + +If the [context definition](#dfn-context-definition) has an `@direction` key, its value *MUST* be one of `"ltr"` or `"rtl"`, or be [null](https://infra.spec.whatwg.org/#nulls). + +If the [context definition](#dfn-context-definition) contains the `@import` [keyword](#dfn-keyword), its value *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3). When used as a reference from an `@import`, the referenced [context definition](#dfn-context-definition) *MUST NOT* include an `@import` key, itself. + +If the [context definition](#dfn-context-definition) has an `@language` key, its value *MUST* have the [lexical form](https://tools.ietf.org/html/bcp47#section-2.1.1) described in \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\] or be [null](https://infra.spec.whatwg.org/#nulls). + +If the [context definition](#dfn-context-definition) has an `@propagate` key, its value *MUST* be `true` or `false`. + +If the [context definition](#dfn-context-definition) has an `@protected` key, its value *MUST* be `true` or `false`. + +If the [context definition](#dfn-context-definition) has an `@type` key, its value *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map) with only the [entry](https://infra.spec.whatwg.org/#map-entry) `@container` set to `@set`, and optionally an entry `@protected`. + +If the [context definition](#dfn-context-definition) has an `@version` key, its value *MUST* be a [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value) with the value `1.1`. + +If the [context definition](#dfn-context-definition) has an `@vocab` key, its value *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), a [compact IRI](#dfn-compact-iri), a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier), a [term](#dfn-term), or [null](https://infra.spec.whatwg.org/#nulls). + +The value of keys that are not [keywords](#dfn-keyword) *MUST* be either an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [compact IRI](#dfn-compact-iri), a [term](#dfn-term), a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier), a [keyword](#dfn-keyword), [null](https://infra.spec.whatwg.org/#nulls), or an [expanded term definition](#dfn-expanded-term-definition). + +#### 9.15.1 Expanded term definition[](#expanded-term-definition) + +An [expanded term definition](#dfn-expanded-term-definition) is used to describe the mapping between a [term](#dfn-term) and its expanded identifier, as well as other properties of the value associated with the [term](#dfn-term) when it is used as key in a [node object](#dfn-node-object). + +An [expanded term definition](#dfn-expanded-term-definition) *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map) composed of zero or more keys from `@id`, `@reverse`, `@type`, `@language`, `@container`, `@context`, `@prefix`, `@propagate`, or `@protected`. An [expanded term definition](#dfn-expanded-term-definition) *SHOULD NOT* contain any other keys. + +When the associated term is `@type`, the [expanded term definition](#dfn-expanded-term-definition) *MUST NOT* contain keys other than `@container` and `@protected`. The value of `@container` is limited to the single value `@set`. + +If the term being defined is not an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or a [compact IRI](#dfn-compact-iri) and the [active context](#dfn-active-context) does not have an `@vocab` mapping, the [expanded term definition](#dfn-expanded-term-definition) *MUST* include the `@id` key. + +[Term definitions](#dfn-term-definition) with keys which are of the form of an [IRI](https://tools.ietf.org/html/rfc3987#section-2) or a [compact IRI](#dfn-compact-iri) *MUST NOT* expand to an [IRI](https://tools.ietf.org/html/rfc3987#section-2) other than the expansion of the key itself. + +If the [expanded term definition](#dfn-expanded-term-definition) contains the `@id` [keyword](#dfn-keyword), its value *MUST* be [null](https://infra.spec.whatwg.org/#nulls), an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier), a [compact IRI](#dfn-compact-iri), a [term](#dfn-term), or a [keyword](#dfn-keyword). + +If an [expanded term definition](#dfn-expanded-term-definition) has an `@reverse` [entry](https://infra.spec.whatwg.org/#map-entry), it *MUST NOT* have `@id` or `@nest` [entries](https://infra.spec.whatwg.org/#map-entry) at the same time, its value *MUST* be an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier), a [compact IRI](#dfn-compact-iri), or a [term](#dfn-term). If an `@container` [entry](https://infra.spec.whatwg.org/#map-entry) exists, its value *MUST* be [null](https://infra.spec.whatwg.org/#nulls), `@set`, or `@index`. + +If the [expanded term definition](#dfn-expanded-term-definition) contains the `@type` [keyword](#dfn-keyword), its value *MUST* be an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [compact IRI](#dfn-compact-iri), a [term](#dfn-term), [null](https://infra.spec.whatwg.org/#nulls), or one of the [keywords](#dfn-keyword) `@id`, `@json`, `@none`, or `@vocab`. + +If the [expanded term definition](#dfn-expanded-term-definition) contains the `@language` [keyword](#dfn-keyword), its value *MUST* have the [lexical form](https://tools.ietf.org/html/bcp47#section-2.1.1) described in \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\] or be [null](https://infra.spec.whatwg.org/#nulls). + +If the [expanded term definition](#dfn-expanded-term-definition) contains the `@index` [keyword](#dfn-keyword), its value *MUST* be an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [compact IRI](#dfn-compact-iri), or a [term](#dfn-term). + +If the [expanded term definition](#dfn-expanded-term-definition) contains the `@container` [keyword](#dfn-keyword), its value *MUST* be either `@list`, `@set`, `@language`, `@index`, `@id`, `@graph`, `@type`, or be [null](https://infra.spec.whatwg.org/#nulls) or an [array](https://infra.spec.whatwg.org/#list) containing exactly any one of those keywords, or a combination of `@set` and any of `@index`, `@id`, `@graph`, `@type`, `@language` in any order . `@container` may also be an array containing `@graph` along with either `@id` or `@index` and also optionally including `@set`. If the value is `@language`, when the [term](#dfn-term) is used outside of the `@context`, the associated value *MUST* be a [language map](#dfn-language-map). If the value is `@index`, when the [term](#dfn-term) is used outside of the `@context`, the associated value *MUST* be an [index map](#dfn-index-map). + +If an [expanded term definition](#dfn-expanded-term-definition) has an `@context` [entry](https://infra.spec.whatwg.org/#map-entry), it *MUST* be a valid `context definition`. + +If the [expanded term definition](#dfn-expanded-term-definition) contains the `@nest` [keyword](#dfn-keyword), its value *MUST* be either `@nest`, or a term which expands to `@nest`. + +If the [expanded term definition](#dfn-expanded-term-definition) contains the `@prefix` [keyword](#dfn-keyword), its value *MUST* be `true` or `false`. + +If the [expanded term definition](#dfn-expanded-term-definition) contains the `@propagate` [keyword](#dfn-keyword), its value *MUST* be `true` or `false`. + +If the [expanded term definition](#dfn-expanded-term-definition) contains the `@protected` [keyword](#dfn-keyword), its value *MUST* be `true` or `false`. + +[Terms](#dfn-term) *MUST NOT* be used in a circular manner. That is, the definition of a term cannot depend on the definition of another term if that other term also depends on the first term. + +See [§ 3.1 The Context](#the-context) for further discussion on [contexts](#dfn-context). + +### 9.16 Keywords[](#keywords) + +JSON-LD [keywords](#dfn-keyword) are described in [§ 1.7 Syntax Tokens and Keywords](#syntax-tokens-and-keywords), this section describes where each [keyword](#dfn-keyword) may appear within different JSON-LD structures. + +Within [node objects](#dfn-node-object), [value objects](#dfn-value-object), [graph objects](#dfn-graph-object), [list objects](#dfn-list-object), [set objects](#dfn-set-object), and [nested properties](#dfn-nested-property) [keyword](#dfn-keyword) aliases *MAY* be used instead of the corresponding [keyword](#dfn-keyword), except for `@context`. The `@context` [keyword](#dfn-keyword) *MUST NOT* be aliased. Within [local contexts](#dfn-local-context) and [expanded term definitions](#dfn-expanded-term-definition), [keyword](#dfn-keyword) aliases *MAY* NOT used. + +`@base` +: The unaliased `@base` keyword *MAY* be used as a key in a [context definition](#dfn-context-definition). Its value *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), or [null](https://infra.spec.whatwg.org/#nulls). + +`@container` +: The unaliased `@container` keyword *MAY* be used as a key in an [expanded term definition](#dfn-expanded-term-definition). Its value *MUST* be either `@list`, `@set`, `@language`, `@index`, `@id`, `@graph`, `@type`, or be [null](https://infra.spec.whatwg.org/#nulls), or an [array](https://infra.spec.whatwg.org/#list) containing exactly any one of those keywords, or a combination of `@set` and any of `@index`, `@id`, `@graph`, `@type`, `@language` in any order. The value may also be an array containing `@graph` along with either `@id` or `@index` and also optionally including `@set`. + +`@context` +: The `@context` keyword *MUST NOT* be aliased, and *MAY* be used as a key in the following objects: + - [node objects](#dfn-node-object) (see [§ 9.2 Node Objects](#node-objects)), + - [value objects](#dfn-value-object) (see [§ 9.5 Value Objects](#value-objects)), + - [graph objects](#dfn-graph-object) (see [§ 9.4 Graph Objects](#graph-objects)), + - [list objects](#dfn-list-object) (see [§ 9.7 Lists and Sets](#lists-and-sets)), + - [set objects](#dfn-set-object) (see [§ 9.7 Lists and Sets](#lists-and-sets)), + - [nested properties](#dfn-nested-property) (see [§ 9.14 Property Nesting](#property-nesting)), and + - [expanded term definitions](#dfn-expanded-term-definition) (see [§ 9.15 Context Definitions](#context-definitions)). + + The value of `@context` *MUST* be [null](https://infra.spec.whatwg.org/#nulls), an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), a [context definition](#dfn-context-definition), or an [array](https://infra.spec.whatwg.org/#list) composed of any of these. + +`@direction` + +: The `@direction` keyword *MAY* be aliased and *MAY* be used as a key in a [value object](#dfn-value-object). Its value *MUST* be one of `"ltr"` or `"rtl"`, or be [null](https://infra.spec.whatwg.org/#nulls). + + The unaliased `@direction` *MAY* be used as a key in a [context definition](#dfn-context-definition). + + See [§ 4.2.4.1 Base Direction](#base-direction) for a further discussion. + +`@graph` + +: The `@graph` keyword *MAY* be aliased and *MAY* be used as a key in a [node object](#dfn-node-object) or a [graph object](#dfn-graph-object), where its value *MUST* be a [value object](#dfn-value-object), [node object](#dfn-node-object), or an array of either [value objects](#dfn-value-object) or [node objects](#dfn-node-object). + + The unaliased `@graph` *MAY* be used as the value of the `@container` key within an [expanded term definition](#dfn-expanded-term-definition). + + See [§ 4.9 Named Graphs](#named-graphs). + +`@id` + +: The `@id` keyword *MAY* be aliased and *MAY* be used as a key in a [node object](#dfn-node-object) or a [graph object](#dfn-graph-object). + + The unaliased `@id` *MAY* be used as a key in an [expanded term definition](#dfn-expanded-term-definition), or as the value of the `@container` key within an [expanded term definition](#dfn-expanded-term-definition). + + The value of the `@id` key *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), or a [compact IRI](#dfn-compact-iri) (including [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier)). + + See [§ 3.3 Node Identifiers](#node-identifiers), [§ 4.1.5 Compact IRIs](#compact-iris), and [§ 4.5.1 Identifying Blank Nodes](#identifying-blank-nodes) for further discussion on `@id` values. + +`@import` +: The unaliased `@import` keyword *MAY* be used in a [context definition](#dfn-context-definition). Its value *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3). See [§ 4.1.10 Imported Contexts](#imported-contexts) for a further discussion. + +`@included` +: The `@included` keyword *MAY* be aliased and its value *MUST* be an [included block](#dfn-included-block). This keyword is described further in [§ 4.7 Included Nodes](#included-nodes), and [§ 9.13 Included Blocks](#included-blocks). + +`@index` + +: The `@index` keyword *MAY* be aliased and *MAY* be used as a key in a [node object](#dfn-node-object), [value object](#dfn-value-object), [graph object](#dfn-graph-object), [set object](#dfn-set-object), or [list object](#dfn-list-object). Its value *MUST* be a [string](https://infra.spec.whatwg.org/#javascript-string). + + The unaliased `@index` *MAY* be used as the value of the `@container` key within an [expanded term definition](#dfn-expanded-term-definition) and as an entry in a [expanded term definition](#dfn-expanded-term-definition), where the value an [IRI](https://tools.ietf.org/html/rfc3987#section-2), a [compact IRI](#dfn-compact-iri), or a [term](#dfn-term). + + See [§ 9.9 Index Maps](#index-maps), and [§ 4.6.1.1 Property-based data indexing](#property-based-data-indexing) for a further discussion. + +`@json` + +: The `@json` keyword *MAY* be aliased and *MAY* be used as the value of the `@type` key within a [value object](#dfn-value-object) or an [expanded term definition](#dfn-expanded-term-definition). + + See [§ 4.2.2 JSON Literals](#json-literals). + +`@language` + +: The `@language` keyword *MAY* be aliased and *MAY* be used as a key in a [value object](#dfn-value-object). Its value *MUST* be a [string](https://infra.spec.whatwg.org/#javascript-string) with the [lexical form](https://tools.ietf.org/html/bcp47#section-2.1.1) described in \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\] or be [null](https://infra.spec.whatwg.org/#nulls). + + The unaliased `@language` *MAY* be used as a key in a [context definition](#dfn-context-definition), or as the value of the `@container` key within an [expanded term definition](#dfn-expanded-term-definition). + + See [§ 4.2.4 String Internationalization](#string-internationalization), [§ 9.8 Language Maps](#language-maps). + +`@list` + +: The `@list` keyword *MAY* be aliased and *MUST* be used as a key in a [list object](#dfn-list-object). The unaliased `@list` *MAY* be used as the value of the `@container` key within an [expanded term definition](#dfn-expanded-term-definition). Its value *MUST* be one of the following: + + - [string](https://infra.spec.whatwg.org/#javascript-string), + - [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), + - `true`, + - `false`, + - [null](https://infra.spec.whatwg.org/#nulls), + - [node object](#dfn-node-object), + - [value object](#dfn-value-object), or + - an [array](https://infra.spec.whatwg.org/#list) of zero or more of the above possibilities + + See [§ 4.3 Value Ordering](#sets-and-lists) for further discussion on sets and lists. + +`@nest` + +: The `@nest` keyword *MAY* be aliased and *MAY* be used as a key in a [node object](#dfn-node-object), where its value must be a [map](https://infra.spec.whatwg.org/#ordered-map). + + The unaliased `@nest` *MAY* be used as the value of a [simple term definition](#dfn-simple-term-definition), or as a key in an [expanded term definition](#dfn-expanded-term-definition), where its value *MUST* be a string expanding to `@nest`. + + See [§ 9.14 Property Nesting](#property-nesting) for a further discussion. + +`@none` +: The `@none` keyword *MAY* be aliased and *MAY* be used as a key in an [index map](#dfn-index-map), [id map](#dfn-id-map), [language map](#dfn-language-map), [type map](#dfn-type-map). See [§ 4.6.1 Data Indexing](#data-indexing), [§ 4.6.2 Language Indexing](#language-indexing), [§ 4.6.3 Node Identifier Indexing](#node-identifier-indexing), [§ 4.6.4 Node Type Indexing](#node-type-indexing), [§ 4.9.3 Named Graph Indexing](#named-graph-indexing), or [§ 4.9.2 Named Graph Data Indexing](#named-graph-data-indexing) for a further discussion. + +`@prefix` +: The unaliased `@prefix` keyword *MAY* be used as a key in an [expanded term definition](#dfn-expanded-term-definition). Its value *MUST* be `true` or `false`. See [§ 4.1.5 Compact IRIs](#compact-iris) and [§ 9.15 Context Definitions](#context-definitions) for a further discussion. + +`@propagate` +: The unaliased `@propagate` keyword *MAY* be used in a [context definition](#dfn-context-definition). Its value *MUST* be `true` or `false`. See [§ 4.1.9 Context Propagation](#context-propagation) for a further discussion. + +`@protected` +: The unaliased `@protected` keyword *MAY* be used in a [context definition](#dfn-context-definition), or an [expanded term definition](#dfn-expanded-term-definition). Its value *MUST* be `true` or `false`. See [§ 4.1.11 Protected Term Definitions](#protected-term-definitions) for a further discussion. + +`@reverse` + +: The `@reverse` keyword *MAY* be aliased and *MAY* be used as a key in a [node object](#dfn-node-object). + + The unaliased `@reverse` *MAY* be used as a key in an [expanded term definition](#dfn-expanded-term-definition). + + The value of the `@reverse` key *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), or a [compact IRI](#dfn-compact-iri) (including [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier)). + + See [§ 4.8 Reverse Properties](#reverse-properties) and [§ 9.15 Context Definitions](#context-definitions) for further discussion. + +`@set` + +: The `@set` keyword *MAY* be aliased and *MUST* be used as a key in a [set object](#dfn-set-object). Its value *MUST* be one of the following: + + - [string](https://infra.spec.whatwg.org/#javascript-string), + - [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), + - `true`, + - `false`, + - [null](https://infra.spec.whatwg.org/#nulls), + - [node object](#dfn-node-object), + - [value object](#dfn-value-object), or + - an [array](https://infra.spec.whatwg.org/#list) of zero or more of the above possibilities + + The unaliased `@set` *MAY* be used as the value of the `@container` key within an [expanded term definition](#dfn-expanded-term-definition). + + See [§ 4.3 Value Ordering](#sets-and-lists) for further discussion on sets and lists. + +`@type` + +: The `@type` keyword *MAY* be aliased and *MAY* be used as a key in a [node object](#dfn-node-object) or a [value object](#dfn-value-object), where its value *MUST* be a [term](#dfn-term), [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), or a [compact IRI](#dfn-compact-iri) (including [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier)). + + The unaliased `@type` *MAY* be used as a key in an [expanded term definition](#dfn-expanded-term-definition), where its value may also be either `@id` or `@vocab`, or as the value of the `@container` key within an [expanded term definition](#dfn-expanded-term-definition). + + Within a context, `@type` may be used as the key for an [expanded term definition](#dfn-expanded-term-definition), whose entries are limited to `@container` and `@protected`. + + This keyword is described further in [§ 3.5 Specifying the Type](#specifying-the-type) and [§ 4.2.1 Typed Values](#typed-values). + +`@value` +: The `@value` keyword *MAY* be aliased and *MUST* be used as a key in a [value object](#dfn-value-object). Its value key *MUST* be either a [string](https://infra.spec.whatwg.org/#javascript-string), a [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), `true`, `false` or [null](https://infra.spec.whatwg.org/#nulls). This keyword is described further in [§ 9.5 Value Objects](#value-objects). + +`@version` +: The unaliased `@version` keyword *MAY* be used as a key in a [context definition](#dfn-context-definition). Its value *MUST* be a [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value) with the value `1.1`. This keyword is described further in [§ 9.15 Context Definitions](#context-definitions). + +`@vocab` +: The unaliased `@vocab` keyword *MAY* be used as a key in a [context definition](#dfn-context-definition) or as the value of `@type` in an [expanded term definition](#dfn-expanded-term-definition). Its value *MUST* be an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), a [compact IRI](#dfn-compact-iri), a [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier), a [term](#dfn-term), or [null](https://infra.spec.whatwg.org/#nulls). This keyword is described further in [§ 9.15 Context Definitions](#context-definitions), and [§ 4.1.2 Default Vocabulary](#default-vocabulary). + +## 10. Relationship to RDF[](#relationship-to-rdf) + +JSON-LD is a [concrete RDF syntax](https://www.w3.org/TR/rdf11-concepts/#dfn-concrete-rdf-syntax) as described in \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\]. Hence, a JSON-LD document is both an RDF document *and* a JSON document and correspondingly represents an instance of an [RDF data model](https://www.w3.org/TR/rdf11-concepts/#data-model). However, JSON-LD also extends the RDF data model to optionally allow JSON-LD to serialize [generalized RDF Datasets](https://www.w3.org/TR/rdf11-concepts/#dfn-generalized-rdf-dataset). The JSON-LD extensions to the RDF data model are: + +- In JSON-LD [properties](https://www.w3.org/TR/rdf11-concepts/#dfn-property) can be [IRIs](https://tools.ietf.org/html/rfc3987#section-2) or [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) whereas in RDF properties ([predicates](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate)) have to be [IRIs](https://tools.ietf.org/html/rfc3987#section-2). This means that JSON-LD serializes [generalized RDF Datasets](https://www.w3.org/TR/rdf11-concepts/#dfn-generalized-rdf-dataset). +- In JSON-LD [lists](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab) use native JSON syntax, either contained in a list object, or described as such within a context. Consequently, developers using the JSON representation can access list elements directly rather than using the vocabulary for collections described in \[[RDF-SCHEMA](#bib-rdf-schema "RDF Schema 1.1")\]. +- RDF values are either typed *literals* ([typed values](#dfn-typed-value)) or [language-tagged strings](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) whereas JSON-LD also supports JSON\'s native data types, i.e., [number](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value), [strings](https://infra.spec.whatwg.org/#javascript-string), and the boolean values `true` and `false`. The JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\] defines the [conversion rules](https://www.w3.org/TR/json-ld11-api/#data-round-tripping) between JSON\'s native data types and RDF\'s counterparts to allow round-tripping. +- As an extension to the [RDF data model](https://www.w3.org/TR/rdf11-concepts/#data-model), literals without an explicit datatype *MAY* include a [base direction](#dfn-base-direction). As there is currently no standardized mechanism for representing the [base direction](#dfn-base-direction) of [RDF literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal), the JSON-LD to standard RDF transformation loses the base direction. However, the [Deserialize JSON-LD to RDF Algorithm](https://www.w3.org/TR/json-ld11-api/#deserialize-json-ld-to-rdf-algorithm) provides a means of representing [base direction](#dfn-base-direction) using mechanisms which will preserve round-tripping through non-standard RDF. + +Note + +The use of [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) to label properties is obsolete, and may be removed in a future version of JSON-LD, as is the support for [generalized RDF Datasets](https://www.w3.org/TR/rdf11-concepts/#dfn-generalized-rdf-dataset). + +Summarized, these differences mean that JSON-LD is capable of serializing any RDF [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) or [dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and most, but not all, JSON-LD documents can be directly interpreted as RDF as described in RDF 1.1 Concepts \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\]. + +Authors are strongly encouraged to avoid labeling properties using [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier), instead, consider one of the following mechanisms: + +- a [relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5), either relative to the document or the vocabulary (see [§ 4.1.4 Using the Document Base for the Default Vocabulary](#document-relative-vocabulary-mapping) for a discussion on using the document base as part of the [vocabulary mapping](#dfn-vocabulary-mapping)), +- a URN such as `urn:example:1`, see \[[URN](#bib-urn "URN Syntax")\], or +- a \"Skolem IRI\" as per [Replacing Blank Nodes with IRIs](https://www.w3.org/TR/rdf11-concepts/#section-skolemization) of \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\]. + +The normative algorithms for interpreting JSON-LD as RDF and serializing RDF as JSON-LD are specified in the JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\]. + +Even though JSON-LD serializes [RDF Datasets](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset), it can also be used as a [graph source](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-source). In that case, a consumer *MUST* only use the [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) and ignore all [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph). This allows servers to expose data in languages such as Turtle and JSON-LD using [HTTP content negotiation](https://en.wikipedia.org/wiki/Content_negotiation). + +Note + +Publishers supporting both [dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) syntaxes have to ensure that the primary data is stored in the [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) to enable consumers that do not support [datasets](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) to process the information. + +### 10.1 Serializing/Deserializing RDF[](#serializing-deserializing-rdf) + +*This section is non-normative.* + +The process of serializing RDF as JSON-LD and deserializing JSON-LD to RDF depends on executing the algorithms defined in [RDF Serialization-Deserialization Algorithms](https://www.w3.org/TR/json-ld11-api/#rdf-serialization-deserialization-algorithms) in the JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\]. It is beyond the scope of this document to detail these algorithms any further, but a summary of the necessary operations is provided to illustrate the process. + +The procedure to deserialize a JSON-LD document to RDF involves the following steps: + +1. Expand the JSON-LD document, removing any context; this ensures that properties, types, and values are given their full representation as [IRIs](https://tools.ietf.org/html/rfc3987#section-2) and expanded values. [Expansion](https://www.w3.org/TR/json-ld11-api/#dfn-expanded) is discussed further in [§ 5.1 Expanded Document Form](#expanded-document-form). +2. Flatten the document, which turns the document into an array of [node objects](#dfn-node-object). Flattening is discussed further in [§ 5.3 Flattened Document Form](#flattened-document-form). +3. Turn each [node object](#dfn-node-object) into a series of [triples](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple). + +For example, consider the following JSON-LD document in compact form: + +[Example 151](#example-151-sample-json-ld-document): Sample JSON-LD document + +``` {aria-busy="false"} +{ + "@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": [ + { + "@id": "http://manu.sporny.org/about#manu", + "name": "Manu Sporny" + }, { + "name": "Dave Longley" + } + ] +} +``` + +Running the JSON-LD [Expansion](https://www.w3.org/TR/json-ld11-api/#expansion-algorithm) and [Flattening](https://www.w3.org/TR/json-ld11-api/#flattening-algorithm) algorithms against the JSON-LD input document in the example above would result in the following output: + +[Example 152](#example-152-flattened-and-expanded-form-for-the-previous-example): Flattened and expanded form for the previous example + +``` {aria-busy="false"} +[ + { + "@id": "_:b0", + "http://xmlns.com/foaf/0.1/name": "Dave Longley" + }, { + "@id": "http://manu.sporny.org/about#manu", + "http://xmlns.com/foaf/0.1/name": "Manu Sporny" + }, { + "@id": "http://me.markus-lanthaler.com/", + "http://xmlns.com/foaf/0.1/name": "Markus Lanthaler", + "http://xmlns.com/foaf/0.1/knows": [ + { "@id": "http://manu.sporny.org/about#manu" }, + { "@id": "_:b0" } + ] + } +] +``` + +Deserializing this to RDF now is a straightforward process of turning each [node object](#dfn-node-object) into one or more [triples](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple). This can be expressed in Turtle as follows: + +[Example 153](#example-153-turtle-representation-of-expanded-flattened-document): Turtle representation of expanded/flattened document + +``` {content-type="text/turtle" result-for="Flattened and expanded form for the previous example" to-rdf="" aria-busy="false"} +@prefix foaf: . + +_:b0 foaf:name "Dave Longley" . + + foaf:name "Manu Sporny" . + + foaf:name "Markus Lanthaler" ; + foaf:knows , _:b0 . +``` + +The process of serializing RDF as JSON-LD can be thought of as the inverse of this last step, creating an expanded JSON-LD document closely matching the triples from RDF, using a single [node object](#dfn-node-object) for all triples having a common subject, and a single [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) for those triples also having a common [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate). The result may then be framed by using the [Framing Algorithm](https://www.w3.org/TR/json-ld11-framing/#framing-algorithm) described in \[[JSON-LD11-FRAMING](#bib-json-ld11-framing "JSON-LD 1.1 Framing")\] to create the desired object embedding. + +### 10.2 The `rdf:JSON` Datatype[](#the-rdf-json-datatype) + +RDF provides for JSON content as a possible [literal value](https://www.w3.org/TR/rdf11-concepts/#dfn-literal). This allows markup in literal values. Such content is indicated in a [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) using a [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) whose datatype is set to `rdf:JSON`. + +The `rdf:JSON` datatype is defined as follows: + +The IRI denoting this datatype +: is `http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON`. + +The lexical space +: is the set of UNICODE \[[UNICODE](#bib-unicode "The Unicode Standard")\] strings which conform to the [JSON Grammar](https://tools.ietf.org/html/rfc4627#section-2) as described in [Section 2 JSON Grammar](https://tools.ietf.org/html/rfc8259#section-2) of \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\]. + +The value space +: is the set of UNICODE \[[UNICODE](#bib-unicode "The Unicode Standard")\] strings which conform to the [JSON Grammar](https://tools.ietf.org/html/rfc4627#section-2) as described in [Section 2 JSON Grammar](https://tools.ietf.org/html/rfc8259#section-2) of \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\], and furthermore comply with the following constraints: + - It *MUST NOT* contain any unnecessary whitespace, + - Keys in objects *MUST* be ordered lexicographically, + - Native Numeric values *MUST* be serialized according to [Section 7.1.12.1](https://tc39.es/ecma262/#sec-tostring-applied-to-the-number-type) of \[[ECMASCRIPT](#bib-ecmascript "ECMAScript Language Specification")\], + - Strings *MUST* be serialized with Unicode codepoints from `U+0000` through `U+001F` using lower case hexadecimal Unicode notation (`\uhhhh`) unless in the set of predefined JSON control characters `U+0008`, `U+0009`, `U+000A`, `U+000C` or `U+000D` which *SHOULD* be serialized as `\b`, `\t`, `\n`, `\f` and `\r` respectively. All other Unicode characters *SHOULD* be serialized \"as is\", other than `U+005C` (`\`) and `U+0022` (`"`) which *SHOULD* be serialized as `\\` and `\"` respectively. + + Issue + + The JSON Canonicalization Scheme (JCS) \[[RFC8785](#bib-rfc8785 "JSON Canonicalization Scheme (JCS)")\] is an emerging standard for JSON canonicalization. This specification will likely be updated to require such a canonical representation. Users are cautioned from depending on the [JSON literal](#dfn-json-literal) lexical representation as an [RDF literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal), as the specifics of serialization may change in a future revision of this document. + + Despite being defined as a set of strings, this value space is considered distinct from the value space of `xsd:string`, in order to avoid side effects with existing specifications. + +The lexical-to-value mapping +: maps any element of the lexical space to the result of + 1. parsing it into an internal representation consistent with \[[ECMASCRIPT](#bib-ecmascript "ECMAScript Language Specification")\] representation created by using the `JSON.parse` function as defined in [Section 24.5 The JSON Object](https://tc39.es/ecma262/#sec-json-object) of \[[ECMASCRIPT](#bib-ecmascript "ECMAScript Language Specification")\], + 2. then serializing it in the JSON format \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\] in compliance with the constraints of the value space described above. + +The canonical mapping +: maps any element of the value space to the identical string in the lexical space. + +### 10.3 The `i18n` Namespace[](#the-i18n-namespace) + +*This section is non-normative.* + +The `i18n` namespace is used for describing combinations of [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) and [base direction](#dfn-base-direction) in [RDF literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal). It is used as an alternative mechanism for describing the \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\] [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) and [base direction](#dfn-base-direction) of [RDF literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) that would otherwise use the `xsd:string` or `rdf:langString` datatypes. + +Datatypes based on this namespace allow round-tripping of JSON-LD documents using base direction, although the mechanism is not otherwise standardized. + +The [Deserialize JSON-LD to RDF Algorithm](https://www.w3.org/TR/json-ld11-api/#deserialize-json-ld-to-rdf-algorithm) can be used with the [rdfDirection](https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-rdfdirection) option set to `i18n-datatype` to generate [RDF literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) using the `i18n` base to create an IRI encoding the [base direction](#dfn-base-direction) along with optional [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) (normalized to lower case) from value objects containing `@direction` by appending to `https://www.w3.org/ns/i18n#` the value of `@language`, if any, followed by an underscore (`"_"`) followed by the value of `@direction`. + +For improved interoperability, the [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) is normalized to lower case when creating the datatype IRI. + +The following example shows two statements with literal values of `i18n:ar-EG_rtl`, which encodes the language tag `ar-EG` and the base direction `rtl`. + +``` {.turtle-dt .nohighlight content-type="text/turtle" options="rdfDirection=i18n-datatype" to-rdf=""} +@prefix ex: . +@prefix i18n: . + +# Note that this version preserves the base direction using a non-standard datatype. +[ + ex:title "HTML و CSS: تصميم و إنشاء مواقع الويب"^^i18n:ar-eg_rtl; + ex:publisher "مكتبة"^^i18n:ar-eg_rtl +] . +``` + +See [§ 4.2.4.1 Base Direction](#base-direction) for more details on using [base direction](#dfn-base-direction) for strings. + +### 10.4 The `rdf:CompoundLiteral` class and the `rdf:language` and `rdf:direction` properties[](#the-rdf-compoundliteral-class-and-the-rdf-language-and-rdf-direction-properties) + +*This section is non-normative.* + +This specification defines the `rdf:CompoundLiteral` class, which is in the domain of `rdf:language` and `rdf:direction` to be used for describing RDF literal values containing base direction and a possible language tag to be associated with the string value of `rdf:value` on the same subject. + +`rdf:CompoundLiteral` +: A class representing a compound literal. + +`rdf:language` +: An RDF [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property). The range of the property is an `rdfs:Literal`, whose value *MUST* be a well-formed \[[BCP47](#bib-bcp47 "Tags for Identifying Languages")\] [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag). The domain of the property is `rdf:CompoundLiteral`. + +`rdf:direction` +: An RDF [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property). The range of the property is an `rdfs:Literal`, whose value *MUST* be either `"ltr"` or `"rtl"`. The domain of the property is `rdf:CompoundLiteral`. + +The [Deserialize JSON-LD to RDF Algorithm](https://www.w3.org/TR/json-ld11-api/#deserialize-json-ld-to-rdf-algorithm) can be used with the [rdfDirection](https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-rdfdirection) option set to `compound-literal` to generate [RDF literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) using these properties to describe the [base direction](#dfn-base-direction) and optional [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) (normalized to lower case) from value objects containing `@direction` and optionally `@language`. + +For improved interoperability, the [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) is normalized to lower case when creating the datatype IRI. + +The following example shows two statements with compound literals representing strings with the [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) `ar-EG` and [base direction](#dfn-base-direction) `rtl`. + +``` {.turtle-dt .nohighlight content-type="text/turtle" options="rdfDirection=compound-literal" to-rdf=""} +@prefix ex: . + +# Note that this version preserves the base direction using a bnode structure. +[ + ex:title [ + rdf:value "HTML و CSS: تصميم و إنشاء مواقع الويب", + rdf:language "ar-eg", + rdf:direction "rtl" + ]; + ex:publisher [ + rdf:value "مكتبة", + rdf:language "ar-eg", + rdf:direction "rtl" + ] +] . +``` + +See [§ 4.2.4.1 Base Direction](#base-direction) for more details on using [base direction](#dfn-base-direction) for strings. + +## 11. Security Considerations[](#security) + +See, [Security Considerations](#iana-security) in [§ C. IANA Considerations](#iana-considerations). + +Note + +Future versions of this specification may incorporate subresource integrity \[[SRI](#bib-sri "Subresource Integrity")\] as a means of ensuring that cached and retrieved content matches data retrieved from remote servers; see [issue 86](https://github.com/w3c/json-ld-syntax/issues/86). + +## 12. Privacy Considerations[](#privacy) + +The retrieval of external contexts can expose the operation of a JSON-LD processor, allow intermediate nodes to fingerprint the client application through introspection of retrieved resources (see \[[fingerprinting-guidance](#bib-fingerprinting-guidance "Mitigating Browser Fingerprinting in Web Specifications")\]), and provide an opportunity for a man-in-the-middle attack. To protect against this, publishers should consider caching remote contexts for future use, or use the [documentLoader](https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-documentloader) to maintain a local version of such contexts. + +## 13. Internationalization Considerations[](#internationalization) + +As JSON-LD uses the RDF data model, it is restricted by design in its ability to properly record [JSON-LD Values](#dfn-json-ld-value) which are [strings](https://infra.spec.whatwg.org/#javascript-string) with left-to-right or right-to-left direction indicators. Both JSON-LD and RDF provide a mechanism for specifying the language associated with a string ([language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string)), but do not provide a means of indicating the [base direction](#dfn-base-direction) of the string. + +Unicode provides a mechanism for signaling direction within a string (see [Unicode Bidirectional Algorithm](https://www.unicode.org/reports/tr9/tr9-42.html) \[[UAX9](#bib-uax9 "Unicode Bidirectional Algorithm")\]), however, when a string has an overall [base direction](#dfn-base-direction) which cannot be determined by the beginning of the string, an external indicator is required, such as the \[[HTML](#bib-html "HTML Standard")\] [dir attribute](https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute), which currently has no counterpart for [RDF literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal). + +The issue of properly representing [base direction](#dfn-base-direction) in RDF is not something that this Working Group can handle, as it is a limitation or the core RDF data model. This Working Group expects that a future RDF Working Group will consider the matter and add the ability to specify the base direction of [language-tagged strings](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string). + +Until a more comprehensive solution can be addressed in a future version of this specification, publishers should consider this issue when representing strings where the [base direction](#dfn-base-direction) of the string cannot otherwise be correctly inferred based on the content of the string. See \[[string-meta](#bib-string-meta "Strings on the Web: Language and Direction Metadata")\] for a discussion best practices for identifying language and base direction for strings used on the Web. + +## A. Image Descriptions[](#image-descriptions) + +*This section is non-normative.* + +### A.1 Linked Data Dataset[](#fig-linked-data-graph-descr) + +*This section is non-normative.* + +This section describes the [Linked Data Dataset figure](#fig-linked-data-graph) in [§ 8. Data Model](#data-model). + +The image consists of three dashed boxes, each describing a different [linked data graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph). Each box consists of shapes linked with arrows describing the linked data relationships. + +The first box is titled \"default graph: \\" describes two resources: `http://example.com/people/alice` and `http://example.com/people/bob` (denoting \"Alice\" and \"Bob\" respectively), which are connected by an arrow labeled `schema:knows` which describes the knows relationship between the two resources. Additionally, the \"Alice\" resource is related to three different literals: + +Alice +: an RDF literal with no datatype or language. + +weiblich \| de +: an language-tagged string with the value \"weiblich\" and [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) \"de\". + +female \| en +: an language-tagged string with the value \"female\" and [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) \"en\". + +The second and third boxes describe two [named graphs](https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph), with the graph names \"http://example.com/graphs/1\" and \"http://example.com/graphs/1\", respectively. + +The second box consists of two resources: `http://example.com/people/alice` and `http://example.com/people/bob` related by the `schema:parent` relationship, and names the `http://example.com/people/bob` \"Bob\". + +The third box consists of two resources, one named `http://example.com/people/bob` and the other unnamed. The two resources related to each other using `schema:sibling` relationship with the second named \"Mary\". + +## B. Relationship to Other Linked Data Formats[](#relationship-to-other-linked-data-formats) + +*This section is non-normative.* + +The JSON-LD examples below demonstrate how JSON-LD can be used to express semantic data marked up in other linked data formats such as Turtle, RDFa, and Microdata. These sections are merely provided as evidence that JSON-LD is very flexible in what it can express across different Linked Data approaches. + +### B.1 Turtle[](#turtle) + +*This section is non-normative.* + +The following are examples of transforming RDF expressed in \[[Turtle](#bib-turtle "RDF 1.1 Turtle")\] into JSON-LD. + +#### B.1.1 Prefix definitions[](#prefix-definitions) + +The JSON-LD context has direct equivalents for the Turtle `@prefix` declaration: + +[Example 154](#example-154-a-set-of-statements-serialized-in-turtle): A set of statements serialized in Turtle + +``` {content-type="text/turtle" result-for="The same set of statements serialized in JSON-LD" to-rdf="" aria-busy="false"} +@prefix foaf: . + + a foaf:Person; + foaf:name "Manu Sporny"; + foaf:homepage . +``` + +[Example 155](#example-155-the-same-set-of-statements-serialized-in-json-ld): The same set of statements serialized in JSON-LD + +``` {aria-busy="false"} +{ + "@context": { + "foaf": "http://xmlns.com/foaf/0.1/" + }, + "@id": "http://manu.sporny.org/about#manu", + "@type": "foaf:Person", + "foaf:name": "Manu Sporny", + "foaf:homepage": { "@id": "http://manu.sporny.org/" } +} +``` + +#### B.1.2 Embedding[](#embedding-0) + +Both \[[Turtle](#bib-turtle "RDF 1.1 Turtle")\] and JSON-LD allow embedding, although \[[Turtle](#bib-turtle "RDF 1.1 Turtle")\] only allows embedding of [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). + +[Example 156](#example-156-embedding-in-turtle): Embedding in Turtle + +``` {content-type="text/turtle" to-rdf="" result-for="Same embedding example in JSON-LD" aria-busy="false"} +@prefix foaf: . + + + a foaf:Person; + foaf:name "Manu Sporny"; + foaf:knows [ a foaf:Person; foaf:name "Gregg Kellogg" ] . +``` + +[Example 157](#example-157-same-embedding-example-in-json-ld): Same embedding example in JSON-LD + +``` {aria-busy="false"} +{ + "@context": { + "foaf": "http://xmlns.com/foaf/0.1/" + }, + "@id": "http://manu.sporny.org/about#manu", + "@type": "foaf:Person", + "foaf:name": "Manu Sporny", + "foaf:knows": { + "@type": "foaf:Person", + "foaf:name": "Gregg Kellogg" + } +} +``` + +#### B.1.3 Conversion of native data types[](#conversion-of-native-data-types) + +In JSON-LD numbers and boolean values are native data types. While \[[Turtle](#bib-turtle "RDF 1.1 Turtle")\] has a shorthand syntax to express such values, RDF\'s abstract syntax requires that numbers and boolean values are represented as typed literals. Thus, to allow full round-tripping, the JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\] defines conversion rules between JSON-LD\'s native data types and RDF\'s counterparts. [Numbers](https://tc39.es/ecma262/#sec-terms-and-definitions-number-value) without fractions are converted to `xsd:integer`-typed literals, numbers with fractions to `xsd:double`-typed literals and the two boolean values `true` and `false` to a `xsd:boolean`-typed literal. All typed literals are in canonical lexical form. + +[Example 158](#example-158-json-ld-using-native-data-types-for-numbers-and-boolean-values): JSON-LD using native data types for numbers and boolean values + +``` {aria-busy="false"} +{ + "@context": { + "ex": "http://example.com/vocab#" + }, + "@id": "http://example.com/", + "ex:numbers": [ 14, 2.78 ], + "ex:booleans": [ true, false ] +} +``` + +[Example 159](#example-159-same-example-in-turtle-using-typed-literals): Same example in Turtle using typed literals + +``` {content-type="text/turtle" result-for="JSON-LD using native data types for numbers and boolean values" to-rdf="" aria-busy="false"} +@prefix ex: . +@prefix xsd: . + + + ex:numbers "14"^^xsd:integer, "2.78E0"^^xsd:double ; + ex:booleans "true"^^xsd:boolean, "false"^^xsd:boolean . +``` + +Note + +Note that this interpretation differs from \[[Turtle](#bib-turtle "RDF 1.1 Turtle")\], in which the literal `2.78` translates to an `xsd:decimal`. The rationale is that most JSON tools parse numbers with fractions as *floating point numbers*, so `xsd:double` is the most appropriate datatype to render them back in RDF. + +#### B.1.4 Lists[](#lists-0) + +Both JSON-LD and \[[Turtle](#bib-turtle "RDF 1.1 Turtle")\] can represent sequential lists of values. + +[Example 160](#example-160-a-list-of-values-in-turtle): A list of values in Turtle + +``` {content-type="text/turtle" to-rdf="" result-for="Same example with a list of values in JSON-LD" aria-busy="false"} +@prefix foaf: . + + a foaf:Person; + foaf:name "Joe Bob"; + foaf:nick ( "joe" "bob" "jaybee" ) . +``` + +[Example 161](#example-161-same-example-with-a-list-of-values-in-json-ld): Same example with a list of values in JSON-LD + +``` {aria-busy="false"} +{ + "@context": { + "foaf": "http://xmlns.com/foaf/0.1/" + }, + "@id": "http://example.org/people#joebob", + "@type": "foaf:Person", + "foaf:name": "Joe Bob", + "foaf:nick": { + "@list": [ "joe", "bob", "jaybee" ] + } +} +``` + +### B.2 RDFa[](#rdfa) + +*This section is non-normative.* + +The following example describes three people with their respective names and homepages in RDFa \[[RDFA-CORE](#bib-rdfa-core "RDFa Core 1.1 - Third Edition")\]. + +[Example 162](#example-162-rdfa-fragment-that-describes-three-people): RDFa fragment that describes three people + +``` {.nohighlight content-type="text/html" to-rdf="" result-for="Same description in JSON-LD (context shared among node objects)"} +
+ +
+``` + +An example JSON-LD implementation using a single [context](#dfn-context) is described below. + +[Example 163](#example-163-same-description-in-json-ld-context-shared-among-node-objects): Same description in JSON-LD (context shared among node objects) + +``` {aria-busy="false"} +{ + "@context": { + "foaf": "http://xmlns.com/foaf/0.1/", + "foaf:homepage": {"@type": "@id"} + }, + "@graph": [ + { + "@type": "foaf:Person", + "foaf:homepage": "http://example.com/bob/", + "foaf:name": "Bob" + }, { + "@type": "foaf:Person", + "foaf:homepage": "http://example.com/eve/", + "foaf:name": "Eve" + }, { + "@type": "foaf:Person", + "foaf:homepage": "http://example.com/manu/", + "foaf:name": "Manu" + } + ] +} +``` + +### B.3 Microdata[](#microdata) + +*This section is non-normative.* + +The HTML Microdata \[[MICRODATA](#bib-microdata "HTML Microdata")\] example below expresses book information as a Microdata Work item. + +[Example 164](#example-164-html-that-describes-a-book-using-microdata): HTML that describes a book using microdata + +``` {content-type="text/html" result-for="Same book description in JSON-LD (avoiding contexts)" to-rdf="" aria-busy="false"} +
+
Title
+
Just a Geek
+
By
+
Wil Wheaton
+
Format
+
+ + Print +
+
+ + Ebook +
+
+``` + +Note that the JSON-LD representation of the Microdata information stays true to the desires of the Microdata community to avoid contexts and instead refer to items by their full [IRI](https://tools.ietf.org/html/rfc3987#section-2). + +[Example 165](#example-165-same-book-description-in-json-ld-avoiding-contexts): Same book description in JSON-LD (avoiding contexts) + +``` {aria-busy="false"} +[ + { + "@id": "http://purl.oreilly.com/works/45U8QJGZSQKDH8N", + "@type": "http://purl.org/vocab/frbr/core#Work", + "http://purl.org/dc/elements/1.1/title": "Just a Geek", + "http://purl.org/dc/elements/1.1/creator": "Wil Wheaton", + "http://purl.org/vocab/frbr/core#realization": + [ + {"@id": "http://purl.oreilly.com/products/9780596007683.BOOK"}, + {"@id": "http://purl.oreilly.com/products/9780596802189.EBOOK"} + ] + }, { + "@id": "http://purl.oreilly.com/products/9780596007683.BOOK", + "@type": "http://purl.org/vocab/frbr/core#Expression", + "http://purl.org/dc/elements/1.1/type": {"@id": "http://purl.oreilly.com/product-types/BOOK"} + }, { + "@id": "http://purl.oreilly.com/products/9780596802189.EBOOK", + "@type": "http://purl.org/vocab/frbr/core#Expression", + "http://purl.org/dc/elements/1.1/type": {"@id": "http://purl.oreilly.com/product-types/EBOOK"} + } +] +``` + +## C. IANA Considerations[](#iana-considerations) + +This section has been submitted to the Internet Engineering Steering Group (IESG) for review, approval, and registration with IANA. + +### application/ld+json[](#iana-considerations) + +Type name: +: application + +Subtype name: +: ld+json + +Required parameters: +: N/A + +Optional parameters: + +: + + `profile` + + : A non-empty list of space-separated URIs identifying specific constraints or conventions that apply to a JSON-LD document according to \[[RFC6906](#bib-rfc6906 "The 'profile' Link Relation Type")\]. A profile does not change the semantics of the resource representation when processed without profile knowledge, so that clients both with and without knowledge of a profiled resource can safely use the same representation. The `profile` parameter *MAY* be used by clients to express their preferences in the content negotiation process. If the profile parameter is given, a server *SHOULD* return a document that honors the profiles in the list which it recognizes, and *MUST* ignore the profiles in the list which it does not recognize. It is *RECOMMENDED* that profile URIs are dereferenceable and provide useful documentation at that URI. For more information and background please refer to \[[RFC6906](#bib-rfc6906 "The 'profile' Link Relation Type")\]. + + This specification defines six values for the `profile` parameter. + + `http://www.w3.org/ns/json-ld#expanded` + : To request or specify [expanded JSON-LD document form](#dfn-expanded-document-form). + + `http://www.w3.org/ns/json-ld#compacted` + : To request or specify [compacted JSON-LD document form](#dfn-compacted-document-form). + + `http://www.w3.org/ns/json-ld#context` + : To request or specify a [JSON-LD context document](#dfn-context-document). + + `http://www.w3.org/ns/json-ld#flattened` + : To request or specify [flattened JSON-LD document form](#dfn-flattened-document-form). + + `http://www.w3.org/ns/json-ld#frame` + : To request or specify a [JSON-LD frame document](https://www.w3.org/TR/json-ld11-framing/#dfn-frame). + + `http://www.w3.org/ns/json-ld#framed` + : To request or specify [framed JSON-LD document form](#dfn-framed-document-form). + + All other URIs starting with `http://www.w3.org/ns/json-ld` are reserved for future use by JSON-LD specifications. + + Other specifications may publish additional `profile` parameter URIs with their own defined semantics. This includes the ability to associate a file extension with a `profile` parameter. + + When used as a [media type parameter](https://tools.ietf.org/html/rfc4288#section-4.3) \[[RFC4288](#bib-rfc4288 "Media Type Specifications and Registration Procedures")\] in an [HTTP Accept header](https://httpwg.org/specs/rfc7231.html#rfc.section.5.3.2) \[[RFC7231](#bib-rfc7231 "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content")\], the value of the `profile` parameter *MUST* be enclosed in quotes (`"`) if it contains special characters such as whitespace, which is required when multiple profile URIs are combined. + + When processing the \"profile\" media type parameter, it is important to note that its value contains one or more URIs and not IRIs. In some cases it might therefore be necessary to convert between IRIs and URIs as specified in [section 3 Relationship between IRIs and URIs](https://tools.ietf.org/html/rfc3986#section-5.1) of \[[RFC3987](#bib-rfc3987 "Internationalized Resource Identifiers (IRIs)")\]. + +Encoding considerations: +: See [RFC 8259, section 11](https://tools.ietf.org/html/rfc8259#section-11). + +Security considerations: + +: See [RFC 8259, section 12](https://tools.ietf.org/html/rfc8259#section-12) \[[RFC8259](#bib-rfc8259 "The JavaScript Object Notation (JSON) Data Interchange Format")\] + + Since JSON-LD is intended to be a pure data exchange format for directed graphs, the serialization *SHOULD NOT* be passed through a code execution mechanism such as JavaScript\'s `eval()` function to be parsed. An (invalid) document may contain code that, when executed, could lead to unexpected side effects compromising the security of a system. + + When processing JSON-LD documents, links to remote contexts and frames are typically followed automatically, resulting in the transfer of files without the explicit request of the user for each one. If remote contexts are served by third parties, it may allow them to gather usage patterns or similar information leading to privacy concerns. Specific implementations, such as the API defined in the JSON-LD 1.1 Processing Algorithms and API specification \[[JSON-LD11-API](#bib-json-ld11-api "JSON-LD 1.1 Processing Algorithms and API")\], may provide fine-grained mechanisms to control this behavior. + + JSON-LD contexts that are loaded from the Web over non-secure connections, such as HTTP, run the risk of being altered by an attacker such that they may modify the JSON-LD [active context](#dfn-active-context) in a way that could compromise security. It is advised that any application that depends on a remote context for mission critical purposes vet and cache the remote context before allowing the system to use it. + + Given that JSON-LD allows the substitution of long IRIs with short terms, JSON-LD documents may expand considerably when processed and, in the worst case, the resulting data might consume all of the recipient\'s resources. Applications should treat any data with due skepticism. + + As JSON-LD places no limits on the IRI schemes that may be used, and vocabulary-relative IRIs use string concatenation rather than IRI resolution, it is possible to construct IRIs that may be used maliciously, if dereferenced. + +Interoperability considerations: +: Not Applicable + +Published specification: +: http://www.w3.org/TR/json-ld + +Applications that use this media type: +: Any programming environment that requires the exchange of directed graphs. Implementations of JSON-LD have been created for JavaScript, Python, Ruby, PHP, and C++. + +Additional information: + +: + + Magic number(s): + : Not Applicable + + File extension(s): + : .jsonld + + Macintosh file type code(s): + : TEXT + +Person & email address to contact for further information: +: Ivan Herman \ + +Intended usage: +: Common + +Restrictions on usage: +: N/A + +Author(s): +: Manu Sporny, Dave Longley, Gregg Kellogg, Markus Lanthaler, Niklas Lindström + +Change controller: +: W3C + +Fragment identifiers used with [application/ld+json](#application-ld-json) are treated as in RDF syntaxes, as per [RDF 1.1 Concepts and Abstract Syntax](https://www.w3.org/TR/rdf11-concepts/#section-fragID) \[[RDF11-CONCEPTS](#bib-rdf11-concepts "RDF 1.1 Concepts and Abstract Syntax")\]. + +This registration is an update to the original definition for [application/ld+json](https://www.w3.org/TR/2014/REC-json-ld-20140116/#application-ld-json) in \[[JSON-LD10](#bib-json-ld10 "JSON-LD 1.0")\]. + +### C.1 Examples[](#iana-examples) + +*This section is non-normative.* + +The following examples illustrate different ways in which the profile parameter may be used to describe different acceptable responses. + +[Example 166](#example-166-http-request-with-profile-requesting-an-expanded-document): HTTP Request with profile requesting an expanded document + +``` {content-type="http" ignore="" aria-busy="false"} +GET /ordinary-json-document.json HTTP/1.1 +Host: example.com +Accept: application/ld+json;profile=http://www.w3.org/ns/json-ld#expanded +``` + +Requests the server to return the requested resource as JSON-LD in [expanded document form](#dfn-expanded-document-form). + +[Example 167](#example-167-http-request-with-profile-requesting-a-compacted-document): HTTP Request with profile requesting a compacted document + +``` {content-type="http" ignore="" aria-busy="false"} +GET /ordinary-json-document.json HTTP/1.1 +Host: example.com +Accept: application/ld+json;profile=http://www.w3.org/ns/json-ld#compacted +``` + +Requests the server to return the requested resource as JSON-LD in [compacted document form](#dfn-compacted-document-form). As no explicit context resource is specified, the server compacts using an application-specific default context. + +[Example 168](#example-168-http-request-with-profile-requesting-a-compacted-document-with-a-reference-to-a-compaction-context): HTTP Request with profile requesting a compacted document with a reference to a compaction context + +``` {content-type="http" ignore="" aria-busy="false"} +GET /ordinary-json-document.json HTTP/1.1 +Host: example.com +Accept: application/ld+json;profile="http://www.w3.org/ns/json-ld#flattened http://www.w3.org/ns/json-ld#compacted" +``` + +Requests the server to return the requested resource as JSON-LD in both [compacted document form](#dfn-compacted-document-form) and [flattened document form](#dfn-flattened-document-form). Note that as whitespace is used to separate the two URIs, they are enclosed in double quotes (`"`). + +## D. Open Issues[](#open-issues) + +*This section is non-normative.* + +The following is a list of issues open at the time of publication. + +[Issue 108](https://github.com/w3c/json-ld-syntax/issues/108): Consider context by reference with metadata [defer-future-version](https://github.com/w3c/json-ld-syntax/issues/?q=is%3Aissue+is%3Aopen+label%3A%22defer-future-version%22)[privacy-tracker](https://github.com/w3c/json-ld-syntax/issues/?q=is%3Aissue+is%3Aopen+label%3A%22privacy-tracker%22)[security-tracker](https://github.com/w3c/json-ld-syntax/issues/?q=is%3Aissue+is%3Aopen+label%3A%22security-tracker%22) + +Consider context by reference with metadata. + +[Issue 191](https://github.com/w3c/json-ld-syntax/issues/191): Compact IRI expansion support for non-trivial prefix term definitions [defer-future-version](https://github.com/w3c/json-ld-syntax/issues/?q=is%3Aissue+is%3Aopen+label%3A%22defer-future-version%22)[spec:enhancement](https://github.com/w3c/json-ld-syntax/issues/?q=is%3Aissue+is%3Aopen+label%3A%22spec%3Aenhancement%22) + +Compact IRI expansion support for non-trivial prefix term definitions. + +[Issue 280](https://github.com/w3c/json-ld-syntax/issues/280): language-maps don\'t allow separate base direction [defer-future-version](https://github.com/w3c/json-ld-syntax/issues/?q=is%3Aissue+is%3Aopen+label%3A%22defer-future-version%22) + +Language-maps don\'t allow separate base direction. + +[Issue 328](https://github.com/w3c/json-ld-syntax/issues/328): \@default in \@context in JSON-LD core syntax [defer-future-version](https://github.com/w3c/json-ld-syntax/issues/?q=is%3Aissue+is%3Aopen+label%3A%22defer-future-version%22) + +`@default` in `@context` in JSON-LD core syntax. + +[Issue 329](https://github.com/w3c/json-ld-syntax/issues/329): Suggestion about \`@prefix\` [defer-future-version](https://github.com/w3c/json-ld-syntax/issues/?q=is%3Aissue+is%3Aopen+label%3A%22defer-future-version%22) + +Suggestion about `@prefix`. + +[Issue 335](https://github.com/w3c/json-ld-syntax/issues/335): Type Coercion / Node Conversion: \@coerce keyword or similar [defer-future-version](https://github.com/w3c/json-ld-syntax/issues/?q=is%3Aissue+is%3Aopen+label%3A%22defer-future-version%22) + +Type Coercion / Node Conversion: \@coerce keyword or similar. + +## E. Changes since 1.0 Recommendation of 16 January 2014[](#changes-from-10) + +*This section is non-normative.* + +- A context may contain a `@version` [entry](https://infra.spec.whatwg.org/#map-entry) which is used to set the [processing mode](#dfn-processing-mode). +- An [expanded term definition](#dfn-expanded-term-definition) can now have an `@context` property, which defines a [context](#dfn-context) used for values of a [property](https://www.w3.org/TR/rdf11-concepts/#dfn-property) identified with such a [term](#dfn-term). +- `@container` values within an [expanded term definition](#dfn-expanded-term-definition) may now include `@id`, `@graph` and `@type`, corresponding to [id maps](#dfn-id-map) and [type maps](#dfn-type-map). +- An [expanded term definition](#dfn-expanded-term-definition) can now have an `@nest` property, which identifies a term expanding to `@nest` which is used for containing properties using the same `@nest` mapping. When expanding, the values of a property expanding to `@nest` are treated as if they were contained within the enclosing [node object](#dfn-node-object) directly. +- The JSON syntax has been abstracted into an [internal representation](https://www.w3.org/TR/json-ld11-api/#dfn-internal-representation) to allow for other serializations that are functionally equivalent to JSON. +- Added [§ 4.6.3 Node Identifier Indexing](#node-identifier-indexing) and [§ 4.6.4 Node Type Indexing](#node-type-indexing). +- Both [language maps](#dfn-language-map) and [index maps](#dfn-index-map) may legitimately have an `@none` key, but [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/) only allowed [string](https://infra.spec.whatwg.org/#javascript-string) keys. This has been updated to allow `@none` keys. +- The value for `@container` in an [expanded term definition](#dfn-expanded-term-definition) can also be an [array](https://infra.spec.whatwg.org/#list) containing any appropriate container keyword along with `@set` (other than `@list`). This allows a way to ensure that such property values will always be expressed in [array](https://infra.spec.whatwg.org/#list) form. +- In JSON-LD 1.1, terms will be chosen as [compact IRI](#dfn-compact-iri) prefixes when compacting only if a [simple term definition](#dfn-simple-term-definition) is used where the value ends with a URI [gen-delim](https://tools.ietf.org/html/rfc3986#section-2.2) character, or if their [expanded term definition](#dfn-expanded-term-definition) contains a `@prefix` [entry](https://infra.spec.whatwg.org/#map-entry) with the value `true`. The 1.0 algorithm has been updated to only consider terms that map to a value that ends with a URI [gen-delim](https://tools.ietf.org/html/rfc3986#section-2.2) character. +- Values of properties where the associated [term definition](#dfn-term-definition) has `@container` set to `@graph` are interpreted as [implicitly named graphs](#dfn-implicitly-named-graph), where the associated graph name is assigned from a new [blank node identifier](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier). Other combinations include `["@container", "@id"]`, `["@container", "@index"]` each also may include `"@set"`, which create maps from the graph identifier or index value similar to [index maps](#dfn-index-map) and [id maps](#dfn-id-map). + +Additionally, see [§ F. Changes since JSON-LD Community Group Final Report](#changes-from-cg). + +## F. Changes since JSON-LD Community Group Final Report[](#changes-from-cg) + +*This section is non-normative.* + +- [Lists](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab) may now have items which are themselves [lists](https://www.w3.org/TR/rdf-schema/#ch_collectionvocab). +- Values of `@type`, or an alias of `@type`, may now have their `@container` set to `@set` to ensure that `@type` [entries](https://infra.spec.whatwg.org/#map-entry) are always represented as an array. This also allows a term to be defined for `@type`, where the value *MUST* be a [map](https://infra.spec.whatwg.org/#ordered-map) with `@container` set to `@set`. +- The use of [blank node identifiers](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier) to label properties is obsolete, and may be removed in a future version of JSON-LD, as is the support for [generalized RDF Datasets](https://www.w3.org/TR/rdf11-concepts/#dfn-generalized-rdf-dataset). +- The [vocabulary mapping](#dfn-vocabulary-mapping) can be a [relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5), which is evaluated either against an existing default vocabulary, or against the document base. This allows vocabulary-relative IRIs, such as the keys of [node objects](#dfn-node-object), are expanded or compacted relative to the document base. (See [Security Considerations](#iana-security) in [§ C. IANA Considerations](#iana-considerations) for a discussion on how string vocabulary-relative IRI resolution via concatenation. ) +- Added support for `"@type": "@none"` in a [term definition](#dfn-term-definition) to prevent value compaction. Define the `rdf:JSON` datatype. +- [Term definitions](#dfn-term-definition) with keys which are of the form of an [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3) or a [compact IRI](#dfn-compact-iri) *MUST NOT* expand to an [IRI](https://tools.ietf.org/html/rfc3987#section-2) other than the expansion of the key itself. +- A [frame](https://www.w3.org/TR/json-ld11-framing/#dfn-frame) may also be located within an HTML document, identified using type `application/ld+json;profile=http://www.w3.org/ns/json-ld#frame`. +- Term definitions can now be [protected](#protected-term-definitions), to limit the ability of other contexts to override them. +- A [context](#dfn-context) defined in an [expanded term definition](#dfn-expanded-term-definition) may also be used for values of `@type`, which defines a [context](#dfn-context) to use for [node objects](#dfn-node-object) including the associated type. +- By default, all contexts are propagated when traversing [node objects](#dfn-node-object), other than [type-scoped contexts](#dfn-type-scoped-context). This can be controlled using the `@propagate` [entry](https://infra.spec.whatwg.org/#map-entry) in a [local context](#dfn-local-context). +- A context may contain an `@import` [entry](https://infra.spec.whatwg.org/#map-entry) used to reference a remote context within a context, allowing `JSON-LD 1.1` features to be added to contexts originally authored for `JSON-LD 1.0`. +- A [node object](#dfn-node-object) may include an [included block](#dfn-included-block), which is used to contain a set of [node objects](#dfn-node-object) which are treated exactly as if they were [node objects](#dfn-node-object) defined in an [array](https://infra.spec.whatwg.org/#list) including the containing [node object](#dfn-node-object). This allows the use of the object form of a JSON-LD document when there is more than one [node object](#dfn-node-object) being defined, and where those [node objects](#dfn-node-object) are not embedded as values of the containing [node object](#dfn-node-object). +- The `alternate` link relation can be used to supply an alternate location for retrieving a JSON-LD document when the returned document is not JSON. +- [Value objects](#dfn-value-object), and associated [context](#dfn-context) and [term definitions](#dfn-term-definition) have been updated to support `@direction` for setting the [base direction](#dfn-base-direction) of strings. +- The [processing mode](#dfn-processing-mode) is now implicitly `json-ld-1.1`, unless set explicitly to `json-ld-1.0`. +- Improve notation using [IRI](https://tools.ietf.org/html/rfc3987#section-2), [IRI reference](https://tools.ietf.org/html/rfc3987#section-1.3), and [relative IRI reference](https://tools.ietf.org/html/rfc3987#section-6.5). +- Warn about forward-compatibility issues for terms of the form (`"@"1*ALPHA`). +- When creating an `i18n` datatype or `rdf:CompoundLiteral`, [language tags](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) are normalized to lower case to improve interoperability between implementations. + +## G. Changes since Candidate Release of 12 December 2019[](#changes-from-cr) + +*This section is non-normative.* + +- Expand [§ 4.1.5 Compact IRIs](#compact-iris) to describe the behavior of `"@prefix": false` for [compact IRIs](#dfn-compact-iri), and to note that this affects both expansion of [compact IRIs](#dfn-compact-iri) and compaction of [IRIs](https://tools.ietf.org/html/rfc3987#section-2) to [compact IRIs](#dfn-compact-iri). +- Adding a missing normative definition of the `@index` keyword used within an [expanded term definition](#dfn-expanded-term-definition) to [§ 9.15.1 Expanded term definition](#expanded-term-definition). +- Changed normative definition of the `rdf:JSON` datatype in [§ 10.2 The `rdf:JSON` Datatype](#the-rdf-json-datatype) to describe a normative canonicalization. This is in response to [Issue 323](https://github.com/w3c/json-ld-syntax/issues/323). +- Updated the non-normative definitions of the `i18n` based datatype in [§ 10.3 The `i18n` Namespace](#the-i18n-namespace) and `rdf:CompoundLiteral` class in [§ 10.4 The `rdf:CompoundLiteral` class and the `rdf:language` and `rdf:direction` properties](#the-rdf-compoundliteral-class-and-the-rdf-language-and-rdf-direction-properties) to normalize language tags to lowercase when generating RDF. + +## H. Changes since Proposed Recommendation Release of 7 May 2020[](#changes-from-pr) + +*This section is non-normative.* + +- Removed remaining \"at-risk\" notes. +- Update bibliographic reference for JCS to \[[RFC8785](#bib-rfc8785 "JSON Canonicalization Scheme (JCS)")\]. +- Fixed typo in [§ 9.3 Frame Objects](#frame-objects), which was unintentionally diverging from the normative description of the `@embed` keyword in [JSON-LD 1.1 Framing](https://www.w3.org/TR/json-ld11-framing/). This is in response to [Issue 358](https://github.com/w3c/json-ld-syntax/issues/358). + +## I. Acknowledgements[](#ack) + +*This section is non-normative.* + +The editors would like to specially thank the following individuals for making significant contributions to the authoring and editing of this specification: + +- Timothy Cole (University of Illinois at Urbana-Champaign) +- Gregory Todd Williams (J. Paul Getty Trust) +- Ivan Herman (W3C Staff) +- Jeff Mixter (OCLC (Online Computer Library Center, Inc.)) +- David Lehn (Digital Bazaar) +- David Newbury (J. Paul Getty Trust) +- Robert Sanderson (J. Paul Getty Trust, chair) +- Harold Solbrig (Johns Hopkins Institute for Clinical and Translational Research) +- Simon Steyskal (WU (Wirschaftsuniversität Wien) - Vienna University of Economics and Business) +- A Soroka (Apache Software Foundation) +- Ruben Taelman (Imec vzw) +- Benjamin Young (Wiley, chair) + +Additionally, the following people were members of the Working Group at the time of publication: + +- Steve Blackmon (Apache Software Foundation) +- Dan Brickley (Google, Inc.) +- Newton Calegari (NIC.br - Brazilian Network Information Center) +- Victor Charpenay (Siemens AG) +- Sebastian Käbisch (Siemens AG) +- Axel Polleres (WU (Wirschaftsuniversität Wien) - Vienna University of Economics and Business) +- Leonard Rosenthol (Adobe) +- Jean-Yves ROSSI (CANTON CONSULTING) +- Antoine Roulin (CANTON CONSULTING) +- Manu Sporny (Digital Bazaar) +- Clément Warnier de Wailly (CANTON CONSULTING) + +A large amount of thanks goes out to the [JSON-LD Community Group](https://www.w3.org/community/json-ld/) participants who worked through many of the technical issues on the mailing list and the weekly telecons: Chris Webber, David Wood, Drummond Reed, Eleanor Joslin, Fabien Gandon, Herm Fisher, Jamie Pitts, Kim Hamilton Duffy, Niklas Lindström, Paolo Ciccarese, Paul Frazze, Paul Warren, Reto Gmür, Rob Trainer, Ted Thibodeau Jr., and Victor Charpenay. + +## J. References[](#references) + +### J.1 Normative references [](#normative-references) + +\[BCP47\] +: [Tags for Identifying Languages](https://tools.ietf.org/html/bcp47). A. Phillips; M. Davis. IETF. September 2009. IETF Best Current Practice. URL: + +\[DOM\] +: [DOM Standard](https://dom.spec.whatwg.org/). Anne van Kesteren. WHATWG. Living Standard. URL: + +\[ECMASCRIPT\] +: [ECMAScript Language Specification](https://tc39.es/ecma262/). Ecma International. URL: + +\[HTML\] +: [HTML Standard](https://html.spec.whatwg.org/multipage/). Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: + +\[IANA-URI-SCHEMES\] +: [Uniform Resource Identifier (URI) Schemes](https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml). IANA. URL: + +\[JSON\] +: [The application/json Media Type for JavaScript Object Notation (JSON)](https://tools.ietf.org/html/rfc4627). D. Crockford. IETF. July 2006. Informational. URL: + +\[JSON-LD10\] +: [JSON-LD 1.0](https://www.w3.org/TR/2014/REC-json-ld-20140116/). Manu Sporny; Gregg Kellogg; Marcus Langhaler. W3C. 16 January 2014. W3C Recommendation. URL: + +\[JSON-LD11-API\] +: [JSON-LD 1.1 Processing Algorithms and API](https://www.w3.org/TR/json-ld11-api/). Gregg Kellogg; Dave Longley; Pierre-Antoine Champin. W3C. 7 May 2020. W3C Proposed Recommendation. URL: + +\[JSON-LD11-FRAMING\] +: [JSON-LD 1.1 Framing](https://www.w3.org/TR/json-ld11-framing/). Dave Longley; Gregg Kellogg; Pierre-Antoine Champin. W3C. 7 May 2020. W3C Proposed Recommendation. URL: + +\[RDF-SCHEMA\] +: [RDF Schema 1.1](https://www.w3.org/TR/rdf-schema/). Dan Brickley; Ramanathan Guha. W3C. 25 February 2014. W3C Recommendation. URL: + +\[RDF11-CONCEPTS\] +: [RDF 1.1 Concepts and Abstract Syntax](https://www.w3.org/TR/rdf11-concepts/). Richard Cyganiak; David Wood; Markus Lanthaler. W3C. 25 February 2014. W3C Recommendation. URL: + +\[RDF11-MT\] +: [RDF 1.1 Semantics](https://www.w3.org/TR/rdf11-mt/). Patrick Hayes; Peter Patel-Schneider. W3C. 25 February 2014. W3C Recommendation. URL: + +\[RFC2119\] +: [Key words for use in RFCs to Indicate Requirement Levels](https://tools.ietf.org/html/rfc2119). S. Bradner. IETF. March 1997. Best Current Practice. URL: + +\[RFC3986\] +: [Uniform Resource Identifier (URI): Generic Syntax](https://tools.ietf.org/html/rfc3986). T. Berners-Lee; R. Fielding; L. Masinter. IETF. January 2005. Internet Standard. URL: + +\[RFC3987\] +: [Internationalized Resource Identifiers (IRIs)](https://tools.ietf.org/html/rfc3987). M. Duerst; M. Suignard. IETF. January 2005. Proposed Standard. URL: + +\[RFC4288\] +: [Media Type Specifications and Registration Procedures](https://tools.ietf.org/html/rfc4288). N. Freed; J. Klensin. IETF. December 2005. Best Current Practice. URL: + +\[RFC5234\] +: [Augmented BNF for Syntax Specifications: ABNF](https://tools.ietf.org/html/rfc5234). D. Crocker, Ed.; P. Overell. IETF. January 2008. Internet Standard. URL: + +\[RFC6839\] +: [Additional Media Type Structured Syntax Suffixes](https://tools.ietf.org/html/rfc6839). T. Hansen; A. Melnikov. IETF. January 2013. Informational. URL: + +\[RFC6906\] +: [The \'profile\' Link Relation Type](https://tools.ietf.org/html/rfc6906). E. Wilde. IETF. March 2013. Informational. URL: + +\[RFC7231\] +: [Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content](https://tools.ietf.org/html/rfc7231). R. Fielding, Ed.; J. Reschke, Ed. June 2014. Proposed Standard. URL: + +\[RFC8174\] +: [Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words](https://tools.ietf.org/html/rfc8174). B. Leiba. IETF. May 2017. Best Current Practice. URL: + +\[RFC8259\] +: [The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc8259). T. Bray, Ed.. IETF. December 2017. Internet Standard. URL: + +\[RFC8288\] +: [Web Linking](https://tools.ietf.org/html/rfc8288). M. Nottingham. October 2017. Proposed Standard. URL: + +\[UAX9\] +: [Unicode Bidirectional Algorithm](https://www.unicode.org/reports/tr9/tr9-42.html). Mark Davis; Aharon Lanin; Andrew Glass. Unicode Consortium. 12 February 2020. Unicode Standard Annex #9. URL: + +\[UNICODE\] +: [The Unicode Standard](https://www.unicode.org/versions/latest/). Unicode Consortium. URL: + +### J.2 Informative references [](#informative-references) + +\[fingerprinting-guidance\] +: [Mitigating Browser Fingerprinting in Web Specifications](https://www.w3.org/TR/fingerprinting-guidance/). Nick Doty. W3C. 28 March 2019. W3C Note. URL: + +\[INFRA\] +: [Infra Standard](https://infra.spec.whatwg.org/). Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: + +\[JSON.API\] +: [JSON API](https://jsonapi.org/format/). Steve Klabnik; Yehuda Katz; Dan Gebhardt; Tyler Kellen; Ethan Resnick. 29 May 2015. unofficial. URL: + +\[ld-glossary\] +: [Linked Data Glossary](https://www.w3.org/TR/ld-glossary/). Bernadette Hyland; Ghislain Auguste Atemezing; Michael Pendleton; Biplav Srivastava. W3C. 27 June 2013. W3C Note. URL: + +\[LINKED-DATA\] +: [Linked Data Design Issues](https://www.w3.org/DesignIssues/LinkedData.html). Tim Berners-Lee. W3C. 27 July 2006. W3C-Internal Document. URL: + +\[MICRODATA\] +: [HTML Microdata](https://www.w3.org/TR/microdata/). Charles \'chaals\' (McCathie) Nevile; Dan Brickley; Ian Hickson. W3C. 26 April 2018. W3C Working Draft. URL: + +\[RDFA-CORE\] +: [RDFa Core 1.1 - Third Edition](https://www.w3.org/TR/rdfa-core/). Ben Adida; Mark Birbeck; Shane McCarron; Ivan Herman et al. W3C. 17 March 2015. W3C Recommendation. URL: + +\[rfc4122\] +: [A Universally Unique IDentifier (UUID) URN Namespace](https://tools.ietf.org/html/rfc4122). P. Leach; M. Mealling; R. Salz. IETF. July 2005. Proposed Standard. URL: + +\[RFC7049\] +: [Concise Binary Object Representation (CBOR)](https://tools.ietf.org/html/rfc7049). C. Bormann; P. Hoffman. IETF. October 2013. Proposed Standard. URL: + +\[RFC7946\] +: [The GeoJSON Format](https://tools.ietf.org/html/rfc7946). H. Butler; M. Daly; A. Doyle; S. Gillies; S. Hagen; T. Schaub. IETF. August 2016. Proposed Standard. URL: + +\[RFC8785\] +: [JSON Canonicalization Scheme (JCS)](https://www.rfc-editor.org/rfc/rfc8785). A. Rundgren; B. Jordan; S. Erdtman. Network Working Group. June 2020. Informational. URL: + +\[SPARQL11-OVERVIEW\] +: [SPARQL 1.1 Overview](https://www.w3.org/TR/sparql11-overview/). The W3C SPARQL Working Group. W3C. 21 March 2013. W3C Recommendation. URL: + +\[SRI\] +: [Subresource Integrity](https://www.w3.org/TR/SRI/). Devdatta Akhawe; Frederik Braun; Francois Marier; Joel Weinberger. W3C. 23 June 2016. W3C Recommendation. URL: + +\[string-meta\] +: [Strings on the Web: Language and Direction Metadata](https://www.w3.org/TR/string-meta/). Addison Phillips; Richard Ishida. W3C. 11 June 2019. W3C Working Draft. URL: + +\[TriG\] +: [RDF 1.1 TriG](https://www.w3.org/TR/trig/). Gavin Carothers; Andy Seaborne. W3C. 25 February 2014. W3C Recommendation. URL: + +\[Turtle\] +: [RDF 1.1 Turtle](https://www.w3.org/TR/turtle/). Eric Prud\'hommeaux; Gavin Carothers. W3C. 25 February 2014. W3C Recommendation. URL: + +\[URN\] +: [URN Syntax](https://tools.ietf.org/html/rfc2141). R. Moats. IETF. May 1997. Proposed Standard. URL: + +\[WEBIDL\] +: [Web IDL](https://heycam.github.io/webidl/). Boris Zbarsky. W3C. 15 December 2016. W3C Editor\'s Draft. URL: + +\[YAML\] +: [YAML Ain't Markup Language (YAML™) Version 1.2](http://yaml.org/spec/1.2/spec.html). Oren Ben-Kiki; Clark Evans; Ingy döt Net. 1 October 2009. URL: + +[↑](#title) diff --git a/specifications/update-specs.sh b/specifications/update-specs.sh index 76ce261..627d176 100755 --- a/specifications/update-specs.sh +++ b/specifications/update-specs.sh @@ -10,16 +10,23 @@ then fi URLS=( + # OpenID specifications "https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html" "https://openid.net/specs/openid-federation-1_0.html" - "https://www.w3.org/TR/vc-data-model-2.0/" - "https://www.w3.org/TR/vc-jose-cose/" - "https://fidescommunity.github.io/DIIP/" "https://openid.net/specs/openid-connect-core-1_0.html" "https://openid.net/specs/openid-connect-discovery-1_0.html" "https://openid.net/specs/openid-connect-rpinitiated-1_0.html" "https://openid.net/specs/openid-connect-frontchannel-1_0.html" "https://openid.net/specs/openid-connect-backchannel-1_0.html" + # W3C specifications + "https://www.w3.org/TR/vc-data-model-2.0/" + "https://www.w3.org/TR/vc-jose-cose/" + "https://www.w3.org/TR/vc-imp-guide/" + "https://www.w3.org/TR/did-1.0/" + "https://www.w3.org/TR/vc-data-integrity/" + "https://www.w3.org/TR/json-ld11/" + # DIIP specifications + "https://fidescommunity.github.io/DIIP/" ) # For each of the specifications, fetch the content from the URL and save it diff --git a/specifications/vc-data-integrity.md b/specifications/vc-data-integrity.md new file mode 100644 index 0000000..6d03539 --- /dev/null +++ b/specifications/vc-data-integrity.md @@ -0,0 +1,1833 @@ +--- +color-scheme: light +description: This specification describes mechanisms for ensuring the authenticity and integrity of verifiable credentials and similar types of constrained digital documents using cryptography, especially through the use of digital signatures and related mathematical proofs. +generator: ReSpec 35.3.1 +lang: en +title: Verifiable Credential Data Integrity 1.0 +viewport: width=device-width, initial-scale=1, shrink-to-fit=no +--- + +[![W3C](https://www.w3.org/StyleSheets/TR/2021/logos/W3C)](https://www.w3.org/) + +# Verifiable Credential Data Integrity 1.0 + +## Securing the Integrity of Verifiable Credential Data + +[W3C Recommendation](https://www.w3.org/standards/types#REC) 15 May 2025 + +More details about this document + +This version: +: [https://www.w3.org/TR/2025/REC-vc-data-integrity-20250515/](https://www.w3.org/TR/2025/REC-vc-data-integrity-20250515/) + +Latest published version: +: + +Latest editor\'s draft: +: + +History: +: +: [Commit history](https://github.com/w3c/vc-data-integrity/commits/) + +Implementation report: +: + +Editors: +: [Manu Sporny](https://www.linkedin.com/in/manusporny/) ([Digital Bazaar](https://digitalbazaar.com/)) +: [Ted Thibodeau Jr](https://github.com/TallTed) ([OpenLink Software](https://www.openlinksw.com/)) +: [Ivan Herman](https://www.w3.org/People/Ivan/)[![](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld2JveD0iMCAwIDI1NiAyNTYiPgogICAgPHN0eWxlPgoKICAgICAgLnN0MSB7CiAgICAgICAgZmlsbDogI2ZmZjsKICAgICAgfQogICAgCjwvc3R5bGU+CiAgICA8cGF0aCBkPSJNMjU2IDEyOGMwIDcwLjctNTcuMyAxMjgtMTI4IDEyOFMwIDE5OC43IDAgMTI4IDU3LjMgMCAxMjggMHMxMjggNTcuMyAxMjggMTI4eiIgZmlsbD0iI2E2Y2UzOSI+PC9wYXRoPgogICAgPHBhdGggY2xhc3M9InN0MSIgZD0iTTg2LjMgMTg2LjJINzAuOVY3OS4xaDE1LjR2MTA3LjF6TTEwOC45IDc5LjFoNDEuNmMzOS42IDAgNTcgMjguMyA1NyA1My42IDAgMjcuNS0yMS41IDUzLjYtNTYuOCA1My42aC00MS44Vjc5LjF6bTE1LjQgOTMuM2gyNC41YzM0LjkgMCA0Mi45LTI2LjUgNDIuOS0zOS43QzE5MS43IDExMS4yIDE3OCA5MyAxNDggOTNoLTIzLjd2NzkuNHpNODguNyA1Ni44YzAgNS41LTQuNSAxMC4xLTEwLjEgMTAuMXMtMTAuMS00LjYtMTAuMS0xMC4xYzAtNS42IDQuNS0xMC4xIDEwLjEtMTAuMXMxMC4xIDQuNiAxMC4xIDEwLjF6Ij48L3BhdGg+CiAgPC9zdmc+)](https://orcid.org/0000-0003-0782-2704) ([W3C](https://www.w3.org)) +: [Dave Longley](https://digitalbazaar.com/) ([Digital Bazaar](http://digitalbazaar.com/)) +: [Greg Bernstein](https://www.grotto-networking.com/) (Invited Expert) + +Authors: +: [Dave Longley](https://digitalbazaar.com/) ([Digital Bazaar](http://digitalbazaar.com/)) +: [Manu Sporny](https://www.linkedin.com/in/manusporny/) ([Digital Bazaar](https://digitalbazaar.com/)) +: [Ivan Herman](https://www.w3.org/People/Ivan/)[![](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld2JveD0iMCAwIDI1NiAyNTYiPgogICAgPHN0eWxlPgoKICAgICAgLnN0MSB7CiAgICAgICAgZmlsbDogI2ZmZjsKICAgICAgfQogICAgCjwvc3R5bGU+CiAgICA8cGF0aCBkPSJNMjU2IDEyOGMwIDcwLjctNTcuMyAxMjgtMTI4IDEyOFMwIDE5OC43IDAgMTI4IDU3LjMgMCAxMjggMHMxMjggNTcuMyAxMjggMTI4eiIgZmlsbD0iI2E2Y2UzOSI+PC9wYXRoPgogICAgPHBhdGggY2xhc3M9InN0MSIgZD0iTTg2LjMgMTg2LjJINzAuOVY3OS4xaDE1LjR2MTA3LjF6TTEwOC45IDc5LjFoNDEuNmMzOS42IDAgNTcgMjguMyA1NyA1My42IDAgMjcuNS0yMS41IDUzLjYtNTYuOCA1My42aC00MS44Vjc5LjF6bTE1LjQgOTMuM2gyNC41YzM0LjkgMCA0Mi45LTI2LjUgNDIuOS0zOS43QzE5MS43IDExMS4yIDE3OCA5MyAxNDggOTNoLTIzLjd2NzkuNHpNODguNyA1Ni44YzAgNS41LTQuNSAxMC4xLTEwLjEgMTAuMXMtMTAuMS00LjYtMTAuMS0xMC4xYzAtNS42IDQuNS0xMC4xIDEwLjEtMTAuMXMxMC4xIDQuNiAxMC4xIDEwLjF6Ij48L3BhdGg+CiAgPC9zdmc+)](https://orcid.org/0000-0003-0782-2704) ([W3C](https://www.w3.org)) + +Feedback: +: [GitHub w3c/vc-data-integrity](https://github.com/w3c/vc-data-integrity/) ([pull requests](https://github.com/w3c/vc-data-integrity/pulls/), [new issue](https://github.com/w3c/vc-data-integrity/issues/new/choose), [open issues](https://github.com/w3c/vc-data-integrity/issues/)) +: [public-vc-wg@w3.org](mailto:public-vc-wg@w3.org?subject=%5Bvc-data-integrity%5D%20YOUR%20TOPIC%20HERE) with subject line \[vc-data-integrity\] *... message topic ...* ([archives](https://lists.w3.org/Archives/Public/public-vc-wg)) + +Errata: +: [Errata exists](https://w3c.github.io/vc-data-integrity/errata.html). + +Related Specifications +: [The Verifiable Credentials Data Model v2.0](https://www.w3.org/TR/VC-DATA-MODEL-2.0/) +: [The Edwards Digital Signature Algorithm Cryptosuites v1.0](https://www.w3.org/TR/vc-di-eddsa/) +: [The Elliptic Curve Digital Signature Algorithm Cryptosuites v1.0](https://www.w3.org/TR/vc-di-ecdsa/) +: [The BBS Digital Signature Algorithm Cryptosuites v1.0](https://www.w3.org/TR/vc-di-bbs/) + +See also [**translations**](https://www.w3.org/Translations/?technology=vc-data-integrity). + +[Copyright](https://www.w3.org/policies/#copyright) © 2025 [World Wide Web Consortium](https://www.w3.org/). W3C^®^ [liability](https://www.w3.org/policies/#Legal_Disclaimer), [trademark](https://www.w3.org/policies/#W3C_Trademarks) and [permissive document license](https://www.w3.org/copyright/software-license-2023/ "W3C Software and Document Notice and License") rules apply. + +------------------------------------------------------------------------ + +## Abstract + +This specification describes mechanisms for ensuring the authenticity and integrity of [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) and similar types of constrained digital documents using cryptography, especially through the use of digital signatures and related mathematical proofs. + +## Status of This Document + +*This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the [W3C standards and drafts index](https://www.w3.org/TR/) at https://www.w3.org/TR/.* + +Comments regarding this specification are welcome at any time. Please file issues directly on [GitHub](https://github.com/w3c/vc-data-integrity/issues/), or send them to if that is not possible. ([subscribe](mailto:public-vc-comments-request@w3.org?subject=subscribe), [archives](https://lists.w3.org/Archives/Public/public-vc-comments/)). + +This document was published by the [Verifiable Credentials Working Group](https://www.w3.org/groups/wg/vc) as a Recommendation using the [Recommendation track](https://www.w3.org/policies/process/20231103/#recs-and-notes). + +W3C recommends the wide deployment of this specification as a standard for the Web. + +A W3C Recommendation is a specification that, after extensive consensus-building, is endorsed by W3C and its Members, and has commitments from Working Group members to [royalty-free licensing](https://www.w3.org/policies/patent-policy/#sec-Requirements) for implementations. + +This document was produced by a group operating under the [W3C Patent Policy](https://www.w3.org/policies/patent-policy/). W3C maintains a [public list of any patent disclosures](https://www.w3.org/groups/wg/vc/ipr) 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)](https://www.w3.org/policies/patent-policy/#def-essential) must disclose the information in accordance with [section 6 of the W3C Patent Policy](https://www.w3.org/policies/patent-policy/#sec-Disclosure). + +This document is governed by the [03 November 2023 W3C Process Document](https://www.w3.org/policies/process/20231103/). + +## Table of Contents + +1. [Abstract](#abstract) +2. [Status of This Document](#sotd) +3. [1. Introduction](#introduction) + 1. [1.1 How it Works](#how-it-works) + 2. [1.2 Design Goals and Rationale](#design-goals-and-rationale) + 3. [1.3 Conformance](#conformance) + 4. [1.4 Terminology](#terminology) +4. [2. Data Model](#data-model) + 1. [2.1 Proofs](#proofs) + 1. [2.1.1 Proof Sets](#proof-sets) + 2. [2.1.2 Proof Chains](#proof-chains) + 3. [2.1.3 Proof Graphs](#proof-graphs) + 2. [2.2 Proof Purposes](#proof-purposes) + 3. [2.3 Resource Integrity](#resource-integrity) + 4. [2.4 Contexts and Vocabularies](#contexts-and-vocabularies) + 1. [2.4.1 Validating Contexts](#validating-contexts) + 2. [2.4.2 Context Injection](#context-injection) + 3. [2.4.3 Securing Data Losslessly](#securing-data-losslessly) + 4. [2.4.4 Datatypes](#datatypes) + 5. [2.5 Relationship to Linked Data](#relationship-to-linked-data) + 6. [2.6 Relationship to Verifiable Credentials](#relationship-to-verifiable-credentials) +5. [3. Cryptographic Suites](#cryptographic-suites) + 1. [3.1 DataIntegrityProof](#dataintegrityproof) +6. [4. Algorithms](#algorithms) + 1. [4.1 Processing Model](#processing-model) + 2. [4.2 Add Proof](#add-proof) + 3. [4.3 Add Proof Set/Chain](#add-proof-set-chain) + 4. [4.4 Verify Proof](#verify-proof) + 5. [4.5 Verify Proof Sets and Chains](#verify-proof-sets-and-chains) + 6. [4.6 Context Validation](#context-validation) + 7. [4.7 Processing Errors](#processing-errors) +7. [5. Security Considerations](#security-considerations) + 1. [5.1 Versioning Cryptography Suites](#versioning-cryptography-suites) + 2. [5.2 Protecting Application Developers](#protecting-application-developers) + 3. [5.3 Conventions for Naming Cryptography Suites](#conventions-for-naming-cryptography-suites) + 4. [5.4 Agility and Layering](#agility-and-layering) + 5. [5.5 Safer Abstractions](#safer-abstractions) + 6. [5.6 Transformations](#transformations) + 7. [5.7 Protected Information](#protected-information) + 8. [5.8 Data Opacity](#data-opacity) + 9. [5.9 Verification Method Binding](#verification-method-binding) + 10. [5.10 Verification Relationship Validation](#verification-relationship-validation) + 11. [5.11 Proof Purpose Validation](#proof-purpose-validation) + 12. [5.12 Canonicalization Method Security](#canonicalization-method-security) + 13. [5.13 Canonicalization Method Correctness](#canonicalization-method-correctness) + 14. [5.14 Network Requests](#network-requests) + 15. [5.15 Other Security Considerations](#other-security-considerations) +8. [6. Privacy Considerations](#privacy-considerations) + 1. [6.1 Unlinkability](#unlinkability) + 2. [6.2 Selective Disclosure](#selective-disclosure) + 3. [6.3 Previous Proofs](#previous-proofs) + 4. [6.4 Fingerprinting Network Requests](#fingerprinting-network-requests) + 5. [6.5 Canonicalization Method Privacy](#canonicalization-method-privacy) + 6. [6.6 Other Privacy Considerations](#other-privacy-considerations) +9. [7. Accessibility Considerations](#accessibility-considerations) + 1. [7.1 Presenting Time Values](#presenting-time-values) +10. [A. Understanding Proof Sets and Proof Chains](#understanding-proof-sets-and-proof-chains) +11. [B. Revision History](#revision-history) +12. [C. Acknowledgements](#acknowledgements) +13. [D. References](#references) + 1. [D.1 Normative references](#normative-references) + 2. [D.2 Informative references](#informative-references) + +## 1. Introduction + +[](#introduction) + +*This section is non-normative.* + +This specification describes mechanisms for ensuring the authenticity and integrity of [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) and similar types of constrained digital documents using cryptography, especially through the use of digital signatures and related mathematical proofs. Cryptographic proofs enable functionality that is useful to implementors of distributed systems. For example, proofs can be used to: + +- Make statements that can be shared without loss of trust, because their authorship can be verified by a third party, for example as part of a [verifiable credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) \[[VC-DATA-MODEL-2.0](#bib-vc-data-model-2.0 "Verifiable Credentials Data Model v2.0")\], [verifiable presentation](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-presentation), or social media post. +- Authenticate as an entity identified by a particular identifier, for example, as the subject identified by a Decentralized Identifier (DID) \[[DID](#bib-did "Decentralized Identifiers (DIDs) v1.0")\]. +- Delegate authorization for actions in a remote execution environment, via mechanisms such as Authorization Capabilities \[[ZCAP](#bib-zcap "Authorization Capabilities for Linked Data")\]. +- Agree to contracts where the agreement can be verified by another party. +- Additionally, many proofs that are based on cryptographic digital signatures provide the benefit of integrity protection, making documents and data tamper-evident. + +### 1.1 How it Works + +[](#how-it-works) + +*This section is non-normative.* + +The operation of Data Integrity is conceptually simple. To create a cryptographic proof, the following steps are performed: 1) Transformation, 2) Hashing, and 3) Proof Generation. + +![ Diagram showing the three steps involved in the creation of a cryptographic proof. The diagram is laid out left to right with a blue box labeled \'Data\' on the far left. The blue box travels, left to right, through three subsequent yellow arrows labeled \'Transform Data\', \'Hash Data\', and \'Generate Proof\'. The resulting blue box at the far right is labeled \'Data with Proof\'. ](diagrams/hiw-creation.svg) + +[Figure 1](#hiw-creation) To create a cryptographic proof, data is transformed, hashed, and cryptographically protected. + +Transformation is a process described by a transformation algorithm that takes input data and prepares it for the hashing process. One example of a possible transformation is to take a record of people\'s names that attended a meeting, sort the list alphabetically by the individual\'s family name, and rewrite the names on a piece of paper, one per line, in sorted order. Examples of transformations include [canonicalization](https://en.wikipedia.org/wiki/Canonicalization) and [binary-to-text](https://en.wikipedia.org/wiki/Binary-to-text_encoding) encoding. + +Hashing is a process described by a hashing algorithm that calculates an identifier for the transformed data using a [cryptographic hash function](https://en.wikipedia.org/wiki/Cryptographic_hash_function). This process is conceptually similar to how a phone address book functions, where one takes a person\'s name (the input data) and maps that name to that individual\'s phone number (the hash). Examples of cryptographic hash functions include [SHA-3](https://en.wikipedia.org/wiki/Cryptographic_hash_function#SHA-3) and [BLAKE-3](https://en.wikipedia.org/wiki/Cryptographic_hash_function#BLAKE3). + +Proof Generation is a process described by a proof serialization algorithm that calculates a value that protects the integrity of the input data from modification or otherwise proves a certain desired threshold of trust. This process is conceptually similar to the way a wax seal can be used on an envelope containing a letter to establish trust in the sender and show that the letter has not been tampered with in transit. Examples of proof serialization functions include [digital signatures](https://en.wikipedia.org/wiki/Digital_signature), [proofs of stake](https://en.wikipedia.org/wiki/Proof_of_stake), and [proofs of knowledge](https://en.wikipedia.org/wiki/Proof_of_knowledge), in general. + +To verify a cryptographic proof, the following steps are performed: 1) Transformation, 2) Hashing, and 3) Proof Verification. + +![ Diagram showing the three steps involved in the verification of a cryptographic proof. The diagram is laid out left to right with a blue box labeled \'Data with Proof\' on the far left. The blue box travels, left to right, through three subsequent yellow arrows labeled \'Transform Data\', \'Hash Data\', and \'Verify Proof\'. The resulting blue box at the far right is labeled \'Data with Proof\'. ](diagrams/hiw-verification.svg) + +[Figure 2](#hiw-verification) To verify a cryptographic proof, data is transformed, hashed, and checked for correctness. + +During verification, the [transformation](#dfn-transformation) and [hashing](#dfn-hashing) steps are conceptually the same as described above. + +Proof Verification is a process that is described by a proof verification algorithm that applies a cryptographic proof verification function to see if the input data can be trusted. Possible proof verification functions include [digital signatures](https://en.wikipedia.org/wiki/Digital_signature), [proofs of stake](https://en.wikipedia.org/wiki/Proof_of_stake), and [proofs of knowledge](https://en.wikipedia.org/wiki/Proof_of_knowledge), in general. + +This specification details how cryptographic software architects and implementers can package these processes together into things called [cryptographic suites](#dfn-cryptosuite) and provide them to application developers for the purposes of protecting the integrity of application data in transit and at rest. + +### 1.2 Design Goals and Rationale + +[](#design-goals-and-rationale) + +*This section is non-normative.* + +This specification optimizes for the following design goals: + +Simplicity +: The technology is designed to be easy to use for application developers, without requiring significant training in cryptography. It optimizes for the following priority of constituencies: application developers over cryptographic suite implementers, over cryptographic suite designers, over cryptographic algorithm specification authors. The solution focuses on sensible defaults to prevent the selection of ineffective protection mechanisms. See section [5.2 Protecting Application Developers](#protecting-application-developers) and [5.1 Versioning Cryptography Suites](#versioning-cryptography-suites) for further details. + +Composability +: A number of historical digital signature mechanisms have had monolithic designs which limited use cases by combining data transformation, syntax, digital signature, and serialization into a single specification. This specification layers each component such that a broader range of use cases are enabled, including generalized selective disclosure and serialization-agnostic signatures. See section [5.6 Transformations](#transformations), section [5.8 Data Opacity](#data-opacity), and [5.1 Versioning Cryptography Suites](#versioning-cryptography-suites) for further rationale. + +Resilience +: Since digital proof mechanisms might be compromised without warning due to technological advancements, it is important that [cryptographic suites](#dfn-cryptosuite) provide multiple layers of protection and can be rapidly upgraded. This specification provides for both algorithmic agility and cryptographic layering, while still keeping the digital proof format easy for developers to understand and use. See section [5.4 Agility and Layering](#agility-and-layering) to understand the particulars. + +Progressive Extensibility +: Creating and deploying new cryptographic protection mechanisms is designed to be a deliberate, iterative, and careful process that acknowledges that extension happens in phases from experimentation, to implementation, to standardization. This specification strives to balance the need for an increase in the rate of innovation in cryptography with the need for stable production-grade cryptography suites. See section [3. Cryptographic Suites](#cryptographic-suites) for instructions on establishing new types of cryptographic proofs. + +Serialization Flexibility +: Cryptographic proofs can be serialized in many different but equivalent ways and have often been tightly bound to the original document syntax. This specification enables one to create cryptographic proofs that are not bound to the original document syntax, which enables more advanced use cases such as being able to use a single digital signature across a variety of serialization syntaxes such as JSON and CBOR without the need to regenerate the cryptographic proof. See section [5.6 Transformations](#transformations) for an explanation of the benefits of such an approach. + +Note: Application of technology to broader use cases + +While this specification primarily focuses on [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential), the design of this technology is generalized, such that it can be used for other use cases. In these instances, implementers are expected to perform their own due diligence and expert review as to the applicability of the technology to their use case. + +### 1.3 Conformance + +[](#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*, *OPTIONAL*, and *SHOULD* in this document are to be interpreted as described in [BCP 14](https://www.rfc-editor.org/info/bcp14) \[[RFC2119](#bib-rfc2119 "Key words for use in RFCs to Indicate Requirement Levels")\] \[[RFC8174](#bib-rfc8174 "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words")\] when, and only when, they appear in all capitals, as shown here. + +A conforming secured document is any [byte sequence](https://infra.spec.whatwg.org/#byte-sequence) that can be converted to a [JSON document](https://infra.spec.whatwg.org/#parse-json-bytes-to-a-javascript-value) that follows the relevant normative requirements in Sections [2.1 Proofs](#proofs), [2.2 Proof Purposes](#proof-purposes), [2.3 Resource Integrity](#resource-integrity), [2.4 Contexts and Vocabularies](#contexts-and-vocabularies), and [3.1 DataIntegrityProof](#dataintegrityproof). + +A conforming cryptographic suite specification is any specification that follows the relevant normative requirements in Section [3. Cryptographic Suites](#cryptographic-suites). + +A conforming processor is any algorithm realized as software and/or hardware that generates and/or consumes a [conforming secured document](#dfn-conforming-secured-document) according to the relevant normative statements in Section [4. Algorithms](#algorithms). Conforming processors *MUST* produce errors when non-conforming documents are consumed. + +### 1.4 Terminology + +[](#terminology) + +This section defines the terms used in this specification. A link to these terms is included whenever they appear in this specification. + +controlled identifier document +: A document that contains public cryptographic material as defined in the [Controlled Identifiers v1.0](https://www.w3.org/TR/cid-1.0/) specification. + +cryptographic suite +: A specification defining the usage of specific cryptographic primitives in order to achieve a particular security goal. These documents are often used to specify [verification methods](#dfn-verification-method), digital signature types, their identifiers, and other related properties. See Section [3. Cryptographic Suites](#cryptographic-suites) for further detail. + +data integrity proof +: A set of attributes that represent a digital proof and the parameters required to verify it. A **digital signature** is a type of data integrity proof. + +proof purpose +: The specific intent for the proof; the reason why an entity created it. The protected declaration acts as a safeguard to prevent the proof from being misused for a purpose other than the one it was intended for. + +public key +: Cryptographic material that can be used to verify digital proofs created with a corresponding [secret key](#dfn-secret-key). + +secret key +: Cryptographic material, sometimes referred to as a **private key**, that is not to be shared with anyone, and is used to generate digital proofs and/or digital signatures. + +verification method + +: A set of parameters that can be used together with a process to independently verify a proof. For example, a cryptographic [public key](#dfn-public-key) can be used as a verification method with respect to a digital signature; in such usage, it verifies that the signer possessed the associated cryptographic [secret key](#dfn-secret-key). + + \"Verification\" and \"proof\" in this definition are intended to apply broadly. For example, a cryptographic public key might be used during Diffie-Hellman key exchange to negotiate a shared symmetric key for encryption. This guarantees the integrity of the key agreement process. It is thus another type of verification method, even though descriptions of the process might not use the words \"verification\" or \"proof.\" + +verifier +: A role an entity performs by receiving data containing one or more [data integrity proofs](#dfn-data-integrity-proof) and then determining whether or not the proof is legitimate. + +## 2. Data Model + +[](#data-model) + +This section specifies the data model that is used for expressing [data integrity proofs](#dfn-data-integrity-proof) and the integrity of related resources. + +All of the data model properties and types in this specification map to URLs. The vocabulary where these URLs are defined is the [The Security Vocabulary](https://w3id.org/security). The explicit mechanism that is used to perform this mapping in a secured document is the `@context` property. + +The mapping mechanism is defined by [JSON-LD 1.1](https://www.w3.org/TR/json-ld11/). To ensure a document can be interoperably consumed without the use of a JSON-LD library, document authors are advised to ensure that domain experts have 1) specified the expected order for all values associated with a `@context` property, 2) published cryptographic hashes for each `@context` file, and 3) deemed that the contents of each `@context` file are appropriate for the intended use case. + +When a document is processed by a processor that does not utilize JSON-LD libraries, and there is a requirement to use the same semantics as those used in a JSON-LD environment, implementers are advised to 1) enforce the expected order and values in the `@context` property, and 2) ensure that each `@context` file matches the known cryptographic hashes for each `@context` file. + +Using static, versioned, `@context` files with published cryptographic hashes in conjunction with JSON Schema is one acceptable approach to implementing the mechanisms described above, which ensures proper term identification, typing, and order, when a processor that does not utilize a JSON-LD library is used. See the section on [Type-Specific Processing](https://www.w3.org/TR/vc-data-model-2.0/#type-specific-credential-processing) in [Verifiable Credentials Data Model v2.0](https://www.w3.org/TR/vc-data-model-2.0/) for more details. + +### 2.1 Proofs + +[](#proofs) + +A [data integrity proof](#dfn-data-integrity-proof) provides information about the proof mechanism, parameters required to verify that proof, and the proof value itself. All of this information is provided using Linked Data vocabularies such as [The Security Vocabulary](https://w3id.org/security). + +When expressing a [data integrity proof](#dfn-data-integrity-proof) on an object, a `proof` property *MUST* be used. The `proof` property within a [verifiable credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) is a [named graph](#dfn-named-graph). If present, its value *MUST* be either a single object, or an unordered set of objects, expressed using the properties below: + +id +: An optional identifier for the proof, which *MUST* be a URL \[[URL](#bib-url "URL Standard")\], such as a UUID as a URN (`urn:uuid:6a1676b8-b51f-11ed-937b-d76685a20ff5`). The usage of this property is further explained in Section [2.1.2 Proof Chains](#proof-chains). + +type +: The specific type of proof *MUST* be specified as a [string](https://infra.spec.whatwg.org/#string) that maps to a URL \[[URL](#bib-url "URL Standard")\]. Examples of proof types include `DataIntegrityProof` and `Ed25519Signature2020`. Proof types determine what other fields are required to secure and verify the proof. + +proofPurpose +: The reason the proof was created *MUST* be specified as a [string](https://infra.spec.whatwg.org/#string) that maps to a URL \[[URL](#bib-url "URL Standard")\]. The proof purpose acts as a safeguard to prevent the proof from being misused by being applied to a purpose other than the one that was intended. For example, without this value the creator of a proof could be tricked into using cryptographic material typically used to create a Verifiable Credential (`assertionMethod`) during a login process (`authentication`) which would then result in the creation of a [verifiable credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) they never meant to create instead of the intended action, which was to merely log in to a website. + +verificationMethod +: A verification method is the means and information needed to verify the proof. If included, the value *MUST* be a [string](https://infra.spec.whatwg.org/#string) that maps to a \[[URL](#bib-url "URL Standard")\]. Inclusion of `verificationMethod` is *OPTIONAL*, but if it is not included, other properties such as `cryptosuite` might provide a mechanism by which to obtain the information necessary to verify the proof. Note that when `verificationMethod` is expressed in a [data integrity proof](#dfn-data-integrity-proof), the value points to the actual location of the data; that is, the `verificationMethod` references, via a URL, the location of the [public key](#dfn-public-key) that can be used to verify the proof. This [public key](#dfn-public-key) data is stored in a [controlled identifier document](#dfn-controlled-identifier-document), which contains a full description of the verification method. + +cryptosuite +: An identifier for the cryptographic suite that can be used to verify the proof. See [3. Cryptographic Suites](#cryptographic-suites) for more information. If the proof `type` is `DataIntegrityProof`, `cryptosuite` *MUST* be specified; otherwise, `cryptosuite` *MAY* be specified. If specified, its value *MUST* be a string. + +created +: The date and time the proof was created is *OPTIONAL* and, if included, *MUST* be specified as an \[[XMLSCHEMA11-2](#bib-xmlschema11-2 "W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes")\] `dateTimeStamp` string, either in Universal Coordinated Time (UTC), denoted by a Z at the end of the value, or with a time zone offset relative to UTC. A [conforming processor](#dfn-conforming-processor) *MAY* chose to consume time values that were incorrectly serialized without an offset. Incorrectly serialized time values without an offset are to be interpreted as UTC. + +expires +: The `expires` property is *OPTIONAL* and, if present, specifies when the proof expires. If present, it *MUST* be an \[[XMLSCHEMA11-2](#bib-xmlschema11-2 "W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes")\] `dateTimeStamp` string, either in Universal Coordinated Time (UTC), denoted by a Z at the end of the value, or with a time zone offset relative to UTC. A [conforming processor](#dfn-conforming-processor) *MAY* chose to consume time values that were incorrectly serialized without an offset. Incorrectly serialized time values without an offset are to be interpreted as UTC. + +domain +: The `domain` property is *OPTIONAL*. It conveys one or more security domains in which the proof is meant to be used. If specified, the associated value *MUST* be either a string, or an unordered set of strings. A verifier *SHOULD* use the value to ensure that the proof was intended to be used in the security domain in which the verifier is operating. The specification of the `domain` parameter is useful in challenge-response protocols where the verifier is operating from within a security domain known to the creator of the proof. Example domain values include: `domain.example` (DNS domain), `https://domain.example:8443` (Web origin), `mycorp-intranet` (bespoke text string), and `b31d37d4-dd59-47d3-9dd8-c973da43b63a` (UUID). + +challenge +: A [string](https://infra.spec.whatwg.org/#string) value that *SHOULD* be included in a proof if a `domain` is specified. The value is used once for a particular [domain](https://url.spec.whatwg.org/#concept-domain) and window of time. This value is used to mitigate replay attacks. Examples of a challenge value include: `1235abcd6789`, `79d34551-ae81-44ae-823b-6dadbab9ebd4`, and `ruby`. + +proofValue +: A [string](https://infra.spec.whatwg.org/#string) value that expresses base-encoded binary data necessary to verify the digital proof using the `verificationMethod` specified. The value *MUST* use a header and encoding as described in Section [2.4 Multibase](https://www.w3.org/TR/cid-1.0/#multibase-0) of the [Controlled Identifiers v1.0](https://www.w3.org/TR/cid-1.0/) specification to express the binary data. The contents of this value are determined by a specific cryptosuite and set to the *proof value* generated by the [Add Proof Algorithm](#add-proof) for that cryptosuite. Alternative properties with different encodings specified by the cryptosuite *MAY* be used, instead of this property, to encode the data necessary to verify the digital proof. + +previousProof +: The `previousProof` property is *OPTIONAL*. If present, it *MUST* be a string value or an unordered list of string values. Each value identifies another [data integrity proof](#dfn-data-integrity-proof), all of which *MUST* also verify for the current proof to be considered verified. This property is used in Section [2.1.2 Proof Chains](#proof-chains). + +nonce +: An *OPTIONAL* [string](https://infra.spec.whatwg.org/#string) value supplied by the proof creator. One use of this field is to increase privacy by decreasing linkability that is the result of deterministically generated signatures. + +A proof can be added to a JSON document like the following: + +[Example 1](#example-a-simple-json-data-document): A simple JSON data document + +``` nohighlight +{ + "myWebsite": "https://hello.world.example/" +}; +``` + +The following proof secures the document above using the `eddsa-jcs-2022` cryptography suite \[[DI-EDDSA](#bib-di-eddsa "The Edwards Digital Signature Algorithm Cryptosuites v1.0")\], which produces a verifiable digital proof by transforming the input data using the JSON Canonicalization Scheme (JCS) \[[RFC8785](#bib-rfc8785 "JSON Canonicalization Scheme (JCS)")\] and then digitally signing it using an Edwards Digital Signature Algorithm (EdDSA). + +[Example 2](#example-a-simple-signed-json-data-document): A simple signed JSON data document + +``` nohighlight +{ + "myWebsite": "https://hello.world.example/", + "proof": { + "type": "DataIntegrityProof", + "cryptosuite": "eddsa-jcs-2022", + "created": "2023-03-05T19:23:24Z", + "verificationMethod": "https://di.example/issuer#z6MkjLrk3gKS2nnkeWcmcxiZPGskmesDpuwRBorgHxUXfxnG", + "proofPurpose": "assertionMethod", + "proofValue": "zQeVbY4oey5q2M3XKaxup3tmzN4DRFTLVqpLMweBrSxMY2xHX5XTYV8nQApmEcqaqA3Q1gVHMrXFkXJeV6doDwLWx" + } +} +``` + +Similarly, a proof can be added to a JSON-LD data document like the following: + +[Example 3](#example-a-simple-json-ld-data-document): A simple JSON-LD data document + +``` nohighlight +{ + "@context": {"myWebsite": "https://vocabulary.example/myWebsite"}, + "myWebsite": "https://hello.world.example/" +}; +``` + +The following proof secures the document above by using the `ecdsa-rdfc-2019` cryptography suite \[[DI-ECDSA](#bib-di-ecdsa "The Elliptic Curve Digital Signature Algorithm Cryptosuites v1.0")\], which produces a verifiable digital proof by transforming the input data using the RDF Dataset Canonicalization Scheme \[[RDF-CANON](#bib-rdf-canon "RDF Dataset Canonicalization")\] and then digitally signing it using the Elliptic Curve Digital Signature Algorithm (ECDSA). + +[Example 4](#example-a-simple-signed-json-ld-data-document): A simple signed JSON-LD data document + +``` nohighlight +{ + "@context": [ + {"myWebsite": "https://vocabulary.example/myWebsite"}, + "https://w3id.org/security/data-integrity/v2" + ], + "myWebsite": "https://hello.world.example/", + "proof": { + "type": "DataIntegrityProof", + "cryptosuite": "ecdsa-rdfc-2019", + "created": "2020-06-11T19:14:04Z", + "verificationMethod": "https://ldi.example/issuer#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP", + "proofPurpose": "assertionMethod", + "proofValue": "zXb23ZkdakfJNUhiTEdwyE598X7RLrkjnXEADLQZ7vZyUGXX8cyJZRBkNw813SGsJHWrcpo4Y8hRJ7adYn35Eetq" + } +} +``` + +Note: Representing time values to individuals + +This specification enables the expression of dates and times, such as through the `created` and `expires` properties. This information might be indirectly exposed to an individual if a proof is processed and is detected to be outside an allowable time range. When displaying date and time values related to the validity of cryptographic proofs, implementers are advised to respect the [locale](https://www.w3.org/TR/ltli/#locale) and local calendar preferences of the individual \[[LTLI](#bib-ltli "Language Tags and Locale Identifiers for the World Wide Web")\]. Conversion of timestamps to local time values are expected to consider the time zone expectations of the individual. See [Verifiable Credentials Data Model v2.0](https://www.w3.org/TR/vc-data-model-2.0/#representing-time) for more details about representing time values to individuals. + +[Example 5](#example-a-data-document-with-an-attached-proof-that-uses-the-expires-property): A data document with an attached proof that uses the \'expires\' property + +``` nohighlight +{ + "@context": [ + {"myWebsite": "https://vocabulary.example/myWebsite"}, + "https://w3id.org/security/data-integrity/v2" + ], + "myWebsite": "https://hello.world.example/", + "proof": { + "type": "DataIntegrityProof", + "cryptosuite": "ecdsa-rdfc-2019", + "created": "2020-06-11T19:14:04Z", + // the proof expires a month after it was created + "expires": "2020-07-11T19:14:04Z", + "verificationMethod": "https://ldi.example/issuer#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP", + "proofPurpose": "assertionMethod", + "proofValue": "z98X7RLrkjnXEADJNUhiTEdwyE5GXX8cyJZRLQZ7vZyUXb23ZkdakfRJ7adYY8hn35EetqBkNw813SGsJHWrcpo4" + } +} +``` + +The Data Integrity specification supports the concept of multiple proofs in a single document. There are two types of multi-proof approaches that are identified: Proof Sets (un-ordered) and Proof Chains (ordered). + +#### 2.1.1 Proof Sets + +[](#proof-sets) + +A proof set is useful when the same data needs to be secured by multiple entities, but where the order of proofs does not matter, such as in the case of a set of signatures on a contract. A proof set, which has no order, is represented by associating a set of proofs with the `proof` key in a document. + +[Example 6](#example-a-proof-set-in-a-data-document): A proof set in a data document + +``` nohighlight +{ + "@context": [ + {"myWebsite": "https://vocabulary.example/myWebsite"}, + "https://w3id.org/security/data-integrity/v2" + ], + "myWebsite": "https://hello.world.example/", + "proof": [{ + // This is one of the proofs in the set + "type": "DataIntegrityProof", + "cryptosuite": "eddsa-rdfc-2022", + "created": "2020-11-05T19:23:24Z", + "verificationMethod": "https://ldi.example/issuer/1#z6MkjLrk3gKS2nnkeWcmcxiZPGskmesDpuwRBorgHxUXfxnG", + "proofPurpose": "assertionMethod", + "proofValue": "z4oey5q2M3XKaxup3tmzN4DRFTLVqpLMweBrSxMY2xHX5XTYVQeVbY8nQAVHMrXFkXJpmEcqdoDwLWxaqA3Q1geV6" + }, { + // This is the other proof in the set + "type": "DataIntegrityProof", + "cryptosuite": "eddsa-rdfc-2022", + "created": "2020-11-05T13:08:49Z", + "verificationMethod": "https://pfps.example/issuer/2#z6MkGskxnGjLrk3gKS2mesDpuwRBokeWcmrgHxUXfnncxiZP", + "proofPurpose": "assertionMethod", + "proofValue": "z5QLBrp19KiWXerb8ByPnAZ9wujVFN8PDsxxXeMoyvDqhZ6Qnzr5CG9876zNht8BpStWi8H2Mi7XCY3inbLrZrm95" + }] +} +``` + +#### 2.1.2 Proof Chains + +[](#proof-chains) + +A proof chain is useful when the same data needs to be signed by multiple entities and the order of when the proofs occurred matters, such as in the case of a notary counter-signing a proof that had been created on a document. A proof chain, where proof order needs to be preserved, is expressed by providing at least one proof with an `id`, such as a UUID \[[RFC9562](#bib-rfc9562 "Universally Unique IDentifiers (UUIDs)")\], and another proof with a `previousProof` value that identifies the previous proof. + +[Example 7](#example-a-proof-chain-in-a-data-document): A proof chain in a data document + +``` nohighlight +{ + "@context": [ + {"myWebsite": "https://vocabulary.example/myWebsite"}, + "https://w3id.org/security/data-integrity/v2" +], + "myWebsite": "https://hello.world.example/", + "proof": [{ + // The 'id' value identifies this specific proof + "id": "urn:uuid:60102d04-b51e-11ed-acfe-2fcd717666a7", + "type": "DataIntegrityProof", + "cryptosuite": "eddsa-rdfc-2022", + "created": "2020-11-05T19:23:42Z", + "verificationMethod": "https://ldi.example/issuer/1#z6MkjLrk3gKS2nnkeWcmcxiZPGskmesDpuwRBorgHxUXfxnG", + "proofPurpose": "assertionMethod", + "proofValue": "zVbY8nQAVHMrXFkXJpmEcqdoDwLWxaqA3Q1geV64oey5q2M3XKaxup3tmzN4DRFTLVqpLMweBrSxMY2xHX5XTYVQe" + }, { + "type": "DataIntegrityProof", + "cryptosuite": "eddsa-rdfc-2022", + "created": "2020-11-05T21:28:14Z", + "verificationMethod": "https://pfps.example/issuer/2#z6MkGskxnGjLrk3gKS2mesDpuwRBokeWcmrgHxUXfnncxiZP", + "proofPurpose": "assertionMethod", + "proofValue": "z6Qnzr5CG9876zNht8BpStWi8H2Mi7XCY3inbLrZrm955QLBrp19KiWXerb8ByPnAZ9wujVFN8PDsxxXeMoyvDqhZ", + // The 'previousProof' value identifies which proof is verified before this one + "previousProof": "urn:uuid:60102d04-b51e-11ed-acfe-2fcd717666a7" + }] +} +``` + +#### 2.1.3 Proof Graphs + +[](#proof-graphs) + +When securing data in a document, it is important to clearly delineate the data being protected, which is every graph expressed in the document except the one containing the data associated with a securing mechanism, which is called a proof graph. Creating this separation enables the processing algorithms to deterministically protect and verify a secured document. + +The information contained in an input document before a [data integrity proof](#dfn-data-integrity-proof) is added to the document is expressed in one or more graphs. To ensure that information from different [data integrity proofs](#dfn-data-integrity-proof) is not accidentally co-mingled, the concept of a [proof graph](#dfn-proof-graph) is used to encapsulate each [data integrity proof](#dfn-data-integrity-proof). Each value associated with the `proof` property of the document identifies a separate graph, which is sometimes referred to as a named graph, of type ProofGraph, which contains a single [data integrity proof](#dfn-data-integrity-proof). + +Using these graphs has a concrete effect when performing JSON-LD processing, as this properly separates statements expressed in one graph from those in another graph. Implementers that limit their processing to other media types, such as JSON, YAML, or CBOR, will need to keep this in mind if they merge data from one document with data from another, such as when an `id` value string is the same in both documents. It is important to not merge objects that seem to have similar properties, when those objects do not have an `id` property and/or use a global identifier type such as a URL, as without these, is not possible to tell whether two such objects are expressing information about the same entity. + +### 2.2 Proof Purposes + +[](#proof-purposes) + +A proof that describes its purpose helps prevent it from being misused for some other purpose. [Proof purposes](#dfn-proof-purpose) enable [verifiers](#dfn-verifier) to know the intent of the creator of a proof so a message cannot be accidentally abused for another purpose. For example, a message signed for the purpose of merely making an assertion (perhaps intended to be widely shared) being abused as a message to authenticate to a service or take some action (such as invoking a capability to do something). + +It is important to note that [proof purposes](#dfn-proof-purpose) are a different mechanism from the `key_ops` restrictions in [JSON Web Key (JWK)](https://www.rfc-editor.org/rfc/rfc7517), the `KeyUsage` restriction in the [Web Cryptography API](https://www.w3.org/TR/WebCryptoAPI/) and the [Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile](https://www.rfc-editor.org/rfc/rfc5280). [Proof purposes](#dfn-proof-purpose) are expressions on why a [proof](#dfn-proof) was created and its intended domain of usage whereas the other mechanisms mentioned are intended to limit what a private key can be used to do. A [proof purpose](#dfn-proof-purpose) \"travels\" with the [proof](#dfn-proof) while a key restriction does not. + +The following is a list of commonly used [proof purpose](#dfn-proof-purpose) values. + +authentication +: Indicates that a given proof is only to be used for the purposes of an authentication protocol. + +assertionMethod +: Indicates that a proof can only be used for making assertions, for example signing a [verifiable credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential). + +keyAgreement +: Indicates that a proof is used for for key agreement protocols, such as Elliptic Curve Diffie Hellman key agreement used by popular encryption libraries. + +capabilityDelegation +: Indicates that the proof can only be used for delegating capabilities. See the Authorization Capabilities \[[ZCAP](#bib-zcap "Authorization Capabilities for Linked Data")\] specification for more detail. + +capabilityInvocation +: Indicates that the proof can only be used for invoking capabilities. See the Authorization Capabilities \[[ZCAP](#bib-zcap "Authorization Capabilities for Linked Data")\] specification for more detail. + +### 2.3 Resource Integrity + +[](#resource-integrity) + +When a link to an external resource is included in a [conforming secured document](#dfn-conforming-secured-document), it is desirable to know whether the resource that is identified has changed since the proof was created. This applies to cases where there is an external resource that is remotely retrieved as well as to cases where the [verifier](#dfn-verifier) might have a locally cached copy of the resource. + +To enable confirmation that a resource referenced by a [conforming secured document](#dfn-conforming-secured-document) has not changed since the document was secured, an implementer *MAY* include a property named `digestMultibase` in any object that includes an `id` property. If present, the `digestMultibase` value *MUST* be a single [string](https://infra.spec.whatwg.org/#string) value, or an [list](https://infra.spec.whatwg.org/#list) of [string](https://infra.spec.whatwg.org/#string) values, each of which is a [Multibase](https://www.w3.org/TR/cid-1.0/#multibase)-encoded [Multihash](https://www.w3.org/TR/cid-1.0/#multihash) value. + +JSON-LD context authors are expected to add `digestMultibase` to contexts that will be used in documents that refer to other resources and to include an associated cryptographic digest. For example, the [Verifiable Credentials Data Model v2.0](https://www.w3.org/TR/vc-data-model-2.0/) base context (`https://www.w3.org/ns/credentials/v2`) includes the `digestMultibase` property. + +An example of a resource integrity protected object is shown below: + +[Example 8](#example-an-integrity-protected-image-that-is-associated-with-an-object): An integrity-protected image that is associated with an object + +``` nohighlight +{ + ... + "image": { + "id": "https://university.example.org/images/58473", + "digestMultibase": "zQmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n" + }, + ... +} +``` + +Implementers are urged to consult appropriate sources, such as the [FIPS 180-4 Secure Hash Standard](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf) and the [Commercial National Security Algorithm Suite 2.0](https://en.wikipedia.org/wiki/Commercial_National_Security_Algorithm_Suite) to ensure that they are choosing a hash algorithm that is appropriate for their use case. + +### 2.4 Contexts and Vocabularies + +[](#contexts-and-vocabularies) + +Implementations that perform JSON-LD processing *MUST* treat the following JSON-LD context URLs as already resolved, where the resolved document matches the corresponding hash values below: + + ----------------------------------------------------------------------------------------- + Context URL and Hash + ----------------------------------------------------------------------------------------- + **URL:** https://w3id.org/security/data-integrity/v2\ + **SHA2-256 Digest:** `67f21e6e33a6c14e5ccfd2fc7865f7474fb71a04af7e94136cb399dfac8ae8f4` + + **URL:** https://w3id.org/security/multikey/v1\ + **SHA2-256 Digest:** `ba2c182de2d92f7e47184bcca8fcf0beaee6d3986c527bf664c195bbc7c58597` + + **URL:** https://w3id.org/security/jwk/v1\ + **SHA2-256 Digest:** `0f14b62f6071aafe00df265770ea0c7508e118247d79b7d861a406d2aa00bece` + ----------------------------------------------------------------------------------------- + +It is possible to confirm the cryptographic digests listed above by running a command like the following (replacing `` with the appropriate value) through a modern UNIX-like OS command line interface: `curl -sL -H "Accept: application/ld+json" | openssl dgst -sha256` + +The security vocabulary terms that the JSON-LD contexts listed above resolve to are in the [https://w3id.org/security#](https://w3id.org/security) namespace. That is, all security terms in this vocabulary are of the form `https://w3id.org/security#TERM`, where `TERM` is the name of a term. + +Implementations that perform RDF processing *MUST* treat the JSON-LD serialization of the vocabulary URL as already dereferenced, where the dereferenced document matches the corresponding hash value below. + +Note + +Beyond the security terms defined by this specification, the [https://w3id.org/security#](https://w3id.org/security) namespace also includes the terms defined in the [Controlled Identifiers v1.0](https://www.w3.org/TR/cid-1.0/) \[[CID](#bib-cid "Controlled Identifiers v1.0")\] specification, with the corresponding mappings in the context files listed above. + +When dereferencing the [https://w3id.org/security#](https://w3id.org/security) URL, the media type of the data that is returned depends on HTTP content negotiation. These are as follows: + + ------------------------------------------------------------------------------------------------------------------------------------------- + Media Type Description and Hash + ----------------------------------- ------------------------------------------------------------------------------------------------------- + application/ld+json The vocabulary in JSON-LD format \[[JSON-LD11](#bib-json-ld11 "JSON-LD 1.1")\].\ + \ + **SHA2-256 Digest:** `082434d5b742418753bbc5d593f93b66d4f1ccf1c627417c0caa2dea40728245` + + text/turtle The vocabulary in Turtle format \[[TURTLE](#bib-turtle "RDF 1.1 Turtle")\].\ + \ + **SHA2-256 Digest:** `9a5ba1e23f54b9adc9c39429f5eb3bd672cb392495cc4159561462921e012b37` + + text/html The vocabulary in HTML+RDFa Format \[[HTML-RDFA](#bib-html-rdfa "HTML+RDFa 1.1 - Second Edition")\].\ + \ + **SHA2-256 Digest:** `dadc810b5bb2c01a3caf276dc03a7c826311cddfefe86160a8c7d34704f50422` + ------------------------------------------------------------------------------------------------------------------------------------------- + +It is possible to confirm the cryptographic digests listed above by running a command like the following (replacing `` and `` with the appropriate values) through a modern UNIX-like OS command line interface: `curl -sL -H "Accept: " | openssl dgst -sha256` + +Authors of application-specific vocabularies and specifications *SHOULD* ensure that their JSON-LD context and vocabulary files are permanently cacheable using the approaches to caching described above or a functionally equivalent mechanism. + +Implementations *MAY* load application-specific JSON-LD context files from the network during development, but *SHOULD* permanently cache JSON-LD context files used by [conforming secured documents](#dfn-conforming-secured-document) in production settings, to increase their security and privacy characteristics. Goals of processing speed *MAY* be achieved through caching approaches such as those described above or functionally equivalent mechanisms. + +Some applications, such as digital wallets, that are capable of holding arbitrary [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) or other data-integrity-protected documents, from any issuer and using any contexts, might need to be able to load externally linked resources, such as JSON-LD context files, in production settings. This is expected to increase user choice, scalability, and decentralized upgrades in the ecosystem over time. Authors of such applications are advised to read the security and privacy sections of this document for further considerations. + +For further information regarding processing of JSON-LD contexts and vocabularies, see [Verifiable Credentials v2.0: Base Context](https://www.w3.org/TR/vc-data-model-2.0/#base-context) and [Verifiable Credentials v2.0: Vocabularies](https://www.w3.org/TR/vc-data-model-2.0/#vocabularies). + +#### 2.4.1 Validating Contexts + +[](#validating-contexts) + +It is necessary to ensure that a consuming application has explicitly approved of the types, and therefore the semantics, of input documents that it will process. Not checking JSON-LD context values against known good values can lead to security vulnerabilities, due to variance in the semantics that they convey. Applications *MUST* use the algorithm in Section [4.6 Context Validation](#context-validation), or one that achieves equivalent protections, to validate contexts in a [conforming secured document](#dfn-conforming-secured-document). Context validation *MUST* be run *after* running the applicable algorithm in either Section [4.4 Verify Proof](#verify-proof) or Section [4.5 Verify Proof Sets and Chains](#verify-proof-sets-and-chains). + +While the algorithm described in Section [4.6 Context Validation](#context-validation) provides one way of checking context values, and one optional way of safely processing unknown context values, implementers *MAY* use alternative approaches, or a different ordering of the steps, that provide the same protections. + +For example, if no JSON-LD processing is to occur, then, rather than performing this check, an application could follow the guidance in whatever trusted documentation is provided out of band for properly understanding the semantics of that type of document. + +Another approach would be to configure an application to use a JSON-LD Context loader, sometimes referred to as a document loader, to use only local copies of approved context files. This would guarantee that neither the context files nor their cryptographic hashes would ever change, effectively resulting in the same result as the algorithm in Section [4.6 Context Validation](#context-validation). + +Another alternative approach, also effectively equivalent to the algorithm in Section [4.6 Context Validation](#context-validation), would be for an application to keep a list of well known context URLs and their associated approved cryptographic hashes, without storing every context file locally. This would allow these contexts to be safely loaded from the network without compromising the security expectations of the application. + +Yet another valid approach would be for a transmitting application to [compact](https://www.w3.org/TR/json-ld11-api/#compaction-algorithm) a document to exactly what a receiving application requests, via a protocol such as one requesting a [verifiable presentation](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-presentation), omitting additional sender-specific context values that were used when securing the original document. As long as the cryptography suite\'s verification algorithm provides a successful verification result, such transformations are valid and would result in full URLs for terms that were previously compacted by the omitted context. That is, a term that was previously compacted to `foo` based on a sender-supplied context that is unknown to a receiver (e.g., \``https://ontology.example/v1`) would instead be \"expanded\" to a URL like `https://ontology.example#foo`, which would then be \"compacted\" to the same URL, once the unknown context is omitted and the JSON-LD compaction algorithm is applied by the receiving application. + +#### 2.4.2 Context Injection + +[](#context-injection) + +The `@context` property is used to ensure that implementations are using the same semantics when terms in this specification are processed. For example, this can be important when properties like `type` are processed and its value, such as `DataIntegrityProof`, are used. + +When an application is securing a document, if an `@context` property is not provided in the document or the Data Integrity terms used in the document are not mapped by existing values in the `@context` property, implementations *SHOULD* inject or append an `@context` property with a value of `https://w3id.org/security/data-integrity/v2` or one or more contexts with at least the same declarations, such as the Verifiable Credential Data Model v2.0 context (`https://www.w3.org/ns/credentials/v2`). + +Implementations that do not intend to use JSON-LD processing *MAY* choose to not include an `@context` declaration at the top-level of the document. However, if an `@context` declaration is not included, extensions (such as the addition of new properties) related to this specification or corresponding cryptosuites *MUST NOT* be made. + +#### 2.4.3 Securing Data Losslessly + +[](#securing-data-losslessly) + +HTML processors are designed to continue processing if recoverable errors are detected. JSON-LD processors operate in a similar manner. This design philosophy was meant to ensure that developers could use only the parts of the JSON-LD language that they find useful, without causing the processor to throw errors on things that might not be important to the developer. Among other effects, this philosophy led to JSON-LD processors being designed to not throw errors, but rather warn developers, when encountering things such as undefined terms. + +When converting from JSON-LD to an RDF Dataset, such as when canonicalizing a document \[[RDF-CANON](#bib-rdf-canon "RDF Dataset Canonicalization")\], undefined terms and relative URLs can be dropped silently. When values are dropped, they are not protected by a digital proof. This creates a mismatch of expectations, where a developer, who is unaware of how a JSON-LD processor works, might think that certain data was being secured, and then be surprised to find that it was not, when no error was thrown. This specification requires that any recoverable loss of data when performing JSON-LD transformations result in an error, to avoid a mismatch in the security expectations of developers. + +Implementations that use JSON-LD processing, such as RDF Dataset Canonicalization \[[RDF-CANON](#bib-rdf-canon "RDF Dataset Canonicalization")\], *MUST* throw an error, which *SHOULD* be `DATA_LOSS_DETECTION_ERROR`, when data is dropped by a JSON-LD processor, such as when an undefined term is detected in an input document. + +Similarly, since [conforming secured documents](#dfn-conforming-secured-document) can be transferred from one security domain to another, [conforming processors](#dfn-conforming-processor) that process the [conforming secured document](#dfn-conforming-secured-document) cannot assume any particular base URL for the document. When deserializing to RDF, implementations *MUST* ensure that the base URL is set to null. + +#### 2.4.4 Datatypes + +[](#datatypes) + +This section defines datatypes that are used by this specification. + +##### 2.4.4.1 The `cryptosuiteString` Datatype + +[](#cryptosuiteString) + +This specification encodes cryptographic suite identifiers as enumerable strings, which is useful in processes that need to efficiently encode such strings, such as compression algorithms. In environments that support data types for [string](https://infra.spec.whatwg.org/#string) values, such as RDF \[[RDF-CONCEPTS](#bib-rdf-concepts "Resource Description Framework (RDF): Concepts and Abstract Syntax")\], cryptographic identifier content is indicated using a literal value whose datatype is set to `https://w3id.org/security#cryptosuiteString`. + +The `cryptosuiteString` datatype is defined as follows: + +The URL denoting this datatype +: `https://w3id.org/security#cryptosuiteString` + +The lexical space +: The union of all cryptosuite strings, expressed using American Standard Code for Information Interchange \[[ASCII](#bib-ascii "ISO/IEC 646:1991, Information technology -- ISO 7-bit coded character set for information interchange")\] strings, that are defined by the collection of all Data Integrity cryptosuite specifications. + +The value space +: The union of all cryptosuite types that are expressed using the `cryptosuite` property, as defined in Section [3.1 DataIntegrityProof](#dataintegrityproof). + +The lexical-to-value mapping +: Any element of the lexical space is mapped to the result of parsing it into an internal representation that uniquely identifies the cryptosuite type from all other possible cryptosuite types. + +The canonical mapping +: Any element of the value space is mapped to the corresponding string in the lexical space. + +### 2.5 Relationship to Linked Data + +[](#relationship-to-linked-data) + +The term Linked Data is used to describe a recommended best practice for exposing, sharing, and connecting information on the Web using standards, such as URLs, to identify things and their properties. When information is presented as Linked Data, other related information can be easily discovered and new information can be easily linked to it. Linked Data is extensible in a decentralized way, greatly reducing barriers to large scale integration. + +With the increase in usage of Linked Data for a variety of applications, there is a need to be able to verify the authenticity and integrity of Linked Data documents. This specification adds authentication and integrity protection to data documents through the use of mathematical proofs without sacrificing Linked Data features such as extensibility and composability. + +Note: Use of Linked Data is an optional feature + +While this specification provides mechanisms to digitally sign Linked Data, the use of Linked Data is not necessary to gain some of the advantages provided by this specification. + +### 2.6 Relationship to Verifiable Credentials + +[](#relationship-to-verifiable-credentials) + +Cryptographic suites that implement this specification can be used to secure [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) and [verifiable presentations](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-presentation). Implementers that are addressing those use cases are cautioned that additional checks might be appropriate when processing those types of documents. + +There are some use cases where it is important to ensure that the [verification method](#dfn-verification-method) used in a proof is associated with the [`issuer`](https://www.w3.org/TR/vc-data-model-2.0/#issuer) in a [verifiable credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential), or the [`holder`](https://www.w3.org/TR/vc-data-model-2.0/#dfn-holders) in a [verifiable presentation](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-presentation), during the process of [validation](https://www.w3.org/TR/vc-data-model-2.0/#issuer-0). One way to check for such an association is to ensure that the value of the `controller` property of a proof\'s [verification method](#dfn-verification-method) matches the URL value used to identify the [`issuer`](https://www.w3.org/TR/vc-data-model-2.0/#issuer) or [`holder`](https://www.w3.org/TR/vc-data-model-2.0/#dfn-holders), respectively, and that the verification method is expressed under a verification relationship that is acceptable given the proof\'s purpose. This particular association indicates that the [`issuer`](https://www.w3.org/TR/vc-data-model-2.0/#issuer) or [`holder`](https://www.w3.org/TR/vc-data-model-2.0/#dfn-holders), respectively, is the controller of the [verification method](#dfn-verification-method) used to verify the proof. + +Document authors and implementers are advised to understand the difference between the validity period of a [proof](#proofs), which is expressed using the [`created`](#dfn-created) and [`expires`](#defn-proof-expires) properties, and the validity period of a [credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-credential), which is expressed using the [`validFrom`](https://www.w3.org/TR/vc-data-model-2.0/#defn-validFrom) and [`validUntil`](https://www.w3.org/TR/vc-data-model-2.0/#defn-validUntil) properties. While these properties might sometimes express the same validity periods, at other times they might not be aligned. When verifying a [proof](#proofs), it is important to ensure that the time of interest (which might be the current time or any other time) is within the validity period for the proof (that is, between [`created`](#dfn-created) and [`expires`](#defn-proof-expires) ). When [validating](https://www.w3.org/TR/vc-data-model-2.0/#validation) a [verifiable credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential), it is important to ensure that the time of interest is within the validity period for the [credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-credential) (that is, betweeen [`validFrom`](https://www.w3.org/TR/vc-data-model-2.0/#defn-validFrom) and [`validUntil`](https://www.w3.org/TR/vc-data-model-2.0/#defn-validUntil)). Note that a failure to validate either the validity period for the [proof](#proofs), or the validity period for the [credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-credential), might result in accepting data that ought to have been rejected. + +Finally, implementers are also urged to understand that there is a difference between the revocation information associated with a [verifiable credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential), and the [revocation](https://www.w3.org/TR/cid-1.0/#dfn-revoked) and [expiration](https://www.w3.org/TR/cid-1.0/#defn-vm-expires) times for a [verification method](#dfn-verification-method). The [revocation](https://www.w3.org/TR/cid-1.0/#dfn-revoked) and [expiration](https://www.w3.org/TR/cid-1.0/#defn-vm-expires) times for a [verification method](#dfn-verification-method) are expressed using the `revocation` and `expires` properties, respectively; are related to events such as a [secret key](#dfn-secret-key) being compromised or expiring; and can provide timing information which might reveal details about a controller, such as their security practices or when they might have been compromised. The revocation information for a [verifiable credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) is expressed using the `credentialStatus` property; is related to events such as an individual losing the privilege that is granted by the [verifiable credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential); and does not provide timing information, which enhances privacy. + +## 3. Cryptographic Suites + +[](#cryptographic-suites) + +A [data integrity proof](#dfn-data-integrity-proof) is designed to be easy to use by developers and therefore strives to minimize the amount of information one has to remember to generate a proof. Often, just the [cryptographic suite](#dfn-cryptosuite) name (such as `eddsa-rdfc-2022`) is required from developers to initiate the creation of a proof. These [cryptographic suite](#dfn-cryptosuite)s are often created and reviewed by people that have the requisite cryptographic training to ensure that safe combinations of cryptographic primitives are used. This section specifies the requirements for authoring cryptographic suite specifications. + +The requirements for all data integrity cryptographic suite specifications are as follows: + +- The specification *MUST* be published as a human-readable document at a URL. +- The specification *MUST* identify a cryptographic suite `type` and any parameters that can be used with the suite. +- The specification *MUST* detail the [transformation algorithms](#dfn-transformation-algorithm) (if any), parameters, and other necessary details, used to modify input data into the data to be protected. +- The specification *MUST* detail the [hashing algorithms](#dfn-hashing-algorithm) parameters, and other necessary details used to perform cryptographic hashing to the data to be protected. +- The specification *MUST* detail the [proof serialization algorithms](#dfn-proof-serialization-algorithm), parameters, and other necessary details used to perform cryptographic protection of the data. +- The specification *MUST* detail the [proof verification algorithms](#dfn-proof-verification-algorithm), parameters, and other necessary details used to perform cryptographic verification of the data. +- The specification *MUST* define a data integrity cryptographic suite instantiation algorithm that accepts a set of options ([map](https://infra.spec.whatwg.org/#ordered-map) `options`) and returns a [cryptosuite instance](#dfn-data-integrity-cryptographic-suite-instance) ([struct](https://infra.spec.whatwg.org/#struct) `cryptosuite`). This algorithm *SHOULD* be listed in the [Verifiable Credential Extensions](https://w3c.github.io/vc-extensions/) document. A data integrity cryptographic suite instance [struct](https://infra.spec.whatwg.org/#struct) has the following [items](https://infra.spec.whatwg.org/#struct-item). + + createProof + : An algorithm that takes an [input document](#dfn-input-document) ([map](https://infra.spec.whatwg.org/#ordered-map) `inputDocument`) and proof options ([map](https://infra.spec.whatwg.org/#ordered-map) `options`) as input, and produces a [data integrity proof](#dfn-data-integrity-proof) ([map](https://infra.spec.whatwg.org/#ordered-map)) or an error. + + verifyProof + : An algorithm that takes a [secured data document](#dfn-secured-data-document) ([map](https://infra.spec.whatwg.org/#ordered-map) `securedDocument`) as input, and produces a cryptosuite verification result or an error. The [cryptosuite verification result](#dfn-cryptosuite-verification-result) is a [struct](https://infra.spec.whatwg.org/#struct) that contains the following [items](https://infra.spec.whatwg.org/#struct-item): + + verified + : A [boolean](https://infra.spec.whatwg.org/#boolean) that is `true` if the verification succeeded, or `false` otherwise. + + verifiedDocument + : A [map](https://infra.spec.whatwg.org/#ordered-map) that represents the [secured data document](#dfn-secured-data-document) with the verified proofs removed if [verified](#dfn-verified) is `true`, or [null](https://infra.spec.whatwg.org/#nulls) otherwise. + + The structure *MAY* contain other implementation-specific information that is useful for developers, such as debugging information. If an error is produced, the verification process failed to complete. An error, such as a network error, does not mean that a future attempt at verification would fail. +- The specification *MUST* detail any known resource starvation attack that can occur in an algorithm and provide testable mitigations against each attack. +- The specification *MUST* contain a Security Considerations section detailing security considerations specific to the cryptographic suite. +- The specification *MUST* contain a Privacy Considerations section detailing privacy considerations specific to the cryptographic suite. +- The JSON-LD context associated with the cryptographic suite *MUST* have its terms protected from unsafe redefinition, by use of the `@protected` keyword. + +A [cryptosuite instance](#dfn-data-integrity-cryptographic-suite-instance) is instantiated using a [cryptosuite instantiation algorithm](#dfn-cryptosuite-instantiation-algorithm) and is made available to algorithms in an implementation-specific manner. Implementations *MAY* use the [Verifiable Credential Extensions](https://w3c.github.io/vc-extensions/) document to discover known [cryptosuite instantiation algorithms](#dfn-cryptosuite-instantiation-algorithm). + +### 3.1 DataIntegrityProof + +[](#dataintegrityproof) + +A number of [cryptographic suites](#dfn-cryptosuite) follow the same basic pattern when expressing a [data integrity proof](#dfn-data-integrity-proof). This section specifies that general design pattern, a [cryptographic suite](#dfn-cryptosuite) type called a `DataIntegrityProof`, which reduces the burden of writing and implementing [cryptographic suites](#dfn-cryptosuite) through the reuse of design primitives and source code. + +When specifing a [cryptographic suite](#dfn-cryptosuite) that utilizes this design pattern, the `proof` value takes the following form: + +type +: The `type` property *MUST* contain the [string](https://infra.spec.whatwg.org/#string) `DataIntegrityProof`. + +cryptosuite +: The value of the `cryptosuite` property *MUST* be a [string](https://infra.spec.whatwg.org/#string) that identifies the [cryptographic suite](#dfn-cryptosuite). If the processing environment supports [string](https://infra.spec.whatwg.org/#string) subtypes, the subtype of the `cryptosuite` value *MUST* be the `https://w3id.org/security#cryptosuiteString` subtype. + +proofValue +: The `proofValue` property *MUST* be used, as specified in Section [2.1 Proofs](#proofs). + +[Cryptographic suite](#dfn-cryptosuite) designers *MUST* use mandatory `proof` value properties defined in Section [2.1 Proofs](#proofs), and *MAY* define other properties specific to their cryptographic suite. + +Note: Design Patterns of Legacy Cryptographic Suites + +One of the design patterns seen in Data Integrity cryptosuites from 2012 to 2020 was use of the `type` property to establish a specific type for a cryptographic suite; the [Ed25519Signature2020 cryptographic suite](https://www.w3.org/TR/vc-di-eddsa/#the-ed25519signature2020-suite) was one such specification. This led to a greater burden on cryptographic suite implementations, where every new cryptographic suite required specification of a new JSON-LD Context, resulting in a sub-optimal developer experience. A streamlined version of this design pattern emerged in 2020, such that a developer would only need to include a single JSON-LD Context to support all modern cryptographic suites. This encouraged more modern cryptosuites --- such as the EdDSA Cryptosuites \[[DI-EDDSA](#bib-di-eddsa "The Edwards Digital Signature Algorithm Cryptosuites v1.0")\] and the ECDSA Cryptosuites \[[DI-ECDSA](#bib-di-ecdsa "The Elliptic Curve Digital Signature Algorithm Cryptosuites v1.0")\] --- to be built based on the streamlined pattern described in this section.\ +\ +To improve the developer experience, authors creating new Data Integrity cryptographic suite specifications *SHOULD* use the modern pattern --- where the `type` is set to `DataIntegrityProof`; the `cryptosuite` property carries the identifier for the cryptosuite; and any cryptosuite-specific cryptographic data is encapsulated (i.e., not directly exposed as application layer data) within `proofValue`. A list of cryptographic suite specifications that are known to follow this pattern is provided in the [Securing Mechanisms section of the Verifiable Credentials Extensions](https://w3c.github.io/vc-extensions/#securing-mechanisms) document. + +## 4. Algorithms + +[](#algorithms) + +The algorithms defined below operate on documents represented as [JSON objects](https://www.rfc-editor.org/rfc/rfc8259#section-4). This specification follows the [JSON-LD 1.1 Processing Algorithms and API](https://www.w3.org/TR/json-ld11-api/) specification in representing a JSON object as a [map](https://infra.spec.whatwg.org/#ordered-map). An unsecured data document is a [map](https://infra.spec.whatwg.org/#ordered-map) that contains no proof values. An input document is an [map](https://infra.spec.whatwg.org/#ordered-map) that has not yet had the current proof added to it, but it *MAY* contain a proof value that was added to it by a previous process. A secured data document is a [map](https://infra.spec.whatwg.org/#ordered-map) that contains one or more proof values. + +Implementers *MAY* implement reasonable defaults and safeguards in addition to the algorithms below, to help mitigate developer error, excessive resource consumption, newly discovered attack models against which there is a particular protection, and other improvements. The algorithms provided below are the minimum requirements for an interoperable implementation, and developers are urged to include additional measures that could contribute to a safer and more efficient ecosystem. + +### 4.1 Processing Model + +[](#processing-model) + +The processing model used by a [conforming processor](#dfn-conforming-processor) and its application-specific software is described in this section. When software is to ensure information is tamper-evident, it performs the following steps: + +1. The software arranges the information into a document, such as a JSON or JSON-LD document. +2. If the document is a JSON-LD document, the software selects one or more JSON-LD Contexts and expresses them using the `@context` property. +3. The software selects one or more cryptography suites that meet the needs of the use case, such as one that provides full, selective, or unlinkable disclosure, using acceptable cryptographic key material. +4. The software uses the applicable algorithm(s) provided in Section [4.2 Add Proof](#add-proof) or Section [4.3 Add Proof Set/Chain](#add-proof-set-chain) to add one or more proofs. + +When software needs to use information that was transmitted to it using a mechanism described by this specification, it performs the following steps: + +1. The software transforms the incoming data into a document that can be understood by the applicable algorithm provided in Section [4.4 Verify Proof](#verify-proof) or Section [4.5 Verify Proof Sets and Chains](#verify-proof-sets-and-chains). +2. The software uses JSON Schema or an equivalent mechanism to validate that the incoming document follows an expected schema used by the application. +3. The software uses the applicable algorithm(s) provided in Section [4.4 Verify Proof](#verify-proof) or Section [4.5 Verify Proof Sets and Chains](#verify-proof-sets-and-chains) to verify the integrity of the incoming document. +4. If the document is a JSON-LD document, the software uses the algorithm provided in Section [4.6 Context Validation](#context-validation), or one providing equivalent protections, to validate all JSON-LD Context values used in the document. + +### 4.2 Add Proof + +[](#add-proof) + +The following algorithm specifies how a digital proof can be added to an [input document](#dfn-input-document), and can then be used to verify the output document\'s authenticity and integrity. Required inputs are an [input document](#dfn-input-document) ([map](https://infra.spec.whatwg.org/#ordered-map) `inputDocument`), a [cryptosuite instance](#dfn-data-integrity-cryptographic-suite-instance) ([struct](https://infra.spec.whatwg.org/#struct) `cryptosuite`), and a set of options ([map](https://infra.spec.whatwg.org/#ordered-map) `options`). Output is a [secured data document](#dfn-secured-data-document) ([map](https://infra.spec.whatwg.org/#ordered-map)) or an error. Whenever this algorithm encodes strings, it *MUST* use UTF-8 encoding. + +1. Let `proof` be the result of calling the [createProof](#dfn-createproof) algorithm specified in `cryptosuite`.`createProof` with `inputDocument` and `options` passed as a parameters. If the algorithm produces an error, the error *MUST* be propagated and *SHOULD* convey the error type. +2. If one or more of the `proof`.`type`, `proof`.`verificationMethod`, and `proof`.`proofPurpose` values is not set, an error *MUST* be raised and *SHOULD* convey an error type of [PROOF_GENERATION_ERROR](#PROOF_GENERATION_ERROR). +3. If `options` has a non-null `domain` [item](https://infra.spec.whatwg.org/#struct-item), it *MUST* be equal to `proof`.`domain` or an error *MUST* be raised and *SHOULD* convey an error type of [PROOF_GENERATION_ERROR](#PROOF_GENERATION_ERROR). +4. If `options` has a non-null `challenge` [item](https://infra.spec.whatwg.org/#struct-item), it *MUST* be equal to `proof`.`challenge` or an error *MUST* be raised and *SHOULD* convey an error type of [PROOF_GENERATION_ERROR](#PROOF_GENERATION_ERROR). +5. Let `securedDataDocument` be a copy of `inputDocument`. +6. Set `securedDataDocument`.`proof` to the value of `proof`. +7. Return `securedDataDocument` as the [secured data document](#dfn-secured-data-document). + +### 4.3 Add Proof Set/Chain + +[](#add-proof-set-chain) + +The following algorithm specifies how to incrementally add a proof to a proof set or proof chain starting with a secured document containing either a proof or proof set/chain. Required inputs are a [secured data document](#dfn-secured-data-document) ([map](https://infra.spec.whatwg.org/#ordered-map) `securedDocument`), a [cryptographic suite](#dfn-cryptosuite) ([cryptosuite instance](#dfn-data-integrity-cryptographic-suite-instance) `suite`), and a set of options ([map](https://infra.spec.whatwg.org/#ordered-map) `options`). Output is a new [secured data document](#dfn-secured-data-document) ([map](https://infra.spec.whatwg.org/#ordered-map)). Whenever this algorithm encodes strings, it *MUST* use UTF-8 encoding. + +1. Let `proof` be set to `securedDocument`.`proof`. Let `allProofs` be an empty list. If `proof` is a list, copy all the elements of `proof` to `allProofs`. If `proof` is an object add a copy of that object to `allProofs`. +2. Let the `inputDocument` be a copy of the `securedDocument` with the `proof` attribute removed. Let `output` be a copy of the `inputDocument`. +3. Let `matchingProofs` be an empty list. +4. If `options` has a `previousProof` [item](https://infra.spec.whatwg.org/#struct-item) that is a string, add the element from `allProofs` with an `id` attribute matching `previousProof` to `matchingProofs`. If a proof with `id` equal to `previousProof` does not exist in `allProofs`, an error *MUST* be raised and *SHOULD* convey an error type of [PROOF_GENERATION_ERROR](#PROOF_GENERATION_ERROR). +5. If `options` has a `previousProof` [item](https://infra.spec.whatwg.org/#struct-item) that is an array, add each element from `allProofs` with an `id` attribute that matches an element of that array. If any element of `previousProof` [list](https://infra.spec.whatwg.org/#list) has an `id` attribute that does not match the `id` attribute of any element of `allProofs`, an error *MUST* be raised and *SHOULD* convey an error type of [PROOF_GENERATION_ERROR](#PROOF_GENERATION_ERROR). +6. Set `inputDocument`.`proof` to `matchingProofs`. + Note: This step protects the document and existing proofs + + This step adds references to the [named graphs](#dfn-named-graph), as well as adding a copy of *all* the claims contained in the [proof graphs](#dfn-proof-graph). The step is critical, as it "binds" any matching proofs to the document prior to applying the current proof. The `proof` value for the document will be updated in a later step of this algorithm. +7. Run steps 1 through 6 of the algorithm in section [4.2 Add Proof](#add-proof), passing `inputDocument`, `suite`, and `options`. If no exceptions are raised, append the generated `proof` value to the `allProofs`; otherwise, raise the exception. +8. Set `output`.`proof` to the value of `allProofs`. +9. Return `output` as the new [secured data document](#dfn-secured-data-document). + +### 4.4 Verify Proof + +[](#verify-proof) + +The following algorithm specifies how to check the authenticity and integrity of a [secured data document](#dfn-secured-data-document) by verifying its digital proof. The algorithm takes as input: + +`mediaType` +: A [media type](https://mimesniff.spec.whatwg.org/#mime-type) as defined in \[[MIMESNIFF](#bib-mimesniff "MIME Sniffing Standard")\] + +`documentBytes` +: A [byte sequence](https://infra.spec.whatwg.org/#byte-sequence) whose media type is `mediaType` + +`cryptosuite` +: A [cryptosuite instance](#dfn-data-integrity-cryptographic-suite-instance) + +`expectedProofPurpose` +: An optional [string](https://infra.spec.whatwg.org/#string), used to ensure that the `proof` was generated by the proof creator for the expected reason by the verifier. See [2.2 Proof Purposes](#proof-purposes) for common values + +`domain` +: An optional [set](https://infra.spec.whatwg.org/#ordered-set) of [strings](https://infra.spec.whatwg.org/#string), used by the proof creator to lock a proof to a particular security domain, and used by the verifier to ensure that a proof is not being used across different security domains + +`challenge` +: An optional [string](https://infra.spec.whatwg.org/#string) [challenge](#dfn-challenge), used by the verifier to ensure that an attacker is not replaying previously created proofs + +This algorithm returns a verification result, a [struct](https://infra.spec.whatwg.org/#struct) whose [items](https://infra.spec.whatwg.org/#struct-item) are: + +verified +: `true` or `false` + +verifiedDocument +: [Null](https://infra.spec.whatwg.org/#nulls), if [verified](#dfn-verified-0) is `false`; otherwise, an [input document](#dfn-input-document) + +mediaType +: [Null](https://infra.spec.whatwg.org/#nulls), if [verified](#dfn-verified-0) is `false`; otherwise, a [media type](https://mimesniff.spec.whatwg.org/#mime-type), which *MAY* include [parameters](https://mimesniff.spec.whatwg.org/#parameters) + +warnings +: a [list](https://infra.spec.whatwg.org/#list) of [ProblemDetails](#dfn-problemdetails), which defaults to an empty [list](https://infra.spec.whatwg.org/#list) + +errors +: a [list](https://infra.spec.whatwg.org/#list) of [ProblemDetails](#dfn-problemdetails), which defaults to an empty [list](https://infra.spec.whatwg.org/#list) + +When a step says \"an error *MUST* be raised\", it means that a [verification result](#dfn-verification-result) *MUST* be returned with a [verified](#dfn-verified-0) value of `false` and a non-empty [errors](#dfn-errors) list. + +1. Let `securedDocument` be the result of running [parse JSON bytes to an Infra value](https://infra.spec.whatwg.org/#parse-json-bytes-to-an-infra-value) on `documentBytes`. +2. If either `securedDocument` is not a [map](https://infra.spec.whatwg.org/#ordered-map) or `securedDocument`.`proof` is not a [map](https://infra.spec.whatwg.org/#ordered-map), an error *MUST* be raised and *SHOULD* convey an error type of [PARSING_ERROR](https://www.w3.org/TR/VC-DATA-MODEL-2.0#PARSING_ERROR). +3. Let `proof` be `securedDocument`.`proof`. +4. If one or more of `proof`.`type`, `proof`.`verificationMethod`, and `proof`.`proofPurpose` does not [exist](https://infra.spec.whatwg.org/#map-exists), an error *MUST* be raised and *SHOULD* convey an error type of [PROOF_VERIFICATION_ERROR](#PROOF_VERIFICATION_ERROR). +5. If `expectedProofPurpose` was given, and it does not match `proof`.`proofPurpose`, an error *MUST* be raised and *SHOULD* convey an error type of [PROOF_VERIFICATION_ERROR](#PROOF_VERIFICATION_ERROR). +6. If `domain` was given, and it does not contain the same [strings](https://infra.spec.whatwg.org/#string) as `proof`.`domain` (treating a single [string](https://infra.spec.whatwg.org/#string) as a [set](https://infra.spec.whatwg.org/#ordered-set) containing just that [string](https://infra.spec.whatwg.org/#string)), an error *MUST* be raised and *SHOULD* convey an error type of [INVALID_DOMAIN_ERROR](#INVALID_DOMAIN_ERROR). +7. If `challenge` was given, and it does not match `proof`.`challenge`, an error *MUST* be raised and *SHOULD* convey an error type of [INVALID_CHALLENGE_ERROR](#INVALID_CHALLENGE_ERROR). +8. Let `cryptosuiteVerificationResult` be the result of running the `cryptosuite`.[verifyProof](#dfn-verifyproof) algorithm with `securedDocument` provided as input. +9. Return a [verification result](#dfn-verification-result) with [items](https://infra.spec.whatwg.org/#struct-item): + + [verified](#dfn-verified-0) + : `cryptosuiteVerificationResult`.`verified` + + [verifiedDocument](#dfn-verifieddocument-0) + : `cryptosuiteVerificationResult`.`verifiedDocument` + + [mediaType](#dfn-mediatype) + : `mediaType` + +### 4.5 Verify Proof Sets and Chains + +[](#verify-proof-sets-and-chains) + +In a [proof set](#dfn-proof-set) or [proof chain](#dfn-proof-chain), a [secured data document](#dfn-secured-data-document) has a `proof` attribute which contains a list of [proofs](#dfn-proof) (`allProofs`). The following algorithm provides one method of checking the authenticity and integrity of a [secured data document](#dfn-secured-data-document), achieved by verifying every proof in `allProofs`. Other approaches are possible, particularly if it is only desired to verify a subset of the proofs contained in `allProofs`. If another approach is taken to verify only a subset of the proofs, then it is important to note that any proof in that subset with a `previousProof` can only be considered verified if the proofs it references are also considered verified. + +Required input is a [secured data document](#dfn-secured-data-document) (`securedDocument`). A list of [verification results](#dfn-verification-result) corresponding to each proof in `allProofs` is generated, and a single combined [verification result](#dfn-verification-result) is returned as output. Implementations *MAY* return any of the other [verification result](#dfn-verification-result)s and/or any other metadata alongside the combined [verification result](#dfn-verification-result). + +1. Set `allProofs` to `securedDocument`.`proof`. +2. Set `verificationResults` to an empty list. +3. For each `proof` in `allProofs`, do the following steps: + 1. Let `matchingProofs` be an empty list. + 2. If `proof` contains a `previousProof` attribute and the value of that attribute is a [string](https://infra.spec.whatwg.org/#string), add the element from `allProofs` with an `id` attribute value matching the value of `previousProof` to `matchingProofs`. If a proof with `id` value equal to the value of `previousProof` does not exist in `allProofs`, an error *MUST* be raised and *SHOULD* convey an error type of [PROOF_VERIFICATION_ERROR](#PROOF_VERIFICATION_ERROR). If the `previousProof` attribute is a [list](https://infra.spec.whatwg.org/#list), add each element from `allProofs` with an `id` attribute value that matches the value of an element of that [list](https://infra.spec.whatwg.org/#list). If any element of `previousProof` [list](https://infra.spec.whatwg.org/#list) has an `id` attribute value that does not match the `id` attribute value of any element of `allProofs`, an error *MUST* be raised and *SHOULD* convey an error type of [PROOF_VERIFICATION_ERROR](#PROOF_VERIFICATION_ERROR). + 3. Let `inputDocument` be a copy of `securedDocument` with the proof value removed and then set `inputDocument`.`proof` to `matchingProofs`. + Note: Secure document and previous proofs + + See the note in Step 6 of Section [4.3 Add Proof Set/Chain](#add-proof-set-chain) to learn about what document properties and previous proofs this step secures. + 4. Run steps 4 through 8 of the algorithm in section [4.4 Verify Proof](#verify-proof) on `inputDocument`; if no exceptions are raised, append `cryptosuiteVerificationResult` to `verificationResults`. +4. Set `successfulVerificationResults` to an empty list. +5. Let `combinedVerificationResult` be an empty struct. Set `combinedVerificationResult`.`status` to `true`, `combinedVerificationResult`.`document` to `null`, and `combinedVerificationResult`.`mediaType` to `null`. +6. For each `cryptosuiteVerificationResult` in `verificationResults`: + 1. If `cryptosuiteVerificationResult`.`verified` is `false`, set `combinedVerificationResult`.`verified` to `false`. + 2. Otherwise, set `combinedVerificationResult`.`document` to `cryptosuiteVerificationResult`.`verifiedDocument`, set `combinedVerificationResult`.`mediaType` to `cryptosuiteVerificationResult`.`mediaType`, and append `cryptosuiteVerificationResult` to `successfulVerificationResults`. +7. If `combinedVerificationResult`.`status` is `false`, set `combinedVerificationResult`.`document` to `null` and `combinedVerificationResult`.`mediaType` to `null`. +8. Return `combinedVerificationResult`, `successfulVerificationResults`. + +### 4.6 Context Validation + +[](#context-validation) + +The following algorithm provides one mechanism that can be used to ensure that an application understands the contexts associated with a document before it executed business rules specific to the input in the document. For more rationale related to this algorithm, see Section [2.4.1 Validating Contexts](#validating-contexts). This algorithm takes inputs of a document ([map](https://infra.spec.whatwg.org/#ordered-map) `inputDocument`), a set of known JSON-LD Contexts ([list](https://infra.spec.whatwg.org/#list) `knownContext`), and a boolean to recompact when unknown contexts are detected ([boolean](https://infra.spec.whatwg.org/#boolean) `recompact`). + +This algorithm returns a context validation result, a [struct](https://infra.spec.whatwg.org/#struct) whose [items](https://infra.spec.whatwg.org/#struct-item) are: + +validated +: `true` or `false` + +validatedDocument +: [Null](https://infra.spec.whatwg.org/#nulls), if [validated](#dfn-validated) is `false`; otherwise, an [input document](#dfn-input-document) + +warnings +: a [list](https://infra.spec.whatwg.org/#list) of [ProblemDetails](#dfn-problemdetails), which defaults to an empty [list](https://infra.spec.whatwg.org/#list) + +errors +: a [list](https://infra.spec.whatwg.org/#list) of [ProblemDetails](#dfn-problemdetails), which defaults to an empty [list](https://infra.spec.whatwg.org/#list) + +The context validation algorithm is as follows: + +1. Set `result`.`validated` to `false`, `result`.`warnings` to an empty list, `result`.`errors` to an empty list, `compactionContext` to an empty list; and clone `inputDocument` to `result`.`validatedDocument`. +2. Let `contextValue` be the value of the `@context` property of `result`.`validatedDocument`, which might be undefined. +3. If `contextValue` does not deeply equal `knownContext`, any subtree in `result`.`validatedDocument` contains an `@context` property, or any URI in `contextValue` dereferences to a JSON-LD Context file that does not match a known good value or cryptographic hash, then perform the applicable action: + 1. If `recompact` is `true`, set `result`.`validatedDocument` to the result of running the [JSON-LD Compaction Algorithm](https://www.w3.org/TR/json-ld11-api/#compaction-algorithm) with the `inputDocument` and `knownContext` as inputs. If the compaction fails, add at least one error to `result`.`errors`. + 2. If `recompact` is not `true`, add at least one error to `result`.`errors`. +4. If `result`.`errors` is empty, set `result`.`validated` to `true`; otherwise, set `result`.`validated` to `false`, and remove the `document` property from `result`. +5. Return the value of `result`. + +Implementations *MAY* include additional warnings or errors that enforce further validation rules that are specific to the implementation or a particular use case. + +### 4.7 Processing Errors + +[](#processing-errors) + +The algorithms described in this specification, as well as in various cryptographic suite specifications, throw specific types of errors. Implementers might find it useful to convey these errors to other libraries or software systems. This section provides specific URLs and descriptions for the errors, such that an ecosystem implementing technologies described by this specification might interoperate more effectively when errors occur. + +When exposing these errors through an HTTP interface, implementers *SHOULD* use \[[RFC9457](#bib-rfc9457 "Problem Details for HTTP APIs")\] to encode the error data structure as a ProblemDetails [map](https://infra.spec.whatwg.org/#ordered-map). If \[[RFC9457](#bib-rfc9457 "Problem Details for HTTP APIs")\] is used: + +- The `type` value of the error object *MUST* be a URL that starts with the value `https://w3id.org/security#` and ends with the value in the section listed below. +- The `title` value *SHOULD* provide a short but specific human-readable [string](https://infra.spec.whatwg.org/#string) for the error. +- The `detail` value *SHOULD* provide a longer human-readable [string](https://infra.spec.whatwg.org/#string) for the error. + +PROOF_GENERATION_ERROR +: A request to generate a proof failed. See Section [4.2 Add Proof](#add-proof), and Section [4.3 Add Proof Set/Chain](#add-proof-set-chain). + +PROOF_VERIFICATION_ERROR +: An error was encountered during proof verification. See Section [4.4 Verify Proof](#verify-proof). + +PROOF_TRANSFORMATION_ERROR +: An error was encountered during the transformation process. + +INVALID_DOMAIN_ERROR +: The `domain` value in a proof did not match the expected value. See Section [4.4 Verify Proof](#verify-proof). + +INVALID_CHALLENGE_ERROR +: The `challenge` value in a proof did not match the expected value. See Section [4.4 Verify Proof](#verify-proof). + +## 5. Security Considerations + +[](#security-considerations) + +The following section describes security considerations that developers implementing this specification should be aware of in order to create secure software. + +### 5.1 Versioning Cryptography Suites + +[](#versioning-cryptography-suites) + +Cryptography secures information through the use of secrets. Knowledge of the necessary secret makes it computationally easy to access certain information. The same information can be accessed if a computationally-difficult, brute-force effort successfully guesses the secret. All modern cryptography requires the computationally difficult approach to remain difficult throughout time, which does not always hold due to breakthroughs in science and mathematics. That is to say that *Cryptography has a shelf life*. + +This specification plans for the obsolescence of all cryptographic approaches by asserting that whatever cryptography is in use today is highly likely to be broken over time. Software systems have to be able to change the cryptography in use over time in order to continue to secure information. Such changes might involve increasing required secret sizes or modifications to the cryptographic primitives used. However, some combinations of cryptographic parameters might actually reduce security. Given these assumptions, systems need to be able to distinguish different combinations of safe cryptographic parameters, also known as cryptographic suites, from one another. When identifying or versioning cryptographic suites, there are several approaches that can be taken which include: parameters, numbers, and dates. + +Parametric versioning specifies the particular cryptographic parameters that are employed in a cryptographic suite. For example, one could use an identifier such as `RSASSA-PKCS1-v1_5-SHA1`. The benefit to this scheme is that a well-trained cryptographer will be able to determine all of the parameters in play by the identifier. The drawback to this scheme is that most of the population that uses these sorts of identifiers are not well trained and thus will not understand that the previously mentioned identifier is a cryptographic suite that is no longer safe to use. Additionally, this lack of knowledge might lead software developers to generalize the parsing of cryptographic suite identifiers such that any combination of cryptographic primitives becomes acceptable, resulting in reduced security. Ideally, cryptographic suites are implemented in software as specific, acceptable profiles of cryptographic parameters instead. + +Numbered versioning might specify a major and minor version number such as `1.0` or `2.1`. Numbered versioning conveys a specific order and suggests that higher version numbers are more capable than lower version numbers. The benefit of this approach is that it removes complex parameters that less expert developers might not understand with a simpler model that conveys that an upgrade might be appropriate. The drawback of this approach is that its not clear if an upgrade is necessary, as software version number increases often don\'t require an upgrade for the software to continue functioning. This can lead to developers thinking their usage of a particular version is safe, when it is not. Ideally, additional signals would be given to developers that use cryptographic suites in their software that periodic reviews of those suites for continued security are required. + +Date-based versioning specifies a particular release date for a specific cryptographic suite. The benefit of a date, such as a year, is that it is immediately clear to a developer if the date is relatively old or new. Seeing an old date might prompt the developer to go searching for a newer cryptographic suite, where as a parametric or number-based versioning scheme might not. The downside of a date-based version is that some cryptographic suites might not expire for 5-10 years, prompting the developer to go searching for a newer cryptographic suite only to not find one that is newer. While this might be an inconvenience, it is one that results in safer ecosystem behavior. + +### 5.2 Protecting Application Developers + +[](#protecting-application-developers) + +Modern cryptographic algorithms provide a number of tunable parameters and options to ensure that the algorithms can meet the varied requirements of different use cases. For example, embedded systems have limited processing and memory environments and might not have the resources to generate the strongest digital signatures for a given algorithm. Other environments, like financial trading systems, might only need to protect data for a day while the trade is occurring, while other environments might need to protect data for multiple decades. To meet these needs, cryptographic algorithm designers often provide multiple ways to configure a cryptographic algorithm. + +Cryptographic library implementers often take the specifications created by cryptographic algorithm designers and specification authors and implement them such that all options are available to the application developers that use their libraries. This can be due to not knowing which combination of features a particular application developer might need for a given cryptographic deployment. All options are often exposed to application developers. + +Application developers that use cryptographic libraries often do not have the requisite cryptographic expertise and knowledge necessary to appropriately select cryptographic parameters and options for a given application. This lack of expertise can lead to an inappropriate selection of cryptographic parameters and options for a particular application. + +This specification sets the priority of constituencies to protect application developers over cryptographic library implementers over cryptographic specification authors over cryptographic algorithm designers. Given these priorities, the following recommendations are made: + +- Cryptographic algorithm designers are advised \[[RFC7696](#bib-rfc7696 "Guidelines for Cryptographic Algorithm Agility and Selecting Mandatory-to-Implement Algorithms")\] to minimize the number of options and parameters to as few as possible to ensure that cryptographic library implementers have a more easily auditable security attack surface for their software libraries. +- Cryptographic specification authors are advised to, if possible, further minimize the number of options and parameters to as few as possible to ensure cryptographic agility while also keeping the auditable security attack surface for downstream software libraries to a minimum. +- Cryptographic library implementers are advised to, if possible, provide known good combinations of options and parameters to application developers. There would ideally be two pre-set default configurations for any algorithmic class, such as Elliptic Curve Digital Signatures, with no ability to fine tune parameters and options when using these pre-sets. Library options can be provided to experts to fine tune their use of the library, use of those options by the general application developer population is to be discouraged. +- Cryptographic library implementers can provide deprecated and experimental cryptographic functionality, but are advised to only do so when explicitly requested by the developer, such as through a library option, and such that the library produces warnings that deprecated or experimental cryptography has been enabled for the application. +- Application developers are advised to choose from a number of pre-set cryptography library configurations and to avoid modifying cryptographic options and parameters, or using experimental or deprecated cryptography. + +The guidance above is meant to ensure that useful cryptographic options and parameters are provided at the lower layers of the architecture while not exposing those options and parameters to application developers who may not fully understand the balancing benefits and drawbacks of each option. + +### 5.3 Conventions for Naming Cryptography Suites + +[](#conventions-for-naming-cryptography-suites) + +Section [5.1 Versioning Cryptography Suites](#versioning-cryptography-suites) emphasized the importance of providing relatively easy to understand information concerning the timeliness of particular cryptographic suite, while section [5.2 Protecting Application Developers](#protecting-application-developers) further emphasized minimizing the number of options to be specified. Indeed, section [3. Cryptographic Suites](#cryptographic-suites) lists requirements for cryptographic suites which include detailed specification of algorithm, transformation, hashing, and serialization. Hence, the name of the cryptographic suite does not need to include all this detail, which implies the *parametric versioning* mentioned in section [5.1 Versioning Cryptography Suites](#versioning-cryptography-suites) is neither necessary nor desirable. + +The recommended naming convention for cryptographic suites is a string composed of a signature algorithm identifier, separated by a hyphen from an option identifier (if the cryptosuite supports incompatible implementation options), followed by a hyphen and designation of the approximate year that the suite was proposed. + +For example, the \[[DI-EDDSA](#bib-di-eddsa "The Edwards Digital Signature Algorithm Cryptosuites v1.0")\] is based on EdDSA digital signatures, supports two incompatible options based on canonicalization approaches, and was proposed in roughly the year 2022, so it would have two different cryptosuite names: "eddsa-rdfc-2022" and "eddsa-jcs-2022". + +Although the \[[DI-ECDSA](#bib-di-ecdsa "The Elliptic Curve Digital Signature Algorithm Cryptosuites v1.0")\] is based on ECDSA digital signatures, supports the same two incompatible canonicalization approaches as \[[DI-EDDSA](#bib-di-eddsa "The Edwards Digital Signature Algorithm Cryptosuites v1.0")\], and supports two different levels of security (128 bit and 192 bit) via two alternative sets of elliptic curves and hashes, it has only two cryptosuite names: "ecdsa-rdfc-2019" and "ecdsa-jcs-2019". The security level and corresponding curves and hashes are determined from the multi-key format of the public key used in validation. + +### 5.4 Agility and Layering + +[](#agility-and-layering) + +Cryptographic agility is a practice by which one designs *frequently connected* information security systems to support *switching between multiple cryptographic primitives and/or algorithms*. The primary goal of cryptographic agility is to enable systems to rapidly adapt to new cryptographic primitives and algorithms without making disruptive changes to the systems\' infrastructure. Thus, when a particular cryptographic primitive, such as the SHA-1 algorithm, is determined to be no longer safe to use, systems can be reconfigured to use a newer primitive via a simple configuration file change. + +Cryptographic agility is most effective when the client and the server in the information security system are in regular contact. However, when the messages protected by a particular cryptographic algorithm are long-lived, as with [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential), and/or when the client (holder) might not be able to easily recontact the server (issuer), then cryptographic agility does not provide the desired protections. + +Cryptographic layering is a practice where one designs *rarely connected* information security systems to *employ multiple primitives and/or algorithms at the same time*. The primary goal of cryptographic layering is to enable systems to survive the failure or one or more cryptographic algorithms or primitives without losing cryptographic protection on the payload. For example, digitally signing a single piece of information using RSA, ECDSA, and Falcon algorithms in parallel would provide a mechanism that could survive the failure of two of these three digital signature algorithms. When a particular cryptographic protection is compromised, such as an RSA digital signature using 768-bit keys, systems can still utilize the non-compromised cryptographic protections to continue to protect the information. Developers are urged to take advantage of this feature for all signed content that might need to be protected for a year or longer. + +This specification provides for both forms of agility. It provides for cryptographic agility, which allows one to easily switch from one algorithm to another. It also provides for cryptographic layering, which allows one to simultaneously use multiple cryptographic algorithms, typically in parallel, such that any of those used to protect information can be used without reliance on or requirement of the others, while still keeping the digital proof format easy to use for developers. + +### 5.5 Safer Abstractions + +[](#safer-abstractions) + +A [proof](#dfn-proof) contains a `proofValue`, in which a number of parameters related to a cryptographic proof can be embedded. For example, the selective disclosure algorithms in the [Data Integrity ECDSA Cryptosuites v1.0](https://www.w3.org/TR/vc-di-ecdsa/) specification include multiple cryptographic signatures in the `proofValue`, one for every item that is selectively disclosable. This has been done to make the technology easier and safer to use by application developers. + +This specification urges specification authors to use a single value to abstract information that is rarely needed by the application layer. Much like a `data:` URL expressing an image encapsulates many of the image rendering parameters into a single value, the `proofValue` property (and other similar properties) abstracts information that is not useful to an application developer in order to simplify identification of fields that *are* important to the application. Abstracting information in this way leads to a data structure that is easier for developers to work with while being less susceptible to, for instance, accidental corruption due to a programming error that adds or removes a critical property, negatively impacting the cryptographic layer. + +The design of data integrity in this specification abstracts information that is generally only useful to the cryptographic layer into a single property to ease the burden on application developers and to enhance the security of the system. + +### 5.6 Transformations + +[](#transformations) + +At times, it is beneficial to transform the data being protected during the cryptographic protection process. Such \"in-line\" transformation can enable a particular type of cryptographic protection to be agnostic to the data format it is carried in. For example, some Data Integrity cryptographic suites utilize RDF Dataset Canonicalization \[[RDF-CANON](#bib-rdf-canon "RDF Dataset Canonicalization")\] which transforms the initial representation into a canonical form \[[N-QUADS](#bib-n-quads "RDF 1.1 N-Quads")\] that is then serialized, hashed, and digitally signed. As long as any syntax expressing the protected data can be transformed into this canonical form, the digital signature can be verified. This enables the same digital signature over the information to be expressed in JSON, CBOR, YAML, and other compatible syntaxes without having to create a cryptographic proof for every syntax. + +Being able to express the same digital signature across a variety of syntaxes is beneficial because systems often have native data formats with which they operate. For example, some systems are written against JSON data, while others are written against CBOR data. Without transformation, systems that process their data internally as CBOR are required to store the digitally signed data structures as JSON (or vice-versa). This leads to double-storing data and can lead to increased security attack surface if the unsigned representation stored in databases accidentally deviates from the signed representation. By using transformations, the digital proof can live in the native data format to help prevent otherwise undetectable database drift over time. + +This specification is designed to avoid requiring the duplication of signed information by utilizing \"in-line\" data transformations. Application developers are urged to work with cryptographically protected data in the native data format for their application and not separate storage of cryptographic proofs from the data being protected. Developers are also urged to regularly confirm that the cryptographically protected data has not been tampered with as it is written to and read from application storage. + +Some transformations, such as RDF Dataset Canonicalization \[[RDF-CANON](#bib-rdf-canon "RDF Dataset Canonicalization")\], have mitigations for input data sets that can be used by attackers to consume excessive processing cycles. This class of attack is called [dataset poisoning](https://www.w3.org/TR/rdf-canon/#dataset-poisoning), and all modern RDF Dataset canonicalizers are required to detect these sorts of bad inputs and halt processing. The test suites for RDF Dataset Canonicalization includes such poisoned datasets to ensure that such mitigations exist in all conforming implementations. Generally speaking, cryptographic suite specifications that use transformations are required to mitigate these sorts of attacks, and implementers are urged to ensure that the software libraries that they use enforce these mitigations. These attacks are in the same general category as any resource starvation attack, such as HTTP clients that deliberately slow connections, thus starving connections on the server. Implementers are advised to consider these sorts of attacks when implementing defensive security strategies. + +### 5.7 Protected Information + +[](#protected-information) + +The data that is protected by any [data integrity proof](#dfn-data-integrity-proof) is the [transformed data](#dfn-transformation). [Transformed data](#dfn-transformation) is generated by a [transformation algorithm](#dfn-transformation-algorithm) that is specified by a particular [cryptosuite](#dfn-cryptosuite). This protection mechanism differs from some more traditional digital signature mechanisms that do not perform any sort of [transformation](#dfn-transformation) on the input data. The benefits of [transformation](#dfn-transformation) are detailed in Section [5.6 Transformations](#transformations). + +For example, [cryptosuites](#dfn-cryptosuite) such as [ecdsa-jcs-2019](https://www.w3.org/TR/vc-di-ecdsa/#ecdsa-jcs-2019) and [eddsa-jcs-2022](https://www.w3.org/TR/vc-di-eddsa/#eddsa-jcs-2022) use the [JSON Canonicalization Scheme (JCS)](https://www.rfc-editor.org/rfc/rfc8785) to [transform](#dfn-transformation) the data to canonicalized JSON, which is then cryptographically hashed and digitally signed. One benefit of this approach is that adding or removing formatting characters that do not impact the meaning of the information being signed, such as spaces, tabs, and newlines, does not invalidate the digital signature. More traditional digital signature mechanisms do not have this capability. + +Other [cryptosuites](#dfn-cryptosuite) such as [ecdsa-rdfc-2019](https://www.w3.org/TR/vc-di-ecdsa/#ecdsa-rdfc-2019) and [eddsa-rdfc-2022](https://www.w3.org/TR/vc-di-eddsa/#eddsa-rdfc-2022) use [RDF Dataset Canonicalization](https://www.w3.org/TR/rdf-canon/) to [transform](#dfn-transformation) the data to canonicalized N-Quads \[[N-QUADS](#bib-n-quads "RDF 1.1 N-Quads")\], which is then cryptographically hashed and digitally signed. One benefit of this approach is that the cryptographic signature is portable to a variety of different syntaxes, such as JSON, YAML, and CBOR, without invalidating the signature. More traditional cryptographic signature mechanisms do not have this capability. + +Implementers and developers are urged to not trust information that contains a [data integrity proof](#dfn-data-integrity-proof) unless the proof has been [verified](#dfn-verified) and the verified data is provided in a return value from a software library that has confirmed that all data returned has been successfully protected. + +### 5.8 Data Opacity + +[](#data-opacity) + +The inspectability of application data has effects on system efficiency and developer productivity. When cryptographically protected application data, such as base-encoded binary data, is not easily processed by application subsystems, such as databases, it increases the effort of working with the cryptographically protected information. For example, a cryptographically protected payload that can be natively stored and indexed by a database will result in a simpler system that: + +- benefits from utilizing existing industry-standard database features with no changes to the protected information, +- avoids the complexity of duplicating data where one copy of the data preserves the message and digital signature, while the other copy only stores and indexes the message and is what drives system behaviour, +- avoids the complexity of bespoke solutions that have to structurally modify the protected information, such as serializing and deserializing nested digitally signed data that has multiple nested base-encoded payloads. + +Similarly, a cryptographically protected payload that can be processed by multiple upstream networked systems increases the ability to properly layer security architectures. For example, if upstream systems do not have to repeatedly decode the incoming payload, it increases the ability for a system to distribute processing load by specializing upstream subsystems to actively combat attacks. While a digital signature needs to always be checked before taking substantive action, other upstream checks can be performed on transparent payloads --- such as identifier-based rate limiting, signature expiration checking, or nonce/challenge checking --- to reject obviously bad requests. + +Additionally, if a developer is not able to easily view data in a system, the ability to easily audit or debug system correctness is hampered. For example, requiring application developers to cut-and-paste base-encoded application data makes development more challenging and increases the chances that obvious bugs will be missed because every message needs to go through a manually operated base-decoding tool. + +There are times, however, where the correct design decision is to make data opaque. Data that does not need to be processed by other application subsystems, as well as data that does not need to be modified or accessed by an application developer, can be serialized into opaque formats. Examples include digital signature values, cryptographic key parameters, and other data fields that only need to be accessed by a cryptographic library and need not be modified by the application developer. There are also examples where data opacity is appropriate when the underlying subsystem does not expose the application developer to the underlying complexity of the opaque data, such as databases that perform encryption at rest. In these cases, the application developer continues to develop against transparent application data formats while the database manages the complexity of encrypting and decrypting the application data to and from long-term storage. + +This specification strives to provide an architecture where application data remains in its native format and is not made opaque, while other cryptographic data, such as digital signatures, are kept in their opaque binary encoded form. Cryptographic suite implementers are urged to consider appropriate use of data opacity when designing their suites, and to weigh the design trade-offs when making application data opaque versus providing access to cryptographic data at the application layer. + +### 5.9 Verification Method Binding + +[](#verification-method-binding) + +Implementers ensure that a [verification method](#dfn-verification-method) is bound to a particular controller by going from the definition of the [verification method](#dfn-verification-method) to the [controlled identifier document](#dfn-controlled-identifier-document), and then ensuring that the [controlled identifier document](#dfn-controlled-identifier-document) also contains a reference to the [verification method](#dfn-verification-method). This process is described in the algorithm for [retrieving a verification method](https://www.w3.org/TR/cid-1.0/#retrieve-verification-method). + +### 5.10 Verification Relationship Validation + +[](#verification-relationship-validation) + +When an implementation is [verifying a proof](#verify-proof), it is imperative that it verify not only that the [verification method](#dfn-verification-method) used to generate the proof is listed in the [controlled identifier document](#dfn-controlled-identifier-document), but also that it was intended to be used to generate the proof that is being verified. This process is known as \"verification relationship validation\". + +The process of validating a verification relationship is outlined in Section [3.3 Retrieve Verification Method](https://www.w3.org/TR/cid-1.0/#retrieve-verification-method) of the [Controlled Identifiers v1.0](https://www.w3.org/TR/cid-1.0/) specification. + +This process is used to ensure that cryptographic material, such as a private cryptographic key, is not misused by application to an unintended purpose. An example of cryptographic material misuse would be if a private cryptographic key meant to be used to issue a [verifiable credential](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) was instead used to log into a website (that is, for authentication). Not checking a verification relationship is dangerous because the restriction and protection profile for some cryptographic material could be determined by its intended use. For example, some applications could be trusted to use cryptographic material for only one purpose, or some cryptographic material could be more protected, such as through storage in a hardware security module in a data center versus as an unencrypted file on a laptop. + +### 5.11 Proof Purpose Validation + +[](#proof-purpose-validation) + +When an implementation is [verifying a proof](#verify-proof), it is imperative that it verify that the [proof purpose](#dfn-proof-purpose) match the intended use. + +This process is used to ensure that proofs are not misused by an application for an unintended purpose, as this is dangerous for the proof creator. An example of misuse would be if a proof that stated its purpose was for securing assertions in [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) was instead used for [authentication](#dfn-authentication) to log into a website. In this case, the proof creator attached proofs to any number of [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) that they expected to be distributed to an unbounded number of other parties. Any one of these parties could log into a website as the proof creator if the website erroneously accepted such a proof as [authentication](#dfn-authentication) instead of its intended purpose. + +### 5.12 Canonicalization Method Security + +[](#canonicalization-method-security) + +The way in which a transformation, such as canonicalization, is performed can affect the security characteristics of a system. Selecting the best canonicalization mechanisms depends on the use case. Often, the simplest mechanism that satisfies the desired security requirements is the best choice. This section attempts to provide simple guidance to help implementers choose between the two main canonicalization mechanisms referred to in this specification, namely JSON Canonicalization Scheme \[[RFC8785](#bib-rfc8785 "JSON Canonicalization Scheme (JCS)")\] and RDF Dataset Canonicalization \[[RDF-CANON](#bib-rdf-canon "RDF Dataset Canonicalization")\]. + +If an application only uses JSON and does not depend on any form of RDF semantics, then using a cryptography suite that uses JSON Canonicalization Scheme \[[RFC8785](#bib-rfc8785 "JSON Canonicalization Scheme (JCS)")\] is an attractive approach. + +If an application uses JSON-LD and needs to secure the semantics of the document, then using a cryptography suite that uses RDF Dataset Canonicalization \[[RDF-CANON](#bib-rdf-canon "RDF Dataset Canonicalization")\] is an attractive approach. + +Implementers are also advised that other mechanisms that perform no transformations are available, that secure the data by wrapping it in a cryptographic envelope instead of embedding the proof in the data, such as JWTs \[[RFC7519](#bib-rfc7519 "JSON Web Token (JWT)")\] and CWTs \[[RFC8392](#bib-rfc8392 "CBOR Web Token (CWT)")\]. These approaches have simplicity advantages in some use cases, at the expense of some of the benefits provided by the approach detailed in this specification. + +### 5.13 Canonicalization Method Correctness + +[](#canonicalization-method-correctness) + +One of the algorithmic processes used by this specification is canonicalization, which is a type of [transformation](#dfn-transformation). Canonicalization is the process of taking information that might be expressed in a variety of semantically equivalent ways as input, and expressing all output in a single way, called a \"canonical form\". + +The security of a resulting [data integrity proof](#dfn-data-integrity-proof) that utilizes canonicalization is highly dependent on the correctness of the algorithm. For example, if a canonicalization algorithm converts two inputs that have different meanings into the same output, then the author\'s intentions can be misrepresented to a [verifier](#dfn-verifier). This can be used as an attack vector by adversaries. + +Additionally, if semantically relevant information in an input is not present in the output, then an attacker could insert such information into a message without causing proof verification to fail. This is similar to another transformation that is commonly used when cryptographically signing messages: cryptographic hashing. If an attacker is able to produce the same cryptographic hash from a different input, then the cryptographic hash algorithm is not considered secure. + +Implementers are strongly urged to ensure proper vetting of any canonicalization algorithms to be used for [transformation](#dfn-transformation) of input to a [hashing](#dfn-hashing) process. Proper vetting includes, at a minimum, association with a peer reviewed mathematical proof of algorithm correctness; multiple implementations and vetting by experts in a standards setting organization is preferred. Implementers are strongly urged not to invent or use new mechanisms unless they have formal training in information canonicalization and/or access to experts in the field who are capable of producing a peer reviewed mathematical proof of algorithm correctness. + +### 5.14 Network Requests + +[](#network-requests) + +This specification is designed in such a way that no network requests are required when verifying a proof on a [conforming secured document](#dfn-conforming-secured-document). Readers might note, however, that [JSON-LD contexts](#data-model) and [verification methods](#dfn-verification-method) can contain URLs that might be retrieved over a network connection. This concern exists for any URL that might be loaded from the network during or after verification. + +To the extent possible, implementers are urged to permanently or aggressively cache such information to reduce the attack surface on an implementation that might need to fetch such URLs over the network. For example, caching techniques for [JSON-LD contexts](#data-model) are described in Section [2.4 Contexts and Vocabularies](#contexts-and-vocabularies), and some [verification methods](#dfn-verification-method), such as `did:key` \[[DID-KEY](#bib-did-key "The did:key Method")\], do not need to be fetched from the network at all. + +When it is not possible to use cached information, such as when a specific HTTP URL-based instance of a [verification method](#dfn-verification-method) is encountered for the first time, implementers are cautioned to use defensive measures to mitigate [denial-of-service attacks](https://en.wikipedia.org/wiki/Denial-of-service_attack) during any process that might fetch a resource from the network. + +### 5.15 Other Security Considerations + +[](#other-security-considerations) + +Since the technology to secure documents described by this specification is generalized in nature, the security implications of its use might not be immediately apparent to readers. To understand the sort of security concerns one might need to consider in a complete software system, implementers are urged to read about how this technology is used in the [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) ecosystem \[[VC-DATA-MODEL-2.0](#bib-vc-data-model-2.0 "Verifiable Credentials Data Model v2.0")\]; see the section on [Verifiable Credential Security Considerations](https://www.w3.org/TR/vc-data-model-2.0/#security-considerations) for more information. + +## 6. Privacy Considerations + +[](#privacy-considerations) + +The following section describes privacy considerations that developers implementing this specification should be aware of in order to create privacy enhancing software. + +### 6.1 Unlinkability + +[](#unlinkability) + +When a digitally-signed payload contains data that is seen by multiple verifiers, it becomes a point of correlation. An example of such data is a shopping loyalty card number. Correlatable data can be used for tracking purposes by verifiers, which can sometimes violate privacy expectations. The fact that some data can be used for tracking might not be immediately apparent. Examples of such correlatable data include, but are not limited to, a static digital signature or a cryptographic hash of an image. + +It is possible to create a digitally-signed payload that does not have any correlatable tracking data while also providing some level of assurance that the payload is trustworthy for a given interaction. This characteristic is called unlinkability which ensures that no correlatable data are used in a digitally-signed payload while still providing some level of trust, the sufficiency of which has to be determined by each verifier. + +It is important to understand that not all use cases require or even permit unlinkability. There are use cases where linkability and correlation are required due to regulatory or safety reasons, such as correlating organizations and individuals that are shipping and storing hazardous materials. Unlinkability is useful when there is an expectation of privacy for a particular interaction. + +There are at least two mechanisms that can provide some level of unlinkability. The first method is to ensure that no data value used in the message is ever repeated in a future message. The second is to ensure that any repeated data value provides adequate herd privacy such that it becomes practically impossible to correlate the entity that expects some level of privacy in the interaction. + +A variety of methods can be used to achieve unlinkability. These methods include ensuring that a message is a single use bearer token with no information that can be used for the purposes of correlation, using attributes that ensure an adequate level of herd privacy, and the use of cryptosuites that enable the entity presenting a message to regenerate new signatures while not compromising the trust in the message being presented. + +### 6.2 Selective Disclosure + +[](#selective-disclosure) + +Selective disclosure is a technique that enables the recipient of a previously-signed message (that is, a message signed by its creator) to reveal only parts of the message without disturbing the verifiability of those parts. For example, one might selectively disclose a digital driver\'s license for the purpose of renting a car. This could involve revealing only the issuing authority, license number, birthday, and authorized motor vehicle class from the license. Note that in this case, the license number is correlatable information, but some amount of privacy is preserved because the driver\'s full name and address are not shared. + +Not all software or cryptosuites are capable of providing selective disclosure. If the author of a message wishes it to be selectively disclosable by its recipient, then they need to enable selective disclosure on the specific message, and both need to use a capable cryptosuite. The author might also make it mandatory to disclose certain parts of the message. A recipient that wants to selectively disclose partial content of the message needs to utilize software that is able to perform the technique. An example of a cryptosuite that supports selective disclosure is `bbs-2023`. + +It is possible to selectively disclose information in a way that does not preserve unlinkability. For example, one might want to disclose the inspection results related to a shipment, which include the shipment identifier or lot number, which might have to be correlatable due to regulatory requirements. However, disclosure of the entire inspection result might not be required as selectively disclosing just the pass/fail status could be deemed adequate. For more information on disclosing information while preserving privacy, see Section [6.1 Unlinkability](#unlinkability). + +### 6.3 Previous Proofs + +[](#previous-proofs) + +When using the `previousProof` feature defined in [2.1.2 Proof Chains](#proof-chains), implementations are required to digitally sign over one or more previous proofs, so as to include them in the secured payload. This inevitably exposes information related to each entity that added a previous proof. + +At minimum, the [verification method](#dfn-verification-method) for the previous proof, such as a public key, is seen by the creator of the next proof in a proof chain. This can be a privacy concern if the creator of the previous proof did not intend to be included in a proof chain, but is an inevitable outcome when adding a non-repudiable digital signature to a document of any kind. + +It is possible to use more advanced cryptographic mechanisms, such as a [group signature](https://en.wikipedia.org/wiki/Group_signature), to hide the identity of the signer of a message, and it is also possible for a Data Integrity cryptographic suite to mitigate this privacy concern. + +### 6.4 Fingerprinting Network Requests + +[](#fingerprinting-network-requests) + +Fingerprinting concerns exist for any URL that might be loaded from the network during or after [proof verification](#verify-proof). This specification is designed in such a way that no network requests are necessary when verifying a proof on a [conforming secured document](#dfn-conforming-secured-document). Readers might note, however, that [JSON-LD contexts](#data-model) and [verification methods](#dfn-verification-method) can contain resource URLs that might be retrieved over a network connection leading to fingerprinting concerns. + +For example, creators of [conforming secured documents](#dfn-conforming-secured-document) might craft unique per-document URLs for [JSON-LD contexts](#data-model) and [verification methods](#dfn-verification-method). When verifying such a document, a verifier fetching that information from the network would reveal their interest in the [conforming secured document](#dfn-conforming-secured-document) to the creator of the document, which might lead to a mismatch in privacy expectations for any entity that is not the creator of the document. + +Implementers are urged to follow the guidance in Section [5.14 Network Requests](#network-requests) on URL caching and implementing defensively when fetching URLs from the network. Usage of techniques such as [Oblivious HTTP](https://datatracker.ietf.org/doc/html/draft-ietf-ohai-ohttp) to retrieve resources from the network, without revealing the client that is making the request, are encouraged. Additionally, heuristics might be used to determine whether creators of [conforming secured documents](#dfn-conforming-secured-document) are using fingerprinting URLs in a way that might violate privacy expectations. These heuristics could be used to display warnings to entities that might process documents containing suspected fingerprinting URLs. + +### 6.5 Canonicalization Method Privacy + +[](#canonicalization-method-privacy) + +The way in which a transformation, namely canonicalization, is performed can affect the privacy characteristics of a system. Selecting the best canonicalization mechanism depends on the use case. This section attempts to provide simple guidance to help implementers pick between the two main canonicalization mechanisms referred to in this specification, namely JSON Canonicalization Scheme \[[RFC8785](#bib-rfc8785 "JSON Canonicalization Scheme (JCS)")\] and RDF Dataset Canonicalization \[[RDF-CANON](#bib-rdf-canon "RDF Dataset Canonicalization")\], from a privacy perspective. + +If an application does not require performing a selective disclosure of information in a secured document, nor does it utilize JSON-LD, then JSON Canonicalization Scheme \[[RFC8785](#bib-rfc8785 "JSON Canonicalization Scheme (JCS)")\] is an attractive approach. + +If an application uses JSON-LD and might require selective disclosure of information in a secured document, then using a cryptography suite that uses RDF Dataset Canonicalization \[[RDF-CANON](#bib-rdf-canon "RDF Dataset Canonicalization")\] is an attractive approach. + +Implementers are also advised that other selective disclosure mechanisms that perform no transformations are available, that secure the data by wrapping it in a cryptographic envelope instead of embedding the proof in the data, such as SD-JWTs \[[SD-JWT](#bib-sd-jwt "Selective Disclosure for JWTs (SD-JWT)")\]. This approach has simplicity advantages in some use cases, at the expense of some of the benefits provided by the approach detailed in this specification. + +### 6.6 Other Privacy Considerations + +[](#other-privacy-considerations) + +Since the technology to secure documents described by this specification is generalized in nature, the privacy implications of its use might not be immediately apparent to readers. To understand the sort of privacy concerns one might need to consider in a complete software system, implementers are urged to read about how this technology is used in the [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential) ecosystem \[[VC-DATA-MODEL-2.0](#bib-vc-data-model-2.0 "Verifiable Credentials Data Model v2.0")\]; see the section on [Verifiable Credential Privacy Considerations](https://www.w3.org/TR/vc-data-model-2.0/#privacy-considerations) for more information. + +## 7. Accessibility Considerations + +[](#accessibility-considerations) + +The following section describes accessibility considerations that developers implementing this specification are urged to consider in order to ensure that their software is usable by people with different cognitive, motor, and visual needs. As a general rule, this specification is used by system software and does not directly expose individuals to information subject to accessibility considerations. However, there are instances where individuals might be indirectly exposed to information expressed by this specification and thus the guidance below is provided for those situations. + +### 7.1 Presenting Time Values + +[](#presenting-time-values) + +This specification enables the expression of dates and times related to the validity period of cryptographic proofs. This information might be indirectly exposed to an individual if a proof is processed and is detected to be outside an allowable time range. When exposing these dates and times to an individual, implementers are urged to take into account [cultural normas and locales when representing dates and times](https://www.w3.org/TR/vc-data-model-2.0/#representing-time) in display software. In addition to these considerations, presenting time values in a way that eases the cognitive burden on the individual receiving the information is a suggested best practice. + +For example, when conveying the expiration date for a particular set of digitally signed information, implementers are urged to present the time of expiration using language that is easier to understand rather than language that optimizes for accuracy. Presenting the expiration time as \"This ticket expired three days ago.\" is preferred over a phrase such as \"This ticket expired on July 25th 2023 at 3:43 PM.\" The former provides a relative time that is easier to comprehend than the latter time, which requires the individual to do the calculation in their head and presumes that they are capable of doing such a calculation. + +## A. Understanding Proof Sets and Proof Chains + +[](#understanding-proof-sets-and-proof-chains) + +*This section is non-normative.* + +Sections [2.1.1 Proof Sets](#proof-sets) and [2.1.2 Proof Chains](#proof-chains) describe how multiple proofs can be expressed in a [secured data document](#dfn-secured-data-document); that is, instead of a single [proof](#dfn-proof) included in the [secured data document](#dfn-secured-data-document), one can express multiple proofs in an [list](https://infra.spec.whatwg.org/#list) as shown in [Example 6](#example-a-proof-set-in-a-data-document) and [Example 7](#example-a-proof-chain-in-a-data-document). The elements of this [list](https://infra.spec.whatwg.org/#list) are members of a [proof set](#dfn-proof-set) and, optionally, a [proof chain](#dfn-proof-chain). The purpose of this section is to explain the intended use of each of these features and, in particular, their differing security properties. These differing security properties lead to differences in the processing in section [4.3 Add Proof Set/Chain](#add-proof-set-chain). + +This section represents [secured data documents](#dfn-secured-data-document), including their proofs, in an abbreviated manner so that the important security properties can be observed. + +Consider a scenario with three signatories: a CEO, a CFO, and a VP of Engineering. Each will need to have a public key and secret key pair for signing a document. We denote the secret/public keys of each of these signatories by *secretCEO/publicCEO*, *secretCFO/publicCFO*, and *secretVPE/publicVPE*, respectively. + +When constructing a [proof set](#dfn-proof-set) where each of the signatories signs an `inputDocument` without concern, we construct a proof symbolically as: + +[Example 9](#example-symbolic-expression-of-how-a-proof-is-created): Symbolic expression of how a proof is created + +``` nohighlight +{ + "type": "DataIntegrityProof", + "cryptosuite": "eddsa-jcs-2022", + "created": "2023-03-05T19:23:24Z", + "proofPurpose": "assertionMethod", + "verificationMethod": publicCEO, + "proofValue": signature(secretCEO, inputDocument) +} +``` + +Where *publicCEO* is used as a placeholder for a reference that resolves to the CEO\'s public key and **signature(`secretKey`, `inputDocument`)** denotes the computation of a digital signature by a particular data integrity cryptosuite using a particular secret key over a particular document. The `type`, `cryptosuite`, `created`, and `proofPurpose` attributes do not factor into our discussion so we will omit them. In particular, below we show all the proofs in a [proof set](#dfn-proof-set) on a document that has been signed by the VP of Engineering, the CFO, and the CEO: + +[Example 10](#example-symbolic-expression-of-a-proof-set): Symbolic expression of a proof set + +``` nohighlight +{ + // Remainder of secured data document not shown (above) + "proof": [{ + "verificationMethod": publicVPE, + "proofValue": signature(secretVPE, inputDocument) + }, { + "verificationMethod": publicCFO, + "proofValue": signature(secretCFO, inputDocument) + }, { + "verificationMethod": publicCEO, + "proofValue": signature(secretCEO, inputDocument) + }] +} +``` + +A [holder](https://www.w3.org/TR/vc-data-model-2.0/#dfn-holders) or any other intermediary receiving a [secured data document](#dfn-secured-data-document) containing a [proof set](#dfn-proof-set) is able to remove any of the `proof` values within the set prior to passing it on to another entity and the [secured data document](#dfn-secured-data-document) will still verify. This might or might not have been the intent. For the signatories sending a birthday card to a valued employee, using a [proof set](#dfn-proof-set) is probably fine. If we are trying to model a business process where approvals ascend the company hierarchy, this would not be ideal, since any intermediary could remove signatures from the [proof set](#dfn-proof-set) and still have it verify; for instance, in the example below, it looks like the CFO and CEO approved something without the VP of Engineering\'s concurrence. + +[Example 11](#example-removal-of-a-signature-in-a-proof-set): Removal of a signature in a proof set + +``` nohighlight +{ + // Remainder of secured data document not shown (above) + "proof": [{ + "verificationMethod": publicCFO, + "proofValue": signature(secretCFO, inputDocument) + }, { + "verificationMethod": publicCEO, + "proofValue": signature(secretCEO, inputDocument) + }] +} +``` + +It is possible to introduce a dependency between [proofs](#dfn-proof) in a [proof set](#dfn-proof-set) by setting the `id` property of each proof such that another proof can reference it. In other words, a *dependent proof* will be referenced by other *relying proofs* by using the `previousProof` property. Such *dependency chains* can have arbitrary depth. The **intent** of such a [proof chain](#dfn-proof-chain) is to model an approval chain in a business process or a notary witnessing analog signatures. + +The examples below demonstrate how a [proof chain](#dfn-proof-chain) can be constructed when the VP of Engineering signs off on the document first; based on the VP of Engineering\'s signature and a review, the CFO then signs off on the document; and finally, based on both prior signatures and a review, the CEO signs off on the document. Since others will be referring to the VP of Engineering\'s signature, we need to add an `id` to the proof. First the VP of Engineering signs the [input document](#dfn-input-document): + +[Example 12](#example-proof-chain-containing-first-proof-with-id-property-set): Proof chain containing first proof with \`id\` property set + +``` nohighlight +{ + // Remainder of secured data document not shown (above) + "proof": { + "id": "urn:proof-1", + "verificationMethod": publicVPE, + "proofValue": signature(secretVPE, inputDocument) + } +} +``` + +Next, the CFO receives the document, verifies that the VP of Engineering signed it, and signs it based on a review and on the signature of the VP of Engineering. For this, we need to set up the [proof chain](#dfn-proof-chain) by indicating a dependency on the proof in the document just received. We do this by setting the `previousProof` property of the second proof to the value `urn:proof-1`, which \"binds\" the second proof to the first proof, which is then signed. The following example shows how the dependency on the first proof is created: + +[Example 13](#example-proof-chain-containing-two-proofs): Proof chain containing two proofs + +``` nohighlight +{ + // Remainder of secured data document not shown (above) + "proof": [{ + "id": "urn:proof-1", + "verificationMethod": publicVPE, + "proofValue": signature(secretVPE, inputDocument) + }, { + "id": "urn:proof-2", + "verificationMethod": publicCFO, + "previousProof": "urn:proof-1", + "proofValue": signature(secretCFO, inputDocumentWithProof1) + }] +} +``` + +Now, when the CEO verifies the received [secured data document](#dfn-secured-data-document) with the above [proof chain](#dfn-proof-chain), they will check that the CFO signed based on the signature of the VP of Engineering. First, they will check the proof with an `id` property whose value is `urn:proof-1` against the public key of the VP of Engineering. Note that this proof is over the original document. + +Next, the CEO will check the proof with an `id` property whose value is `urn:proof-2` against the public key of the CFO. However, to make sure that the CFO signed the document with proof that the VP of Engineering had already signed, we verify this proof over the combination of the document and `urn:proof-1`. If verification is successful, the CEO signs, producing a proof over the document which includes `urn:proof-1` and `urn:proof-2`. The final [proof chain](#dfn-proof-chain) looks like this: + +[Example 14](#example-proof-chain-containing-three-proofs): Proof chain containing three proofs + +``` nohighlight +{ + // Remainder of secured data document not shown (above) + "proof": [{ + "id": "urn:proof-1", + "verificationMethod": publicVPE, + "proofValue": signature(secretVPE, inputDocument) + }, { + "id": "urn:proof-2", + "verificationMethod": publicCFO, + "previousProof": "urn:proof-1", + "proofValue": signature(secretCFO, inputDocumentWithProof1) + }, { + "id": "urn:proof-3", + "verificationMethod": publicCEO, + "previousProof": "urn:proof-2", + "proofValue": signature(secretCEO, inputDocumentWithProof2) + }] +} +``` + +The recipient of this [secured data document](#dfn-secured-data-document) then validates it in a similar way, checking each proof in the chain. + +## B. Revision History + +[](#revision-history) + +*This section is non-normative.* + +This section contains the substantive changes that have been made to this specification over time. + +Changes since the [Second Candidate Recommendation](https://www.w3.org/TR/2024/CR-vc-data-integrity-20241219/): + +- Various editorial changes in algorithms and descriptions to improve readability. +- Remove numerical error codes since implementations were not using them. +- Update to use newly published [Controlled Identifiers v1.0](https://www.w3.org/TR/cid-1.0/) specification references. + +Changes since the [First Candidate Recommendation](https://www.w3.org/TR/2023/CR-vc-data-integrity-20231121/): + +- Various editorial changes in algorithms and descriptions to improve readability. +- Moved Multikey definitions to controlled identifier document. +- Unify error handling between all Data Integrity cryptosuites. +- Ensure that the `created` proof option is not required and additional proof options are included in the generated proof. +- Add language related to context injection. +- Update proof serialization format and algorithm arguments for cryptosuite interfaces. + +Changes since the [First Public Working Draft](https://www.w3.org/TR/2022/WD-vc-data-integrity-20221110/): + +- Added a section on proof purpose validation. +- Refactored chained proof functionality. +- Added the algorithm to retrieve a verification method. +- Added `JsonWebKey` and `Multikey` definitions and context files. +- Deprecated `Ed25519Signature2020` and moved into separate specification. +- Updated Multibase and Multihash references and add text to normatively define certain Multikey values. +- Added Internationalization and Accessibility Considerations sections. +- Added cryptographic hashes for context and vocabulary files and note that those files are to be cached. +- Added section on relationship to Linked Data and [verifiable credentials](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-credential). +- Added algorithms for proof sets and chains. +- Added `nonce` and `expires` to proofs. +- Added requirement to protect terms in JSON-LD mode. +- Required cryptosuite specifications that do RDF canonicalization to abort when poison graphs are detected. +- Added section on how context injection is implemented. +- Added error definitions with anchors to specification and vocabulary. +- Added definitions for secret key expression. +- Added `revoked` and `expires` to verification methods. +- Updated proof `domain` property to allow for an array of values. +- Added `cryptosuiteString` type to proofs to enable proof compression. +- Added `digestMultibase` property and `multibase` data type for securing remote content, and guidance on adding `digestMultibase` to contexts. +- Narrowed date time values to use `dateTimeStamp`. +- Ensure that base URL is set to null when processing as RDF. +- Added requirement that `DataIntegrityProof` objects need to contain the `cryptosuite` property. + +## C. Acknowledgements + +[](#acknowledgements) + +*This section is non-normative.* + +Work on this specification has been supported by the Rebooting the Web of Trust community facilitated by Christopher Allen, Shannon Appelcline, Kiara Robles, Brian Weller, Betty Dhamers, Kaliya Young, Manu Sporny, Drummond Reed, Joe Andrieu, Heather Vescent, Kim Hamilton Duffy, Samantha Chase, Andrew Hughes, Will Abramson, Erica Connell and Eric Schuh. The participants in the Internet Identity Workshop, facilitated by Phil Windley, Kaliya Young, Doc Searls, and Heidi Nobantu Saul, also supported the refinement of this work through numerous working sessions designed to educate about, debate on, and improve this specification. + +The Working Group also thanks our Chair, Brent Zundel, our ex-Chair, Kristina Yasuda, as well as our W3C Staff Contact, Ivan Herman, for their expert management and steady guidance of the group through the W3C standardization process. + +Portions of the work on this specification have been funded by the United States Department of Homeland Security\'s Science and Technology Directorate under contracts 70RSAT20T00000029, 70RSAT21T00000016, 70RSAT23T00000005, 70RSAT20T00000010/P00001, 70RSAT20T00000029, 70RSAT21T00000016/P00001, 70RSAT23T00000005, 70RSAT23C00000030, 70RSAT23R00000006, 70RSAT24T00000011, and the National Science Foundation through NSF 22-572. The content of this specification does not necessarily reflect the position or the policy of the U.S. Government and no official endorsement should be inferred. + +The Working Group would like to thank the following individuals for reviewing and providing feedback on the specification (in alphabetical order by last name or their GitHub handle if a name was not provided): + +Will Abramson, Mahmoud Alkhraishi, Christopher Allen, Joe Andrieu, Bohdan Andriyiv, George Aristy, [Anthony](https://github.com/Anthony), Greg Bernstein, [Bob420](https://github.com/Bob420), Sarven Capadisli, Melvin Carvalho, David Chadwick, Gabe Cohen, Matt Collier, Sebastian Crane, Kim Hamilton Duffy, Snorre Lothar von Gohren Edwin, Veikko Eeva, Eric Elliott, Raphael Flechtner, Julien Fraichot, Benjamin Goering, Kyle Den Hartog, Joseph Heenan, Helge Krueger, Ivan Herman, Michael Herman, Alen Horvat, Anil John, Andrew Jones, Michael B. Jones, Rieks Joosten, Gregory K., Gregg Kellogg, Filip Kolarik, David I. Lehn, Charles E. Lehner, Christine Lemmer-Webber, Eric Lim, Dave Longley, Tobias Looker, Jer Miller, [nightpool](https://github.com/nightpool), Bert Van Nuffelen, Luis Osta, Nate Otto, George J. Padayatti, Addison Phillips, Mike Prorock, Brian Richter, Anders Rundgren, Eugeniu Rusu, Markus Sabadello, [silverpill](https://github.com/silverpill), Wesley Smith, Manu Sporny, Orie Steele, Patrick St-Louis, Henry Story, Oliver Terbu, Ted Thibodeau Jr., John Toohey, Mike Varley, Jeffrey Yasskin, Kristina Yasuda, Benjamin Young, Dmitri Zagidulin, and Brent Zundel. + +## D. References + +[](#references) + +### D.1 Normative references + +[](#normative-references) + +\[ASCII\] +: [ISO/IEC 646:1991, Information technology \-- ISO 7-bit coded character set for information interchange](https://www.ecma-international.org/publications-and-standards/standards/ecma-6/). Ecma International. URL: + +\[CID\] +: [Controlled Identifiers v1.0](https://www.w3.org/TR/cid-1.0/). Michael Jones; Manu Sporny. W3C. 15 May 2025. W3C Recommendation. URL: + +\[INFRA\] +: [Infra Standard](https://infra.spec.whatwg.org/). Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: + +\[JSON-LD11\] +: [JSON-LD 1.1](https://www.w3.org/TR/json-ld11/). Gregg Kellogg; Pierre-Antoine Champin; Dave Longley. W3C. 16 July 2020. W3C Recommendation. URL: + +\[JSON-LD11-API\] +: [JSON-LD 1.1 Processing Algorithms and API](https://www.w3.org/TR/json-ld11-api/). Gregg Kellogg; Dave Longley; Pierre-Antoine Champin. W3C. 16 July 2020. W3C Recommendation. URL: + +\[MIMESNIFF\] +: [MIME Sniffing Standard](https://mimesniff.spec.whatwg.org/). Gordon P. Hemsley. WHATWG. Living Standard. URL: + +\[RDF-CANON\] +: [RDF Dataset Canonicalization](https://www.w3.org/TR/rdf-canon/). Gregg Kellogg; Dave Longley; Dan Yamamoto. W3C. 21 May 2024. W3C Recommendation. URL: + +\[RFC2119\] +: [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119). S. Bradner. IETF. March 1997. Best Current Practice. URL: + +\[RFC8174\] +: [Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words](https://www.rfc-editor.org/rfc/rfc8174). B. Leiba. IETF. May 2017. Best Current Practice. URL: + +\[RFC8259\] +: [The JavaScript Object Notation (JSON) Data Interchange Format](https://www.rfc-editor.org/rfc/rfc8259). T. Bray, Ed. IETF. December 2017. Internet Standard. URL: + +\[RFC8785\] +: [JSON Canonicalization Scheme (JCS)](https://www.rfc-editor.org/rfc/rfc8785). A. Rundgren; B. Jordan; S. Erdtman. IETF. June 2020. Informational. URL: + +\[RFC9457\] +: [Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457). M. Nottingham; E. Wilde; S. Dalal. IETF. July 2023. Proposed Standard. URL: + +\[URL\] +: [URL Standard](https://url.spec.whatwg.org/). Anne van Kesteren. WHATWG. Living Standard. URL: + +\[VC-DATA-MODEL-2.0\] +: [Verifiable Credentials Data Model v2.0](https://www.w3.org/TR/vc-data-model-2.0/). Ivan Herman; Michael Jones; Manu Sporny; Ted Thibodeau Jr; Gabe Cohen. W3C. 15 May 2025. W3C Recommendation. URL: + +\[XMLSCHEMA11-2\] +: [W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes](https://www.w3.org/TR/xmlschema11-2/). David Peterson; Sandy Gao; Ashok Malhotra; Michael Sperberg-McQueen; Henry Thompson; Paul V. Biron et al. W3C. 5 April 2012. W3C Recommendation. URL: + +### D.2 Informative references + +[](#informative-references) + +\[DI-ECDSA\] +: [The Elliptic Curve Digital Signature Algorithm Cryptosuites v1.0](https://www.w3.org/TR/vc-di-ecdsa/). David Longley; Manu Sporny; Marty Reed. W3C Verifiable Credentials Working Group. W3C Working Draft. URL: + +\[DI-EDDSA\] +: [The Edwards Digital Signature Algorithm Cryptosuites v1.0](https://www.w3.org/TR/vc-di-eddsa/). David Longley; Manu Sporny; Dmitri Zagidulin. W3C Verifiable Credentials Working Group. W3C Working Draft. URL: + +\[DID\] +: [Decentralized Identifiers (DIDs) v1.0](https://www.w3.org/TR/did-core/). Manu Sporny; Amy Guy; Markus Sabadello; Drummond Reed. W3C. 19 July 2022. W3C Recommendation. URL: + +\[DID-KEY\] +: [The did:key Method](https://w3c-ccg.github.io/did-key-spec/). Manu Sporny; Dmitri Zagidulin; Dave Longley; Orie Steele. W3C Credentials Community Group. CG-DRAFT. URL: + +\[HTML-RDFA\] +: [HTML+RDFa 1.1 - Second Edition](https://www.w3.org/TR/html-rdfa/). Manu Sporny. W3C. 17 March 2015. W3C Recommendation. URL: + +\[LTLI\] +: [Language Tags and Locale Identifiers for the World Wide Web](https://www.w3.org/TR/ltli/). Addison Phillips. W3C. 7 October 2020. W3C Working Draft. URL: + +\[N-QUADS\] +: [RDF 1.1 N-Quads](https://www.w3.org/TR/n-quads/). Gavin Carothers. W3C. 25 February 2014. W3C Recommendation. URL: + +\[RDF-CONCEPTS\] +: [Resource Description Framework (RDF): Concepts and Abstract Syntax](https://www.w3.org/TR/rdf-concepts/). Graham Klyne; Jeremy Carroll. W3C. 10 February 2004. W3C Recommendation. URL: + +\[RFC5280\] +: [Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile](https://www.rfc-editor.org/rfc/rfc5280). D. Cooper; S. Santesson; S. Farrell; S. Boeyen; R. Housley; W. Polk. IETF. May 2008. Proposed Standard. URL: + +\[RFC7517\] +: [JSON Web Key (JWK)](https://www.rfc-editor.org/rfc/rfc7517). M. Jones. IETF. May 2015. Proposed Standard. URL: + +\[RFC7519\] +: [JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519). M. Jones; J. Bradley; N. Sakimura. IETF. May 2015. Proposed Standard. URL: + +\[RFC7696\] +: [Guidelines for Cryptographic Algorithm Agility and Selecting Mandatory-to-Implement Algorithms](https://www.rfc-editor.org/rfc/rfc7696). R. Housley. IETF. November 2015. Best Current Practice. URL: + +\[RFC8392\] +: [CBOR Web Token (CWT)](https://www.rfc-editor.org/rfc/rfc8392). M. Jones; E. Wahlstroem; S. Erdtman; H. Tschofenig. IETF. May 2018. Proposed Standard. URL: + +\[RFC9562\] +: [Universally Unique IDentifiers (UUIDs)](https://www.rfc-editor.org/rfc/rfc9562). K. Davis; B. Peabody; P. Leach. IETF. May 2024. Proposed Standard. URL: + +\[SD-JWT\] +: [Selective Disclosure for JWTs (SD-JWT)](https://datatracker.ietf.org/doc/draft-ietf-oauth-selective-disclosure-jwt/). Daniel Fett; Kristina Yasuda; Brian Campbell. The IETF OAuth Working Group. I-D. URL: + +\[SECURITY-VOCABULARY\] +: [The Security Vocabulary](https://w3id.org/security). Ivan Herman; Manu Sporny; David Longley. Verifiable Credentials Working Group. W3C Editor\'s Draft. URL: + +\[TURTLE\] +: [RDF 1.1 Turtle](https://www.w3.org/TR/turtle/). Eric Prud\'hommeaux; Gavin Carothers. W3C. 25 February 2014. W3C Recommendation. URL: + +\[VC-DI-ECDSA\] +: [Data Integrity ECDSA Cryptosuites v1.0](https://www.w3.org/TR/vc-di-ecdsa/). Manu Sporny; Dave Longley; Greg Bernstein. W3C. 15 May 2025. W3C Recommendation. URL: + +\[VC-DI-EDDSA\] +: [Data Integrity EdDSA Cryptosuites v1.0](https://www.w3.org/TR/vc-di-eddsa/). Manu Sporny; Ted Thibodeau Jr; Greg Bernstein. W3C. 15 May 2025. W3C Recommendation. URL: + +\[VC-EXTENSIONS\] +: [Verifiable Credential Extensions](https://w3c.github.io/vc-extensions/). Manu Sporny. W3C Verifiable Credentials Working Group. W3C Editor\'s Draft. URL: + +\[WEBCRYPTOAPI\] +: [Web Cryptography API](https://www.w3.org/TR/WebCryptoAPI/). Mark Watson. W3C. 26 January 2017. W3C Recommendation. URL: + +\[ZCAP\] +: [Authorization Capabilities for Linked Data](https://w3c-ccg.github.io/zcap-spec/). Credentials Community Group. CGDRAFT. URL: + +[↑](#title) + +[Permalink](#dfn-transformation) + +**Referenced in:** + +- [§ 1.1 How it Works](#ref-for-dfn-transformation-1 "§ 1.1 How it Works") +- [§ 5.7 Protected Information](#ref-for-dfn-transformation-2 "§ 5.7 Protected Information") [(2)](#ref-for-dfn-transformation-3 "Reference 2") [(3)](#ref-for-dfn-transformation-4 "Reference 3") [(4)](#ref-for-dfn-transformation-5 "Reference 4") [(5)](#ref-for-dfn-transformation-6 "Reference 5") [(6)](#ref-for-dfn-transformation-7 "Reference 6") +- [§ 5.13 Canonicalization Method Correctness](#ref-for-dfn-transformation-8 "§ 5.13 Canonicalization Method Correctness") [(2)](#ref-for-dfn-transformation-9 "Reference 2") + +[Permalink](#dfn-transformation-algorithm) + +**Referenced in:** + +- [§ 3. Cryptographic Suites](#ref-for-dfn-transformation-algorithm-1 "§ 3. Cryptographic Suites") +- [§ 5.7 Protected Information](#ref-for-dfn-transformation-algorithm-2 "§ 5.7 Protected Information") + +[Permalink](#dfn-hashing) + +**Referenced in:** + +- [§ 1.1 How it Works](#ref-for-dfn-hashing-1 "§ 1.1 How it Works") +- [§ 5.13 Canonicalization Method Correctness](#ref-for-dfn-hashing-2 "§ 5.13 Canonicalization Method Correctness") + +[Permalink](#dfn-hashing-algorithm) + +**Referenced in:** + +- [§ 3. Cryptographic Suites](#ref-for-dfn-hashing-algorithm-1 "§ 3. Cryptographic Suites") + +[Permalink](#dfn-proof-serialization-algorithm) + +**Referenced in:** + +- [§ 3. Cryptographic Suites](#ref-for-dfn-proof-serialization-algorithm-1 "§ 3. Cryptographic Suites") + +[Permalink](#dfn-proof-verification-algorithm) + +**Referenced in:** + +- [§ 3. Cryptographic Suites](#ref-for-dfn-proof-verification-algorithm-1 "§ 3. Cryptographic Suites") + +[Permalink](#dfn-conforming-secured-document) + +**Referenced in:** + +- [§ 1.3 Conformance](#ref-for-dfn-conforming-secured-document-1 "§ 1.3 Conformance") +- [§ 2.3 Resource Integrity](#ref-for-dfn-conforming-secured-document-2 "§ 2.3 Resource Integrity") [(2)](#ref-for-dfn-conforming-secured-document-3 "Reference 2") +- [§ 2.4 Contexts and Vocabularies](#ref-for-dfn-conforming-secured-document-4 "§ 2.4 Contexts and Vocabularies") +- [§ 2.4.1 Validating Contexts](#ref-for-dfn-conforming-secured-document-5 "§ 2.4.1 Validating Contexts") +- [§ 2.4.3 Securing Data Losslessly](#ref-for-dfn-conforming-secured-document-6 "§ 2.4.3 Securing Data Losslessly") [(2)](#ref-for-dfn-conforming-secured-document-7 "Reference 2") +- [§ 5.14 Network Requests](#ref-for-dfn-conforming-secured-document-8 "§ 5.14 Network Requests") +- [§ 6.4 Fingerprinting Network Requests](#ref-for-dfn-conforming-secured-document-9 "§ 6.4 Fingerprinting Network Requests") [(2)](#ref-for-dfn-conforming-secured-document-10 "Reference 2") [(3)](#ref-for-dfn-conforming-secured-document-11 "Reference 3") [(4)](#ref-for-dfn-conforming-secured-document-12 "Reference 4") + +[Permalink](#dfn-conforming-processor) + +**Referenced in:** + +- [§ 2.1 Proofs](#ref-for-dfn-conforming-processor-1 "§ 2.1 Proofs") [(2)](#ref-for-dfn-conforming-processor-2 "Reference 2") +- [§ 2.4.3 Securing Data Losslessly](#ref-for-dfn-conforming-processor-3 "§ 2.4.3 Securing Data Losslessly") +- [§ 4.1 Processing Model](#ref-for-dfn-conforming-processor-4 "§ 4.1 Processing Model") + +[Permalink](#dfn-controlled-identifier-document) + +**Referenced in:** + +- [§ 2.1 Proofs](#ref-for-dfn-controlled-identifier-document-1 "§ 2.1 Proofs") +- [§ 5.9 Verification Method Binding](#ref-for-dfn-controlled-identifier-document-2 "§ 5.9 Verification Method Binding") [(2)](#ref-for-dfn-controlled-identifier-document-3 "Reference 2") +- [§ 5.10 Verification Relationship Validation](#ref-for-dfn-controlled-identifier-document-4 "§ 5.10 Verification Relationship Validation") + +[Permalink](#dfn-cryptosuite) exported + +**Referenced in:** + +- [§ 1.1 How it Works](#ref-for-dfn-cryptosuite-1 "§ 1.1 How it Works") +- [§ 1.2 Design Goals and Rationale](#ref-for-dfn-cryptosuite-2 "§ 1.2 Design Goals and Rationale") +- [§ 3. Cryptographic Suites](#ref-for-dfn-cryptosuite-3 "§ 3. Cryptographic Suites") [(2)](#ref-for-dfn-cryptosuite-4 "Reference 2") +- [§ 3.1 DataIntegrityProof](#ref-for-dfn-cryptosuite-5 "§ 3.1 DataIntegrityProof") [(2)](#ref-for-dfn-cryptosuite-6 "Reference 2") [(3)](#ref-for-dfn-cryptosuite-7 "Reference 3") [(4)](#ref-for-dfn-cryptosuite-8 "Reference 4") [(5)](#ref-for-dfn-cryptosuite-9 "Reference 5") [(6)](#ref-for-dfn-cryptosuite-10 "Reference 6") +- [§ 4.3 Add Proof Set/Chain](#ref-for-dfn-cryptosuite-11 "§ 4.3 Add Proof Set/Chain") +- [§ 5.7 Protected Information](#ref-for-dfn-cryptosuite-12 "§ 5.7 Protected Information") [(2)](#ref-for-dfn-cryptosuite-13 "Reference 2") [(3)](#ref-for-dfn-cryptosuite-14 "Reference 3") + +[Permalink](#dfn-data-integrity-proof) exported + +**Referenced in:** + +- [§ 1.4 Terminology](#ref-for-dfn-data-integrity-proof-1 "§ 1.4 Terminology") +- [§ 2. Data Model](#ref-for-dfn-data-integrity-proof-2 "§ 2. Data Model") +- [§ 2.1 Proofs](#ref-for-dfn-data-integrity-proof-3 "§ 2.1 Proofs") [(2)](#ref-for-dfn-data-integrity-proof-4 "Reference 2") [(3)](#ref-for-dfn-data-integrity-proof-5 "Reference 3") [(4)](#ref-for-dfn-data-integrity-proof-6 "Reference 4") +- [§ 2.1.3 Proof Graphs](#ref-for-dfn-data-integrity-proof-7 "§ 2.1.3 Proof Graphs") [(2)](#ref-for-dfn-data-integrity-proof-8 "Reference 2") [(3)](#ref-for-dfn-data-integrity-proof-9 "Reference 3") [(4)](#ref-for-dfn-data-integrity-proof-10 "Reference 4") +- [§ 3. Cryptographic Suites](#ref-for-dfn-data-integrity-proof-11 "§ 3. Cryptographic Suites") [(2)](#ref-for-dfn-data-integrity-proof-12 "Reference 2") +- [§ 3.1 DataIntegrityProof](#ref-for-dfn-data-integrity-proof-13 "§ 3.1 DataIntegrityProof") +- [§ 5.7 Protected Information](#ref-for-dfn-data-integrity-proof-14 "§ 5.7 Protected Information") [(2)](#ref-for-dfn-data-integrity-proof-15 "Reference 2") +- [§ 5.13 Canonicalization Method Correctness](#ref-for-dfn-data-integrity-proof-16 "§ 5.13 Canonicalization Method Correctness") + +[Permalink](#dfn-proof-purpose) exported + +**Referenced in:** + +- [§ 2.2 Proof Purposes](#ref-for-dfn-proof-purpose-1 "§ 2.2 Proof Purposes") [(2)](#ref-for-dfn-proof-purpose-2 "Reference 2") [(3)](#ref-for-dfn-proof-purpose-3 "Reference 3") [(4)](#ref-for-dfn-proof-purpose-4 "Reference 4") [(5)](#ref-for-dfn-proof-purpose-5 "Reference 5") +- [§ 5.11 Proof Purpose Validation](#ref-for-dfn-proof-purpose-6 "§ 5.11 Proof Purpose Validation") + +[Permalink](#dfn-public-key) + +**Referenced in:** + +- [§ 1.4 Terminology](#ref-for-dfn-public-key-1 "§ 1.4 Terminology") +- [§ 2.1 Proofs](#ref-for-dfn-public-key-2 "§ 2.1 Proofs") [(2)](#ref-for-dfn-public-key-3 "Reference 2") + +[Permalink](#dfn-secret-key) + +**Referenced in:** + +- [§ 1.4 Terminology](#ref-for-dfn-secret-key-1 "§ 1.4 Terminology") [(2)](#ref-for-dfn-secret-key-2 "Reference 2") +- [§ 2.6 Relationship to Verifiable Credentials](#ref-for-dfn-secret-key-3 "§ 2.6 Relationship to Verifiable Credentials") + +[Permalink](#dfn-verification-method) exported + +**Referenced in:** + +- [§ 1.4 Terminology](#ref-for-dfn-verification-method-1 "§ 1.4 Terminology") +- [§ 2.6 Relationship to Verifiable Credentials](#ref-for-dfn-verification-method-3 "§ 2.6 Relationship to Verifiable Credentials") [(2)](#ref-for-dfn-verification-method-4 "Reference 2") [(3)](#ref-for-dfn-verification-method-5 "Reference 3") [(4)](#ref-for-dfn-verification-method-6 "Reference 4") [(5)](#ref-for-dfn-verification-method-7 "Reference 5") +- [§ 5.9 Verification Method Binding](#ref-for-dfn-verification-method-8 "§ 5.9 Verification Method Binding") [(2)](#ref-for-dfn-verification-method-9 "Reference 2") [(3)](#ref-for-dfn-verification-method-10 "Reference 3") +- [§ 5.10 Verification Relationship Validation](#ref-for-dfn-verification-method-11 "§ 5.10 Verification Relationship Validation") +- [§ 5.14 Network Requests](#ref-for-dfn-verification-method-12 "§ 5.14 Network Requests") [(2)](#ref-for-dfn-verification-method-13 "Reference 2") [(3)](#ref-for-dfn-verification-method-14 "Reference 3") +- [§ 6.3 Previous Proofs](#ref-for-dfn-verification-method-15 "§ 6.3 Previous Proofs") +- [§ 6.4 Fingerprinting Network Requests](#ref-for-dfn-verification-method-16 "§ 6.4 Fingerprinting Network Requests") [(2)](#ref-for-dfn-verification-method-17 "Reference 2") + +[Permalink](#dfn-verifier) + +**Referenced in:** + +- [§ 2.2 Proof Purposes](#ref-for-dfn-verifier-1 "§ 2.2 Proof Purposes") +- [§ 2.3 Resource Integrity](#ref-for-dfn-verifier-2 "§ 2.3 Resource Integrity") +- [§ 5.13 Canonicalization Method Correctness](#ref-for-dfn-verifier-3 "§ 5.13 Canonicalization Method Correctness") + +[Permalink](#dfn-proof) + +**Referenced in:** + +- [§ 2.2 Proof Purposes](#ref-for-dfn-proof-1 "§ 2.2 Proof Purposes") [(2)](#ref-for-dfn-proof-2 "Reference 2") +- [§ 4.5 Verify Proof Sets and Chains](#ref-for-dfn-proof-3 "§ 4.5 Verify Proof Sets and Chains") +- [§ 5.5 Safer Abstractions](#ref-for-dfn-proof-4 "§ 5.5 Safer Abstractions") +- [§ A. Understanding Proof Sets and Proof Chains](#ref-for-dfn-proof-5 "§ A. Understanding Proof Sets and Proof Chains") [(2)](#ref-for-dfn-proof-6 "Reference 2") + +[Permalink](#dfn-challenge) + +**Referenced in:** + +- [§ 4.4 Verify Proof](#ref-for-dfn-challenge-1 "§ 4.4 Verify Proof") + +[Permalink](#dfn-proof-set) + +**Referenced in:** + +- [§ 4.5 Verify Proof Sets and Chains](#ref-for-dfn-proof-set-1 "§ 4.5 Verify Proof Sets and Chains") +- [§ A. Understanding Proof Sets and Proof Chains](#ref-for-dfn-proof-set-2 "§ A. Understanding Proof Sets and Proof Chains") [(2)](#ref-for-dfn-proof-set-3 "Reference 2") [(3)](#ref-for-dfn-proof-set-4 "Reference 3") [(4)](#ref-for-dfn-proof-set-5 "Reference 4") [(5)](#ref-for-dfn-proof-set-6 "Reference 5") [(6)](#ref-for-dfn-proof-set-7 "Reference 6") [(7)](#ref-for-dfn-proof-set-8 "Reference 7") + +[Permalink](#dfn-proof-chain) + +**Referenced in:** + +- [§ 4.5 Verify Proof Sets and Chains](#ref-for-dfn-proof-chain-1 "§ 4.5 Verify Proof Sets and Chains") +- [§ A. Understanding Proof Sets and Proof Chains](#ref-for-dfn-proof-chain-2 "§ A. Understanding Proof Sets and Proof Chains") [(2)](#ref-for-dfn-proof-chain-3 "Reference 2") [(3)](#ref-for-dfn-proof-chain-4 "Reference 3") [(4)](#ref-for-dfn-proof-chain-5 "Reference 4") [(5)](#ref-for-dfn-proof-chain-6 "Reference 5") [(6)](#ref-for-dfn-proof-chain-7 "Reference 6") + +[Permalink](#dfn-proof-graph) exported + +**Referenced in:** + +- [§ 2.1.3 Proof Graphs](#ref-for-dfn-proof-graph-1 "§ 2.1.3 Proof Graphs") +- [§ 4.3 Add Proof Set/Chain](#ref-for-dfn-proof-graph-2 "§ 4.3 Add Proof Set/Chain") + +[Permalink](#dfn-named-graph) exported + +**Referenced in:** + +- [§ 2.1 Proofs](#ref-for-dfn-named-graph-1 "§ 2.1 Proofs") +- [§ 4.3 Add Proof Set/Chain](#ref-for-dfn-named-graph-2 "§ 4.3 Add Proof Set/Chain") + +[Permalink](#dfn-authentication) + +**Referenced in:** + +- [§ 5.11 Proof Purpose Validation](#ref-for-dfn-authentication-1 "§ 5.11 Proof Purpose Validation") [(2)](#ref-for-dfn-authentication-2 "Reference 2") + +[Permalink](#dfn-cryptosuite-instantiation-algorithm) exported + +**Referenced in:** + +- [§ 3. Cryptographic Suites](#ref-for-dfn-cryptosuite-instantiation-algorithm-1 "§ 3. Cryptographic Suites") [(2)](#ref-for-dfn-cryptosuite-instantiation-algorithm-2 "Reference 2") + +[Permalink](#dfn-data-integrity-cryptographic-suite-instance) exported + +**Referenced in:** + +- [§ 3. Cryptographic Suites](#ref-for-dfn-data-integrity-cryptographic-suite-instance-1 "§ 3. Cryptographic Suites") [(2)](#ref-for-dfn-data-integrity-cryptographic-suite-instance-2 "Reference 2") +- [§ 4.2 Add Proof](#ref-for-dfn-data-integrity-cryptographic-suite-instance-3 "§ 4.2 Add Proof") +- [§ 4.3 Add Proof Set/Chain](#ref-for-dfn-data-integrity-cryptographic-suite-instance-4 "§ 4.3 Add Proof Set/Chain") +- [§ 4.4 Verify Proof](#ref-for-dfn-data-integrity-cryptographic-suite-instance-5 "§ 4.4 Verify Proof") + +[Permalink](#dfn-createproof) + +**Referenced in:** + +- [§ 4.2 Add Proof](#ref-for-dfn-createproof-1 "§ 4.2 Add Proof") + +[Permalink](#dfn-verifyproof) + +**Referenced in:** + +- [§ 4.4 Verify Proof](#ref-for-dfn-verifyproof-1 "§ 4.4 Verify Proof") + +[Permalink](#dfn-cryptosuite-verification-result) + +**Referenced in:** + +- [§ 3. Cryptographic Suites](#ref-for-dfn-cryptosuite-verification-result-1 "§ 3. Cryptographic Suites") + +[Permalink](#dfn-verified) + +**Referenced in:** + +- [§ 3. Cryptographic Suites](#ref-for-dfn-verified-1 "§ 3. Cryptographic Suites") +- [§ 5.7 Protected Information](#ref-for-dfn-verified-2 "§ 5.7 Protected Information") + +[Permalink](#dfn-input-document) + +**Referenced in:** + +- [§ 3. Cryptographic Suites](#ref-for-dfn-input-document-1 "§ 3. Cryptographic Suites") +- [§ 4.2 Add Proof](#ref-for-dfn-input-document-2 "§ 4.2 Add Proof") [(2)](#ref-for-dfn-input-document-3 "Reference 2") +- [§ 4.4 Verify Proof](#ref-for-dfn-input-document-4 "§ 4.4 Verify Proof") +- [§ 4.6 Context Validation](#ref-for-dfn-input-document-5 "§ 4.6 Context Validation") +- [§ A. Understanding Proof Sets and Proof Chains](#ref-for-dfn-input-document-6 "§ A. Understanding Proof Sets and Proof Chains") + +[Permalink](#dfn-secured-data-document) exported + +**Referenced in:** + +- [§ 3. Cryptographic Suites](#ref-for-dfn-secured-data-document-1 "§ 3. Cryptographic Suites") [(2)](#ref-for-dfn-secured-data-document-2 "Reference 2") +- [§ 4.2 Add Proof](#ref-for-dfn-secured-data-document-3 "§ 4.2 Add Proof") [(2)](#ref-for-dfn-secured-data-document-4 "Reference 2") +- [§ 4.3 Add Proof Set/Chain](#ref-for-dfn-secured-data-document-5 "§ 4.3 Add Proof Set/Chain") [(2)](#ref-for-dfn-secured-data-document-6 "Reference 2") [(3)](#ref-for-dfn-secured-data-document-7 "Reference 3") +- [§ 4.4 Verify Proof](#ref-for-dfn-secured-data-document-8 "§ 4.4 Verify Proof") +- [§ 4.5 Verify Proof Sets and Chains](#ref-for-dfn-secured-data-document-9 "§ 4.5 Verify Proof Sets and Chains") [(2)](#ref-for-dfn-secured-data-document-10 "Reference 2") [(3)](#ref-for-dfn-secured-data-document-11 "Reference 3") +- [§ A. Understanding Proof Sets and Proof Chains](#ref-for-dfn-secured-data-document-12 "§ A. Understanding Proof Sets and Proof Chains") [(2)](#ref-for-dfn-secured-data-document-13 "Reference 2") [(3)](#ref-for-dfn-secured-data-document-14 "Reference 3") [(4)](#ref-for-dfn-secured-data-document-15 "Reference 4") [(5)](#ref-for-dfn-secured-data-document-16 "Reference 5") [(6)](#ref-for-dfn-secured-data-document-17 "Reference 6") [(7)](#ref-for-dfn-secured-data-document-18 "Reference 7") + +[Permalink](#dfn-verification-result) + +**Referenced in:** + +- [§ 4.4 Verify Proof](#ref-for-dfn-verification-result-1 "§ 4.4 Verify Proof") [(2)](#ref-for-dfn-verification-result-2 "Reference 2") +- [§ 4.5 Verify Proof Sets and Chains](#ref-for-dfn-verification-result-3 "§ 4.5 Verify Proof Sets and Chains") [(2)](#ref-for-dfn-verification-result-4 "Reference 2") [(3)](#ref-for-dfn-verification-result-5 "Reference 3") [(4)](#ref-for-dfn-verification-result-6 "Reference 4") + +[Permalink](#dfn-verified-0) + +**Referenced in:** + +- [§ 4.4 Verify Proof](#ref-for-dfn-verified-0-1 "§ 4.4 Verify Proof") [(2)](#ref-for-dfn-verified-0-2 "Reference 2") [(3)](#ref-for-dfn-verified-0-3 "Reference 3") [(4)](#ref-for-dfn-verified-0-4 "Reference 4") + +[Permalink](#dfn-verifieddocument-0) + +**Referenced in:** + +- [§ 4.4 Verify Proof](#ref-for-dfn-verifieddocument-0-1 "§ 4.4 Verify Proof") + +[Permalink](#dfn-mediatype) + +**Referenced in:** + +- [§ 4.4 Verify Proof](#ref-for-dfn-mediatype-1 "§ 4.4 Verify Proof") + +[Permalink](#dfn-errors) + +**Referenced in:** + +- [§ 4.4 Verify Proof](#ref-for-dfn-errors-1 "§ 4.4 Verify Proof") + +[Permalink](#dfn-validated) + +**Referenced in:** + +- [§ 4.6 Context Validation](#ref-for-dfn-validated-1 "§ 4.6 Context Validation") + +[Permalink](#dfn-problemdetails) + +**Referenced in:** + +- [§ 4.4 Verify Proof](#ref-for-dfn-problemdetails-1 "§ 4.4 Verify Proof") [(2)](#ref-for-dfn-problemdetails-2 "Reference 2") +- [§ 4.6 Context Validation](#ref-for-dfn-problemdetails-3 "§ 4.6 Context Validation") [(2)](#ref-for-dfn-problemdetails-4 "Reference 2") diff --git a/specifications/vc-imp-guide.md b/specifications/vc-imp-guide.md new file mode 100644 index 0000000..d515b97 --- /dev/null +++ b/specifications/vc-imp-guide.md @@ -0,0 +1,948 @@ +--- +description: This document provides implementation guidance for Verifiable Credentials. +generator: +- HTML Tidy for HTML5 for Linux version 5.7.27 +- ReSpec 24.32.2 +lang: en +title: Verifiable Credentials Implementation Guidelines 1.0 +viewport: width=device-width, initial-scale=1, shrink-to-fit=no +--- + +[![W3C](https://www.w3.org/StyleSheets/TR/2016/logos/W3C)](https://www.w3.org/) + +# Verifiable Credentials Implementation Guidelines 1.0 + +## Implementation guidance for Verifiable Credentials + +## W3C Working Group Note 24 September 2019 + +This version: +: [https://www.w3.org/TR/2019/NOTE-vc-imp-guide-20190924/](https://www.w3.org/TR/2019/NOTE-vc-imp-guide-20190924/) + +Latest published version: +: + +Latest editor\'s draft: +: + +Editor: +: [Andrei Sambra](https://deiu.me/) + +Authors: +: [David Chadwick](https://www.linkedin.com/in/david-chadwick-36816395/) ([University of Kent](https://www.kent.ac.uk/)) +: [Dave Longley](https://github.com/dlongley) ([Digital Bazaar](https://digitalbazaar.com/)) +: [Manu Sporny](http://manu.sporny.org/) ([Digital Bazaar](https://digitalbazaar.com/)) +: [Oliver Terbu](mailto:oliver.terbu@consensys.net) ([Consensys](https://consensys.net/)) +: [Dmitri Zagidulin](mailto:dzagidulin@gmail.com) ([Digital Bazaar](https://digitalbazaar.com)) +: [Brent Zundel](https://www.linkedin.com/in/bzundel/) ([Evernym](https://evernym.com/)) + +Participate: +: [GitHub w3c/vc-imp-guide](https://github.com/w3c/vc-imp-guide/) +: [File a bug](https://github.com/w3c/vc-imp-guide/issues/) +: [Commit history](https://github.com/w3c/vc-imp-guide/commits/gh-pages) +: [Pull requests](https://github.com/w3c/vc-imp-guide/pulls/) + +[Copyright](https://www.w3.org/Consortium/Legal/ipr-notice#Copyright) © 2019 [W3C](https://www.w3.org/)^®^ ([MIT](https://www.csail.mit.edu/), [ERCIM](https://www.ercim.eu/), [Keio](https://www.keio.ac.jp/), [Beihang](https://ev.buaa.edu.cn/)). W3C [liability](https://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer), [trademark](https://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks) and [permissive document license](https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document) rules apply. + +------------------------------------------------------------------------ + +## Abstract + +This document provides implementation guidance for Verifiable Credentials. + +## 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](https://www.w3.org/TR/) at https://www.w3.org/TR/.* + +Future versions of this document will be updated and maintained by the [Credentials Community Group](https://www.w3.org/community/credentials/). Please consult that group for the most up to date version of this document. + +The work on this document was carried out under tight time constraints due to limitations of the W3C process and publishing deadlines. Under such conditions, errors are unavoidable and some of the ideas presented here are incomplete. The Working Group hopes that in the future, W3C process can be revised to better support the dynamic nature of standards work in a more consistent way across different groups. + +Comments regarding this document are welcome. Please file issues directly on [GitHub](https://github.com/w3c/vc-data-model/issues/), or send them to ([subscribe](mailto:public-vc-comments-request@w3.org?subject=subscribe), [archives](https://lists.w3.org/Archives/Public/public-vc-comments/)). + +This document was published by the [Verifiable Claims Working Group](https://www.w3.org/2017/vc/) as a Working Group Note. + +[GitHub Issues](https://github.com/w3c/vc-imp-guide/issues/) are preferred for discussion of this specification. Alternatively, you can send comments to our mailing list. Please send them to ([archives](https://lists.w3.org/Archives/Public/public-vc-comments/)). + +Publication as a Working Group Note does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress. + +This document was produced by a group operating under the [W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy/). + +This document is governed by the [1 March 2019 W3C Process Document](https://www.w3.org/2019/Process-20190301/). + +## Table of Contents + +1. [1. Introduction](#introduction) +2. [2. Identifiers](#identifiers) +3. [3. Terminology](#terminology) +4. [4. Verification](#verification) + 1. [4.1 Core Data Model](#core-data-model) + 2. [4.2 Specific Verifiable Credentials](#specific-verifiable-credentials) + 3. [4.3 Content Integrity](#content-integrity) + 1. [4.3.1 Hashlinks](#hashlinks) + 2. [4.3.2 Verifiable Data Registries](#verifiable-data-registries) +5. [5. Referencing Other Credentials](#referencing-other-credentials) + 1. [5.1 Referencing Credentials Without Integrity Protection](#referencing-credentials-without-integrity-protection) + 2. [5.2 Referencing Credentials With Integrity Protection](#referencing-credentials-with-integrity-protection) + 3. [5.3 Attaching Evidence](#attaching-evidence) +6. [6. Disputes](#disputes) +7. [7. Presentations](#presentations) +8. [8. Using the JWT aud claim](#using-the-jwt-aud-claim) +9. [9. Extensions](#extensions) + 1. [9.1 Creating New Credential Types](#creating-new-credential-types) + 2. [9.2 Extending JWTs](#extending-jwts) + 3. [9.3 Human Readability](#human-readability) +10. [10. Proof Formats](#proof-formats) + 1. [10.1 Benefits of JWTs](#benefits-of-jwts) + 2. [10.2 Benefits of JSON-LD and LD-Proofs](#benefits-of-json-ld-and-ld-proofs) +11. [11. Zero-Knowledge Proofs](#zero-knowledge-proofs) +12. [12. Progressive Trust](#progressive-trust) + 1. [12.1 Data Minimization](#data-minimization) + 2. [12.2 Selective Disclosure](#selective-disclosure) + 3. [12.3 Predicates](#predicates) + 4. [12.4 Further Techniques](#further-techniques) +13. [13. Related Specifications](#related-specifications) + 1. [13.1 Web Authentication](#web-authentication) +14. [14. Test suite](#test-suite) +15. [A. References](#references) + 1. [A.1 Informative references](#informative-references) + +## 1. Introduction[](#introduction) + +*This section is non-normative.* + +This guide provides some examples and resources for implementing protocols which make use of [verifiable credentials](#dfn-verifiable-credentials), beyond those available in the core specification. + +It may be useful to first familiarize yourself with the official [Use Cases document](https://www.w3.org/TR/verifiable-claims-use-cases/), which offers a concise collection of examples of [Verifiable Credentials](#dfn-verifiable-credentials) as they may appear in everyday life, and how they may be used. + +The [data model specification](https://www.w3.org/TR/vc-data-model/) contains the technical details about [verifiable credentials](#dfn-verifiable-credentials). However, the data model specification does not specify any *protocols* for using [verifiable credentials](#dfn-verifiable-credentials), nor any *proof formats* or additional *identifiers* upon which such protocols may depend. + +## 2. Identifiers[](#identifiers) + +*This section is non-normative.* + +When expressing statements about a specific entity, such as a person, product, or organization, it is often useful to have an identifier for it so that others can express statements about the same thing. The [verifiable credentials](#dfn-verifiable-credentials) [data model specification](https://www.w3.org/TR/vc-data-model//) contains numerous examples where the identifier is a [decentralized identifier](https://w3c-ccg.github.io/did-primer/), also known as a DID. An example of a DID is `did:example:123456abcdef`. + +There is currently a proposed charter for a W3C [Decentralized Identifier Working Group](https://w3c-ccg.github.io/did-wg-charter/), which will put DIDs on track to become a W3C standard. + +Note + +As of the publication of the [verifiable credentials](#dfn-verifiable-credentials) [data model specification](https://www.w3.org/TR/vc-data-model/), DIDs are not necessary for [verifiable credentials](#dfn-verifiable-credentials) to be useful. Specifically, [verifiable credentials](#dfn-verifiable-credentials) do not depend on [DIDs](#dfn-decentralized-identifiers) and [DIDs](#dfn-decentralized-identifiers) do not depend on [verifiable credentials](#dfn-verifiable-credentials). However, it is expected that many [verifiable credentials](#dfn-verifiable-credentials) will use [DIDs](#dfn-decentralized-identifiers) and that software libraries implementing the [data model specification](https://www.w3.org/TR/vc-data-model/) will benefit from knowing how to resolve [DIDs](#dfn-decentralized-identifiers). [DID](#dfn-decentralized-identifiers)-based URLs may be used to express identifiers associated with [subjects](#dfn-subjects), [issuers](#dfn-issuers), [holders](#dfn-holders), credential status lists, cryptographic keys, and other machine-readable information associated with a [verifiable credential](#dfn-verifiable-credentials). + +## 3. Terminology[](#terminology) + +*This section is non-normative.* + +The following terms are used to describe concepts in this specification. + +claim +: An assertion made about a [subject](#dfn-subjects). + +credential +: A set of one or more [claims](#dfn-claims) made by an [issuer](#dfn-issuers). A verifiable credential is a tamper-evident credential that has authorship that can be cryptographically verified. Verifiable credentials can be used to build [verifiable presentations](#dfn-verifiable-presentations), which can also be cryptographically verified. The [claims](#dfn-claims) in a credential can be about different [subjects](#dfn-subjects). + +data minimization +: The act of limiting the amount of shared data strictly to the minimum necessary to successfully accomplish a task or goal. + +decentralized identifier +: A portable URL-based identifier, also known as a ***DID***, associated with an [entity](#dfn-entities). These identifiers are most often used in a [verifiable credential](#dfn-verifiable-credentials) and are associated with [subjects](#dfn-subjects) such that a [verifiable credential](#dfn-verifiable-credentials) itself can be easily ported from one [repository](#dfn-credential-repository) to another without the need to reissue the [credential](#dfn-credential). An example of a DID is `did:example:123456abcdef`. + +decentralized identifier document +: Also referred to as a ***DID document***, this is a document that is accessible using a [verifiable data registry](#dfn-verifiable-data-registries) and contains information related to a specific [decentralized identifier](#dfn-decentralized-identifiers), such as the associated [repository](#dfn-credential-repository) and public key information. + +derived predicate +: A verifiable, boolean assertion about the value of another attribute in a [verifiable credential](#dfn-verifiable-credentials). These are useful in zero-knowledge-proof-style [verifiable presentations](#dfn-verifiable-presentations) because they can limit information disclosure. For example, if a [verifiable credential](#dfn-verifiable-credentials) contains an attribute for expressing a specific height in centimeters, a derived predicate might reference the height attribute in the [verifiable credential](#dfn-verifiable-credentials) demonstrating that the [issuer](#dfn-issuers) attests to a height value meeting the minimum height requirement, without actually disclosing the specific height value. For example, the [subject](#dfn-subjects) is taller than 150 centimeters. + +digital signature +: A mathematical scheme for demonstrating the authenticity of a digital message. + +entity +: A thing with distinct and independent existence, such as a person, organization, or device that performs one or more roles in the ecosystem. + +graph +: A network of information composed of [subjects](#dfn-subjects) and their relationship to other [subjects](#dfn-subjects) or data. + +hashlink +: Hashlink URLs can be used to provide content integrity for links to external resources. + +holder +: A role an [entity](#dfn-entities) might perform by possessing one or more [verifiable credentials](#dfn-verifiable-credentials) and generating [presentations](#dfn-presentations) from them. A holder is usually, but not always, a [subject](#dfn-subjects) of the [verifiable credentials](#dfn-verifiable-credentials) they are holding. Holders store their [credentials](#dfn-credential) in [credential repositories](#dfn-credential-repository). + +identity +: The means for keeping track of [entities](#dfn-entities) across contexts. Digital identities enable tracking and customization of [entity](#dfn-entities) interactions across digital contexts, typically using identifiers and attributes. Unintended distribution or use of identity information can compromise privacy. Collection and use of such information should follow the principle of [data minimization](#dfn-data-minimization). + +identity provider +: An identity provider, sometimes abbreviated as *IdP*, is a system for creating, maintaining, and managing identity information for [holders](#dfn-holders), while providing authentication services to relying party applications within a federation or distributed network. In this case the [holder](#dfn-holders) is always the [subject](#dfn-subjects). Even if the [verifiable credentials](#dfn-verifiable-credentials) are bearer [credentials](#dfn-credential), it is assumed the [verifiable credentials](#dfn-verifiable-credentials) remain with the [subject](#dfn-subjects), and if they are not, they were stolen by an attacker. This specification does not use this term unless comparing or mapping the concepts in this document to other specifications. This specification decouples the [identity provider](#dfn-identity-providers) concept into two distinct concepts: the [issuer](#dfn-issuers) and the [holder](#dfn-holders). + +issuer +: A role an [entity](#dfn-entities) can perform by asserting [claims](#dfn-claims) about one or more [subjects](#dfn-subjects), creating a [verifiable credential](#dfn-verifiable-credentials) from these [claims](#dfn-claims), and transmitting the [verifiable credential](#dfn-verifiable-credentials) to a [holder](#dfn-holders). + +presentation +: Data derived from one or more [verifiable credentials](#dfn-verifiable-credentials), issued by one or more [issuers](#dfn-issuers), that is shared with a specific [verifier](#dfn-verifier). A verifiable presentation is a tamper-evident presentation encoded in such a way that authorship of the data can be trusted after a process of cryptographic verification. Certain types of verifiable presentations might contain data that is synthesized from, but do not contain, the original [verifiable credentials](#dfn-verifiable-credentials) (for example, zero-knowledge proofs). + +repository +: A program, such as a storage vault or personal [verifiable credential](#dfn-verifiable-credentials) wallet, that stores and protects access to [holders\'](#dfn-holders) [verifiable credentials](#dfn-verifiable-credentials). + +selective disclosure +: The ability of a [holder](#dfn-holders) to make fine-grained decisions about what information to share. + +subject +: A thing about which [claims](#dfn-claims) are made. + +user agent +: A program, such as a browser or other Web client, that mediates the communication between [holders](#dfn-holders), [issuers](#dfn-issuers), and [verifiers](#dfn-verifier). + +validation +: The assurance that a [verifiable credential](#dfn-verifiable-credentials) or a [verifiable presentation](#dfn-verifiable-presentations) meets the needs of a [verifier](#dfn-verifier) and other dependent stakeholders. This specification is constrained to [verifying](#dfn-verify) [verifiable credentials](#dfn-verifiable-credentials) and [verifiable presentations](#dfn-verifiable-presentations) regardless of their usage. Validating [verifiable credentials](#dfn-verifiable-credentials) or [verifiable presentations](#dfn-verifiable-presentations) is outside the scope of this specification. + +verifiable data registry +: A role a system might perform by mediating the creation and [verification](#dfn-verify) of identifiers, keys, and other relevant data, such as [verifiable credential](#dfn-verifiable-credentials) schemas, revocation registries, issuer public keys, and so on, which might be required to use [verifiable credentials](#dfn-verifiable-credentials). Some configurations might require correlatable identifiers for [subjects](#dfn-subjects). Some registries, such as ones for UUIDs and public keys, might just act as namespaces for identifiers. + +verification +: The evaluation of whether a [verifiable credential](#dfn-verifiable-credentials) or [verifiable presentation](#dfn-verifiable-presentations) is an authentic and timely statement of the issuer or presenter, respectively. This includes checking that: the credential (or presentation) conforms to the specification; the proof method is satisfied; and, if present, the status is successfully checked. + +verifier +: The [entity](#dfn-entities) verifying a claim about a given subject. + +URI +: A Uniform Resource Identifier, as defined by \[[RFC3986](#bib-rfc3986 "Uniform Resource Identifier (URI): Generic Syntax")\]. + +## 4. Verification[](#verification) + +*This section is non-normative.* + +[Verification](#dfn-verify) is the process a [verifier](#dfn-verifier) or [holder](#dfn-holders) performs when presented with a [verifiable presentation](#dfn-verifiable-presentations) or [verifiable credential](#dfn-verifiable-credentials). [Verification](#dfn-verify) includes checking the presented item against the [core data model](https://www.w3.org/TR/vc-data-model/), and may also include validating the provided proof section and checking the item\'s status. + +### 4.1 Core Data Model[](#core-data-model) + +Conformant tooling that processes Verifiable Credentials will ensure that the core data model is verified when processing credentials. + +### 4.2 Specific Verifiable Credentials[](#specific-verifiable-credentials) + +There are many data verification languages, the following approach is one that should work for most use cases. + +### 4.3 Content Integrity[](#content-integrity) + +Protecting the integrity of content is an important component of verification. [Verifiers](#dfn-verifier) need to have confidence that the content they rely on to verify [credentials](#dfn-credential) doesn\'t change without their knowledge. This content may include data schemas, identifiers, public keys, etc. + +There are a number of ways to provide content integrity protection. A few of these are described in greater detail below. + +#### 4.3.1 Hashlinks[](#hashlinks) + +[Hashlink URLs](https://tools.ietf.org/html/draft-sporny-hashlink) can be used to provide content integrity for links to external resources. + +#### 4.3.2 Verifiable Data Registries[](#verifiable-data-registries) + +A [verifiable data registry](#dfn-verifiable-data-registries) can also provide content integrity protection. One example of a [verifiable data registry](#dfn-verifiable-data-registries) which provides content integrity protection is a distributed ledger. This is a shared transaction record which provides mechanisms for verifying the content it stores. These mechanisms include consensus protocols, digital signatures, and verifiable data structures such as Merkle trees. These mechanisms provide cryptographic assurances that the content retrieved from the ledger has not been altered, and is complete. + +## 5. Referencing Other Credentials[](#referencing-other-credentials) + +Usage of [verifiable credentials](#dfn-verifiable-credentials) will often require referencing other credentials, embedding or attaching multiple credentials, or otherwise binding them together. + +### 5.1 Referencing Credentials Without Integrity Protection[](#referencing-credentials-without-integrity-protection) + +The simplest way for a [credential](#dfn-credential) to reference another external credential is to link to it, either directly by using its URI, or indirectly by providing a well-known ID (for example, a credential modeling an internal company Invoice may refer to its parent Purchase Order credential simply by the PO Number, relevant only within the context of this specific enterprise). + +This method of linking to an external credential without using an integrity protection mechanism may be acceptable in some use cases, such as when both credentials are issued by the same entity, the verifier has a high level of trust and confidence in the issuer\'s security and auditing mechanisms, and the risk to the verifier is sufficiently low. However, implementers should keep in mind that although the credential that contains the reference may be integrity protected itself (by a cryptographic signature or a similar proof mechanism), the verifier has no way of knowing that the external credential being linked to has not been tampered with, unless the link itself has a content integrity protection mechanism built into it. + +### 5.2 Referencing Credentials With Integrity Protection[](#referencing-credentials-with-integrity-protection) + +The recommended way of referencing an external credential from within a [verifiable credential](#dfn-verifiable-credentials) is to use a linking mechanism that cryptographically binds the contents of the target document to the URI itself. One way to accomplish this would be to use [hashlinks](#dfn-hashlinks) or an equivalent URI scheme. Another mechanism would be to encode the full contents of the target credential in the URI itself, although this is much less commonly used, and the discussion of the practical limits of URI length are outside the scope of this document. + +### 5.3 Attaching Evidence[](#attaching-evidence) + +[Issuers](#dfn-issuers) wishing to attach additional supporting information to a [verifiable credential](#dfn-verifiable-credentials) are encouraged to use the [evidence](https://www.w3.org/TR/vc-data-model/#evidence) property. Note that this can be done either by embedding the relevant evidence information in the credential itself, or by referencing it (with or without an integrity protection mechanism, as previously discussed). + +## 6. Disputes[](#disputes) + +There are at least two different cases to consider where an [entity](#dfn-entities) wants to dispute a [credential](#dfn-credential) issued by an [issuer](#dfn-issuers): + +- A [subject](#dfn-subjects) disputes a claim made by the [issuer](#dfn-issuers). For example, the `address` property is incorrect or out of date. +- An [entity](#dfn-entities) disputes a potentially false claim made by the [issuer](#dfn-issuers) about a different [subject](#dfn-subjects). For example, an imposter has claimed the social security number for an [entity](#dfn-entities). + +The mechanism for issuing a `DisputeCredential` is the same as for a regular [credential](#dfn-credential), except that the `credentialSubject` identifier in the `DisputeCredential` property is the identifier of the disputed [credential](#dfn-credential). + +For example, if a [credential](#dfn-credential) with an identifier of `https://example.org/credentials/245` is disputed, an [entity](#dfn-entities) can issue one of the [credentials](#dfn-credential) shown below. In the first example, the [subject](#dfn-subjects) might present this to the [verifier](#dfn-verifier) along with the disputed [credential](#dfn-credential). In the second example, the [entity](#dfn-entities) might publish the `DisputeCredential` in a public venue to make it known that the [credential](#dfn-credential) is disputed. + +[Example 1](#example-1-a-subject-disputes-a-credential): A subject disputes a credential + +``` nohighlight +{ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1" + ], + "id": "http://example.com/credentials/123", + "type": ["VerifiableCredential", "DisputeCredential"], + "credentialSubject": { + "id": "http://example.com/credentials/245", + "currentStatus": "Disputed", + "statusReason": { + "@value": "Address is out of date", + "@language": "en" + }, + }, + "issuer": "https://example.com/people#me", + "issuanceDate": "2017-12-05T14:27:42Z", + "proof": { ... } +} +``` + +[Example 2](#example-2-another-entity-disputes-a-credential): Another entity disputes a credential + +``` nohighlight +{ + "@context": "https://w3id.org/credentials/v1", + "id": "http://example.com/credentials/321", + "type": ["VerifiableCredential", "DisputeCredential"], + "credentialSubject": { + "id": "http://example.com/credentials/245", + "currentStatus": "Disputed", + "statusReason": { + "@value": "Credential contains disputed statements", + "@language": "en" + }, + "disputedClaim": { + "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", + "address": "Is Wrong" + } + }, + "issuer": "https://example.com/people#me", + "issuanceDate": "2017-12-05T14:27:42Z", + "proof": { ... } +} +``` + +In the above [verifiable credential](#dfn-verifiable-credentials), the [issuer](#dfn-issuers) is claiming that the address in the disputed [verifiable credential](#dfn-verifiable-credentials) is wrong. For example, the [subject](#dfn-subjects) might wrongly be claiming to have the same address as that of the [issuer](#dfn-issuers). + +Note + +If a [credential](#dfn-credential) does not have an identifier, a content-addressed identifier can be used to identify the disputed [credential](#dfn-credential). Similarly, content-addressed identifiers can be used to uniquely identify individual claims. + +## 7. Presentations[](#presentations) + +[Verifiable credentials](#dfn-verifiable-credentials) may be presented to a [verifier](#dfn-verifier) by using a [verifiable presentation](#dfn-verifiable-presentations). A [verifiable presentation](#dfn-verifiable-presentations) can be targeted to a specific [verifier](#dfn-verifier) by using a Linked Data Proof that includes a `domain` and `challenge`. This also helps prevent a [verifier](#dfn-verifier) from reusing a [verifiable presentation](#dfn-verifiable-presentations) as their own. + +The `domain` value can be any string or URI, and the `challenge` should be a randomly generated string. + +The following sample [verifiable presentation](#dfn-verifiable-presentations) is for authenticating to a website, `https://example.com`. + +[Example 3](#example-3-a-targeted-verifiable-presentation): A targeted verifiable presentation + +``` nohighlight +{ + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "type": "VerifiablePresentation, + "verifiableCredential": { ... }, + "proof": { + "type": "Ed25519Signature2018", + "created": "2019-08-13T15:09:00Z", + "challenge": "d1b23d3...3d23d32d2", + "domain": "https://example.com", + "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..uyW7Hv + VOZ8QCpLJ63wHode0OdgWjsHfJ0O8d8Kfs55dMVEg3C1Z0bYUGV49s8IlTbi3eXsNvM63n + vah79E-lAg", + "proofPurpose": "authentication" + } +} +``` + +## 8. Using the JWT aud claim[](#using-the-jwt-aud-claim) + +The JWT `aud` [claim](#dfn-claims) name refers to (i.e., identifies) the intended audience of the [verifiable presentation](#dfn-verifiable-presentations) (i.e., the [verifier(s)](#dfn-verifier)). Consequently this is an alternative to the Linked Data Proof method specified above. It lets the [holder](#dfn-holders) indicate which [verifier(s)](#dfn-verifier) it allows to verify the [verifiable presentation](#dfn-verifiable-presentations). Any JWT-compliant [verifier](#dfn-verifier) that is not identified in the `aud` is required to reject the JWT (see [RFC 7519](https://tools.ietf.org/html/rfc7519)). + +[RFC 7519](https://tools.ietf.org/html/rfc7519) defines `aud` as \"an array of case-sensitive strings, each containing a `StringOrURI` value\". For use in a [verifiable presentation](#dfn-verifiable-presentations), we strongly suggest that this be restricted to a single URI value, equal to the URI of the intended verifier. + +The [data model specification](https://w3c.github.io/vc-data-model/) provides no guidance of how to transform this JWT [claim](#dfn-claims) into a property of the [verifiable presentation](#dfn-verifiable-presentations), nor vice versa. We strongly suggest that the `aud` JWT [claim](#dfn-claims) be mapped to the `verifier` property of the [verifiable presentation](#dfn-verifiable-presentations). + +[Example 4](#example-4-an-example-of-a-targeted-verifiable-presentation-using-the-verifier-property): An example of a targeted verifiable presentation using the verifier property + +``` nohighlight +{ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2019/credentials/v1.1" + ], + "type": "VerifiablePresentation", + "verifiableCredential": [" ... "], + "holder": "did:example:ebfeb1f712ebc6f1c276e12ec21", + "verifier": "https://some.verifier.com" +} +``` + +[Example 5](#example-5-an-example-jwt-for-a-targeted-verifiable-presentation-using-the-jwt-aud-claim): An example JWT for a targeted verifiable presentation using the JWT aud claim + +``` nohighlight +{ + "iss": "did:example:ebfeb1f712ebc6f1c276e12ec21", + "jti": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5", + "aud": "https://some.verifier.com", + "nbf": 1541493724, + "iat": 1541493724, + "exp": 1573029723, + "nonce": "343s$FSFDa-", + "vp": { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credImpGuide/v1" + ], + "type": "VerifiablePresentation", + "verifiableCredential": [" ... "] + } +} +``` + +## 9. Extensions[](#extensions) + +*This section is non-normative.* + +The Verifiable Credentials Data Model is designed around an *open world assumption*, meaning that any entity can say anything about another entity. This approach enables permissionless innovation; there is no centralized registry or authority through which an extension author must register themselves nor the specific data models and vocabularies they create. + +Instead, credential data model authors are expected to use machine-readable vocabularies through the use of \[LINKED-DATA\]. This implementation guide provides examples for how to express data models using a data format that is popular with software developers and web page authors called \[JSON-LD\]. This data format provides features that enable authors to express their data models in idiomatic JSON while also ensuring that their vocabulary terms are unambigiously understood, even by software that does not implement JSON-LD processing. + +The Verifiable Credentials data model also uses a graph-based data model, which allows authors to model both simple relationships that describe one or more attributes for a single entity and complex multi-entity relationships. + +The rest of this section describes how to author extensions that build on the Verifiable Credentials Data Model. + +### 9.1 Creating New Credential Types[](#creating-new-credential-types) + +We expect the most common extensions to the Verifiable Credentials Data Model to be new credential types. Whenever someone has something to say about one or more entities and they want their authorship to be verifiable, they should use a Verifiable Credential. Sometimes there may be an existing credential type, that someone else has created, that can be reused to make the statements they want to make. However, there are often cases where new credential types are needed. + +New credential types can be created by following a few steps. This guide will also walk you through creating an example new credential type. At a high level, the steps to follow are: + +1. Design the data model. +2. Create a new JSON-LD context. +3. Select a publishing location. +4. Use the new JSON-LD context when issuing new credentials. + +So, let\'s walk through creating a new credential type which we will call `ExampleAddressCredential`. The purpose of this credential will be to express a person\'s postal address. + +#### Design the data model[](#creating-new-credential-types) + +First, we must design a data model for our new credential type. We know that we will need to be able to express the basics of a postal address, things like a person\'s city, state, and zipcode. Of course, those items are quite US centric, so we should consider internationalizing those terms. But before we go further, since we\'re using \[LINKED-DATA\] vocabularies, there is a good chance that commonly known concepts may already have a vocabulary that someone else has created that we can leverage. + +If we are going to use someone else\'s vocabulary, we will want to make sure it is stable and unlikely to change in any significant way. There may even be technologies that we can make use of that store immutable vocabularies that we can reference, but those are not the focus of this example. Here we will rely on the inertia that comes from a very popularly used vocabulary on the Web, schema.org. It turns out that this vocabulary has just what we need; it has already modeled a postal address and even has examples for how to express it using JSON-LD. + +Please note that schema.org is developed incrementally, meaning that the definition of a term today may differ from a future definition, or even be removed. Although schema.org developers encourage using the latest release, as in the simple non-versioned schema.org URLs such as `http://schema.org/Place` in structured data applications, there are times in which more precise versioning is important. Schema.org also provides dated snapshots of each release, including both human and machine readable definitions of the schema.org core vocabulary. These are linked from the [releases page](https://schema.org/docs/releases.html). For instance, instead of the unversioned URI `http://schema.org/Place`, you might use the versioned URI `https://schema.org/version/3.9/schema-all.html#term_Place`. In addition, the `schemaVersion` property has been defined to provide a way for documents to indicate the specific intended version of schema.org\'s definitions. + +Using the schema.org vocabulary and JSON-LD we can express a person\'s address like so: + +[Example 6](#example-6-example-schema-org-address): Example schema.org address + +``` nohighlight +{ + + "@context": [ + "http://schema.org" + ], + "type": "Person", + "address": { + "type": "PostalAddress", + "streetAddress": "123 Main St." + "addressLocality": "Blacksburg", + "addressRegion": "VA", + "postalCode": "24060", + "addressCountry": "US" + } +} +``` + +Note the above `@context` key in the JSON. This `@context` refers to a machine-readable file (also expressed in JSON) that provides term definitions \[JSON-LD\]. A term definition maps a key or type used in the JSON, such as `address` or `PostalAddress`, to a globally unique identifier: a URL. + +This ensures that when software sees the `@context` *http://schema.org*, that it will interpret the the keys and types in the JSON in a globally consistent way, without requiring developers to use full URLs in the JSON or in the code that may traverse it. As long as the software is aware of the specific `@context` used (or if it uses JSON-LD processing to transform it to some other known `@context`), then it will understand the *context* in which the JSON was written and meant to be understood. The use of `@context` also allows \[JSON-LD\] keywords such as `@type` to be aliased to the simpler `type` as is done in the above example. + +Note that we could also express the JSON using full URLs, if we want to avoid using *\@context*. Here is what the example would look like if we did that: + +[Example 7](#example-7-example-schema-org-address-with-full-urls): Example schema.org address with full URLs + +``` nohighlight +{ + "@type": "http://schema.org/Person", + "http://schema.org/address": { + "@type": "http://schema.org/PostalAddress", + "http://schema.org/streetAddress": "123 Main St." + "http://schema.org/addressLocality": "Blacksburg", + "http://schema.org/addressRegion": "VA", + "http://schema.org/postalCode": "24060", + "http://schema.org/addressCountry": "US" + } +} +``` + +While this form is an acceptable way to express the information such that it is unambiguous, many software developers would prefer to use more idiomatic JSON. The use of `@context` enables idiomatic JSON without losing global consistency and without the need for a centralized registry or authority for creating extensions. Note that `@context` can also have more than one value. In this case, a JSON array is used to express multiple values, where each value references another context that defines terms. Using this mechanism we can first bring in the terms defined in the Verifiable Credentials Data Model specification and then bring in the terms defined by schema.org: + +[Example 8](#example-8-example-address-credential-with-schema-org-context): Example address credential with schema.org context + +``` nohighlight +{ + + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "http://schema.org" + ], + ... + "credentialSubject": { + "type": "Person", + "address": { + "type": "PostalAddress", + "streetAddress": "123 Main St." + "addressLocality": "Blacksburg", + "addressRegion": "VA", + "postalCode": "24060", + "addressCountry": "US" + } + }, + ... +} +``` + +Note, however, that each *context* might have a different definition for the same term, e.g., the JSON key `address` might map to a different URL in each *context*. By default, \[JSON-LD\] allows terms in a `@context` to be redefined using a *last term wins* order. While these changes can be safely dealt with by using JSON-LD processing, we want to lower the burden on consumers of Verifiable Credentials. We want consumer software to be able to make assumptions about the meaning of terms by only having to read and understand the string value associated with the `@context` key. We don\'t want them to have to worry about terms being redefined in unexpected ways. That way their software can inspect only the `@context` values and then be hard coded to understand the meaning of the terms. + +In order to prevent term redefinition, the \[JSON-LD\] `@protected` feature must be applied to term definitions in the `@context`. All terms in the core Verifiable Credentials `@context` are already protected in this way. The only time that an existing term is allowed to be redefined is if the new definition is scoped underneath another new term that is defined in a *context*. This matches developer expectations and ensures that consumer software has strong guarantees about the semantics of the data it is processing; it can be written such that it is never confused about the definition of a term. Note that consumers must determine their own risk profile for how to handle any credentials their software processes that include terms that it does not understand. + +#### Create a new JSON-LD context[](#creating-new-credential-types) + +Given the above, there is at least one reason why we don\'t want to use the schema.org *context*: it is designed to be very flexible and thus does not use the `@protected` feature. There are a few additional reasons we want to create our own \[JSON-LD\] context though. First, the schema.org context does not define our new credential type: *ExampleAddressCredential*. Second, it is not served via a secure protocol (e.g., *https*); rather, it uses *http*. Note that this is less of a concern than it may seem, as it is recommended that all Verifiable Credential consumer software hard code the `@context` values it understands and not reach out to the Web to fetch them. Lastly, it is a very large context, containing many more term definitions than are necessary for our purposes. + +So, we will create our own \[JSON-LD\] context that expresses just those term definitions that we need for our new credential type. Note that this does not mean that we must mint new URLs; we can still reuse the schema.org vocabulary terms. All we are doing is creating a more concise and targeted context. Here\'s what we\'ll need in our context: + +[Example 9](#example-9-example-address-credential-context): Example address credential context + +``` nohighlight +{ + "@version": 1.1, + "@protected": true, + + "ExampleAddressCredential": + "https://example.org/ExampleAddressCredential", + + "Person": { + "@id": "http://schema.org/Person", + "@context": { + "@version": 1.1, + "@protected": true, + + "address": "http://schema.org/address" + } + }, + "PostalAddress": { + "@id": "http://schema.org/PostalAddress", + "@context": { + "@version": 1.1, + "@protected": true, + + "streetAddress": "http://schema.org/streetAddress", + "addressLocality": "http://schema.org/addressLocality", + "addressRegion": "http://schema.org/addressRegion", + "postalCode": "http://schema.org/postalCode", + "addressCountry": "http://schema.org/addressCountry" + } + } +} +``` + +The above context defines a term for our new credential type *ExampleAddressCredential*, mapping it to the URL *https://example.org/ExampleAddressCredential*. We could have also chosen a URI like *urn:private-example:ExampleAddressCredential*, but this approach would not allow us to serve up a Web page to describe it, if we so desire. The context also defines the terms for types *Person* and *PostalAddress*, mapping them to their schema.org vocabulary URLs. Furthermore, when those types are used, it also defines protected terms for each of them via a *scoped context*, mapping terms like *address* and *streetAddress* to their schema.org vocabulary URLs. For more information on how to write a JSON-LD context or *scoped contexts*, see the \[JSON-LD\] specification. + +#### Select a publishing location[](#creating-new-credential-types) + +Now that we have a \[JSON-LD\] context, we must give it a URL. Technically speaking, we could just use a URI, for example, a private URN such as *urn:private-example:my-extension*. However, if we want people to be able to read and discover it on the Web, we should give it a URL like *https://example.org/example-address-credential-context/v1*. + +When this URL is dereferenced, it should return *application/ld+json* by default, to allow JSON-LD processors to process the context. However, if a user agent requests *HTML*, it should return human readable text that explains, to humans, what the term definitions are and what they map to. Since we\'re reusing an existing vocabulary, schema.org, we can also simply link to the definitions of the meaning of our types and terms via their website. If we had created our own new vocabulary terms, we would describe them on our own site, ideally including machine readable Information as well. + +#### Use the new JSON-LD context when issuing new credentials[](#creating-new-credential-types) + +Now we\'re ready for our context to be used by anyone who wishes to issue an *ExampleAddressCredential*! + +[Example 10](#example-10-example-address-credential-with-schema-org-context): Example address credential with schema.org context + +``` nohighlight +{ + + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://example.org/example-address-credential-context/v1" + ], + "id": "https://example.org/credentials/1234", + "type": "ExampleAddressCredential", + "issuer": "https://example.org/people#me", + "issuanceDate": "2017-12-05T14:27:42Z", + "credentialSubject": { + "id": "did:example:1234", + "type": "Person", + "address": { + "type": "PostalAddress", + "streetAddress": "123 Main St." + "addressLocality": "Blacksburg", + "addressRegion": "VA", + "postalCode": "24060", + "addressCountry": "US" + } + }, + "proof": { ... } +} +``` + +Note that writing this new credential type requires permission from no one, you must only adhere to the above referenced standards. + +### 9.2 Extending JWTs[](#extending-jwts) + +The [Verifiable Credentials Data Model 1.0](https://www.w3.org/TR/vc-data-model/) specifies a minimal set of JWT [claim](#dfn-claims) names that are to be used to represent the properties of a [verifiable credential](#dfn-verifiable-credentials) and its `credentialSubject`. Implementers may wish to extend a [verifiable credential](#dfn-verifiable-credentials) with some properties that are new (e.g., `drivingLicenseNumber`, `mySpecialProperty` or that are already registered with IANA as JWT [claim](#dfn-claims) names (e.g., `given_name`. `phone_number_verified`. + +As the [Verifiable Credentials Data Model 1.0](https://www.w3.org/TR/vc-data-model/) states, such extension properties are best placed directly in either the JWT `vc` [claim](#dfn-claims) or the `credentialSubject` property of the `vc` [claim](#dfn-claims) as appropriate, although they **MAY** be placed directly into their own JWT [claims](#dfn-claims). + +If implementers wish to use JWT [claim](#dfn-claims) names for these extensions, the following steps are recommended. Note that there are three types of JWT [claim](#dfn-claims) name: public, named with a URI; private, named with a local name; and registered with IANA. + +1. First, check with IANA (https://www.iana.org/assignments/jwt/jwt.xhtml) to see if the JWT [claim](#dfn-claims) name already exists. +2. If it does not exist, the implementer may wish to either give it a public name (i.e., a URI), give it a local name (i.e., any string), or register it with IANA. +3. Once the JWT [claim](#dfn-claims) name exists, define encoding/decoding transformation rules to convert the [verifiable credential](#dfn-verifiable-credentials) property or `credentialSubject` property into the JWT [claim](#dfn-claims). + - *Encoding*: Remove the property from the [verifiable credential](#dfn-verifiable-credentials), encode it according to the defined rule, and place it in the JWT [claim](#dfn-claims) + - *Decoding*: Remove the value from the JWT [claim](#dfn-claims), decode it according to the defined rule, and place it in the new [verifiable credential](#dfn-verifiable-credentials) JSON object, as either a property of the [verifiable credential](#dfn-verifiable-credentials) or the `credentialSubject`, as appropriate. + +### 9.3 Human Readability[](#human-readability) + +The JSON-LD Context declaration mechanism is used by implementations to signal the context in which the data transmission is happening to consuming applications: + +[Example 11](#example-11-use-of-context-mechanism): Use of \@context mechanism + +``` nohighlight +{ + + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1" + ], + "id": "http://example.edu/credentials/1872", + ... +``` + +Extension authors are urged to publish two types of information at the context URLs. The first type of information is for machines, and is the machine-readable JSON-LD Context. The second type of information is for humans, and should be an HTML document. It is suggested that the default mode of operation is to serve the machine-readable JSON-LD Context as that is the primary intended use of the URL. If content-negotiation is supported, requests for `text/html` should result in a human readable document. The human readable document should at least contain usage information for the extension, such as the expected order of URLs associated with the `@context` property, specifications that elaborate on the extension, and examples of typical usage of the extension. + +## 10. Proof Formats[](#proof-formats) + +*This section is non-normative.* + +The [verifiable credentials](#dfn-verifiable-credentials) [data model](https://w3c.github.io/vc-data-model/) is designed to be proof format agnostic. [The specification](https://w3c.github.io/vc-data-model/) does not normatively require any particular digital proof or signature format. While the data model is the canonical representation of a [verifiable credential](#dfn-verifiable-credentials) or [verifiable presentation](#dfn-verifiable-presentations), the proving mechanisms for these are often tied to the syntax used in the transmission of the document between parties. As such, each proofing mechanism has to specify whether the validation of the proof is calculated against the state of the document as transmitted, against the transformed data model, or against another form. At the time of publication, at least two proof formats are being actively utilized by implementers, and the Working Group felt that documenting what these proof formats are and how they are being used would be beneficial to other implementers. + +This guide provides tables in section [Benefits of JWTs](#pf1b) and section [Benefits of JSON-LD and LD-Proofs](#pf1b) that compare three syntax and proof format ecosystems; JSON+JWTs, JSON-LD+JWTs, and JSON-LD+LD-Proofs. + +Because the Verifiable Credentials Data Model is extensible, and agnostic to any particular proof format, the specification and use of additional proof formats is supported. + +### 10.1 Benefits of JWTs[](#benefits-of-jwts) + +The Verifiable Credentials Data Model is designed to be compatible with a variety of existing and emerging syntaxes and digital proof formats. Each approach has benefits and drawbacks. The following table is intended to summarize a number of these native trade-offs. + +The table below compares three syntax and proof format ecosystems; JSON+JWTs, JSON-LD+JWTs, and JSON-LD+LD-Proofs. + + -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Feature JSON\ JSON‑LD\ JSON‑LD\ + +\ +\ +\ + JWTs JWTs LD‑Proofs + -------------------------------------------------------------------------------------------------------------------- ----------------- ----------------- ----------------- + [PF1a.](#pf1a) Proof format supports Zero-Knowledge Proofs. ✓ ✓ ✓ + + [PF2a.](#pf2a) Proof format supports arbitrary proofs such as Proof of Work, Timestamp Proofs, and Proof of Stake. ✓ ✓ ✓ + + [PF3a.](#pf3a) Based on existing official standards. ✓ ✖ ✖ + + [PF4a.](#pf4a) Designed to be small in size. ✓ ✖ ✖ + + [PF5a.](#pf5a) Offline support without further processing. ✓ ✖ ✖ + + [PF6a.](#pf6a) Wide adoption in other existing standards. ✓ ✓ ✖ + + [PF7a.](#pf7a) No type ambiguity. ✓ ✖ ✖ + + [PF8a.](#pf8a) Broad library support. ✓ ✖ ✖ + + [PF9a.](#pf9a) Easy to understand what is signed. ✓ ✓ ✖ + + [PF10a.](#pf10a) Ability to be used as authn/authz token with existing systems. ✓ ✓ ✖ + + [PF11a.](#pf11a) No additional canonicalization required. ✓ ✖ ✖ + + [PF12a.](#pf12a) No Internet PKI required. ✓ ✖ ✖ + + [PF13a.](#pf13a) No resolution of external documents needed. ✓ ✖ ✖ + -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +Note + +Some of the features listed in the table above are debateable, since a feature can always be added to a particular syntax or digital proof format. The table is intended to identify native features of each combination such that no additional language design or extension is required to achieve the identified feature. Features that all languages provide, such as the ability to express numbers, have not been included for the purposes of brevity. Find more information about different proof formats in the next section. + +PF1a: Proof format supports Zero-Knowledge Proofs. +: JWTs can embed `proof` attributes for repudiable proofs such as Zero-Knowledge Proofs. In that case, the JWS will not have an signature element. + +PF2a: Proof format supports arbitrary proofs such as Proof of Work, Timestamp Proofs, and Proof of Stake. +: JWTs can embed `proof` attributes for any type of proofs such as Proof of Work, Timestamp, Proofs, and Proof Stake. + +PF3a: Based on existing official standards. +: JSON and JWT are proposed and mature IETF standards. While JSON-LD 1.0 is in REC state in W3C, JSON-LD 1.1 is still in WD state. LD-Proofs are not standardized at all. + +PF4a: Designed to be small in size. +: JSON was invented as a simple data format to be transmitted on the wire. A verifiable credential can be expressed by its attributes only, without the necessity to introduce additional meta-information such as \@context. This makes the resulting JSON+JWT credential typically also smaller in size. + +PF5a: Offline support without further processing. +: A JWT can fully describe itself without the need to retrieve or verify any external documents. JSON-LD requires the context to be queryable and requires further documents to be accessible to check the prevalent document, e.g., LD-Proof. Additional caching needs to be implemented to support offline use cases. + +PF6a: Wide adoption in other existing standards. +: JWT founds its application in many other existing standards, e.g., OAuth2, OpenID Connect. This allows for backward compatibility with existing authentication and authorization frameworks without or with only minor modifications to these legacy systems. + +PF7a: No type ambiguity. +: It is best practice that JSON data structures typically do not expect changing types of their internal attributes. JSON-LD has implicit support for compact form serialization which transforms arrays with a single element only to switch its data type. Developers writing parsers have to implement special handling of these data types, which results in more code, is more error-prone and sometimes does not allow parsers based on code generation, which rely on static types. + +PF8a: Broad library support. +: JWT and JSON due to its maturity and standardization, have a lot of open-source library support. While JSON-LD 1.0 is a standard and has support for different programming languages, it is still behind JSON which is often part of the native platform toolchain, e.g., JavaScript. For LD-Proofs, on the other hand, only a few scattered libraries exist. + +PF9a: Easy to understand what is signed. +: JWT makes it visible what is signed in contrast to LD-Proofs, e.g., LD Signatures, that are detached from the actual payload and contain links to external documents which makes it not obvious for a developer to figure out what is part of the signature. + +PF10a: Ability to be used as authn/authz token with existing systems. +: Many existing applications rely on JWT for authentication and authorization purposes. In theory, developers maintaining these applications could leverage JWT-based verifiable presentations in their current systems with minor or no modifications. LD-Proofs represents a new approach which would require more work to achieve the same result. + +PF11a: No additional canonicalization required. +: Beyond base64 URL encoding JSON and JWT don\'t require any canonicalization to be transmitted on the wire. The JWS can be calculated on any data inside of the payload. This results in less computation, less complexity, and light-weight libraries compared to JSON-LD and LD-Proofs where canonicalization is required. + +PF12a: No Internet PKI required. +: JSON-LD and LD-Proofs rely on resolving external documents, e.g., `@context`. This means that a verifiable credential system would rely on existing Internet PKI to a certain extend and cannot be fully decentralized. A JWT-based system does not need to introduce this dependency. + +PF13a: No resolution of external documents needed. +: JSON-LD and LD-Proofs require the resolution of external documents, which leads to an increased network load for the verifier of a verifiable presentation. This needs to be mitigated through caching strategies. + +### 10.2 Benefits of JSON-LD and LD-Proofs[](#benefits-of-json-ld-and-ld-proofs) + +The Verifiable Credentials Data Model is designed to be compatible with a variety of existing and emerging syntaxes and digital proof formats. Each approach has benefits and drawbacks. The following table is intended to summarize a number of these native trade-offs. + +The table below compares three syntax and proof format ecosystems; JSON+JWTs, JSON-LD+JWTs, and JSON-LD+LD-Proofs. Readers should be aware that Zero-Knowledge Proofs are currently proposed as a sub-type of LD-Proofs and thus fall into the final column below. + + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Feature JSON\ JSON‑LD\ JSON‑LD\ + +\ +\ +\ + JWTs JWTs LD‑Proofs + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------- ----------------- ----------------- + [PF1b.](#pf1b) Support for open world data modelling. ✖ ✓ ✓ + + [PF2b.](#pf2b) Universal identifier mechanism for JSON objects via the use of URIs. ✖ ✓ ✓ + + [PF3b.](#pf3b) A way to disambiguate properties shared among different JSON documents by mapping them to IRIs via a context. ✖ ✓ ✓ + + [PF4b.](#pf4b) A mechanism to refer to data in an external document, where the data may be merged with the local document without a merge conflict in semantics or structure. ✖ ✓ ✓ + + [PF5b.](#pf5b) The ability to annotate strings with their language. ✖ ✓ ✓ + + [PF6b.](#pf6b) A way to associate arbitrary datatypes, such as dates and times, with arbitrary property values. ✖ ✓ ✓ + + [PF7b.](#pf7b) A facility to express one or more directed graphs, such as a social network, in a single document. ✖ ✓ ✓ + + [PF8b.](#pf8b) Supports signature sets. ✖ ✖ ✓ + + [PF9b.](#pf9b) Embeddable in HTML such that search crawlers will index the machine-readable content. ✖ ✖ ✓ + + [PF10b.](#pf10b) Data on the wire is easy to debug and serialize to database systems. ✖ ✖ ✓ + + [PF11b.](#pf11b) Nesting signed data does not cause data size to double for every embedding. ✖ ✖ ✓ + + [PF12b.](#pf12b) Proof format supports Zero-Knowledge Proofs. ✖ ✖ ✓ + + [PF13b.](#pf13b) Proof format supports arbitrary proofs such as Proof of Work, Timestamp Proofs, and Proof of Stake. ✖ ✖ ✓ + + [PF14b.](#pf14b) Proofs can be expressed unmodified in other data syntaxes such as YAML, N-Quads, and CBOR. ✖ ✖ ✓ + + [PF15b.](#pf15b) Changing property-value ordering, or introducing whitespace does not invalidate signature. ✖ ✖ ✓ + + [PF16b.](#pf16b) Designed to easily support experimental signature systems. ✖ ✖ ✓ + + [PF17b.](#pf17b) Supports signature chaining. ✖ ✖ ✓ + + [PF18b.](#pf18b) Does not require pre-processing or post-processing. ✖ ✖ ✓ + + [PF19b.](#pf19b) Canonicalization requires only base-64 encoding. ✖ ✖ ✓ + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +Note + +Some of the features listed in the table above are debateable, since a feature can always be added to a particular syntax or digital proof format. The table is intended to identify native features of each combination such that no additional language design or extension is required to achieve the identified feature. Features that all languages provide, such as the ability to express numbers, have not been included for the purposes of brevity. + +PF1b: Support for open world data modelling +: An *open world data model* is one where any entity can make any statement about anything while simultaneously ensuring that the semantics of the statement are unambiguous. This specification is enabled by an open world data model called Linked Data. One defining characteristic of supporting an open world data model is the ability to specify the semantic context in which data is being expressed. JSON-LD provides this mechanism via the `@context` property. JSON has no such feature. + +PF2b: Universal identifier mechanism for JSON objects via the use of URIs. +: All entities in a JSON-LD document are identified either via an automatic URI, or via an explicit URI. This enables all entities in a document to be unambiguously referenced. JSON does not have a native URI type nor does it require objects to have one, making it difficult to impossible to unambiguously identify an entity expressed in JSON. + +PF3b: A way to disambiguate properties shared among different JSON documents by mapping them to IRIs via a context. +: All object properties in a JSON-LD document, such as the property \"homepage\", are either keywords or they are mapped to an IRI. This feature enables open world systems to identify the semantic meaning of the property in an unambiguous way, which enables seamless merging of data between disparate systems. JSON object properties are not mapped to IRIs, which result in ambiguities with respect to the semantic meaning of the property. For example, one JSON document might use \"title\" (meaning \"book title\") in a way that is semantically incompatible with another JSON document using \"title\" (meaning \"job title\"). + +PF4b: A mechanism to refer to data in an external document, where the data may be merged with the local document without a merge conflict in semantics or structure. +: JSON-LD provides a mechanism that enables a data value to use a URL to refer to data outside of the local document. This external data may then be automatically merged with the local document without a merge conflict in semantics or structure. This feature enables a system to apply the \"follow your nose\" principle to discover a richer set of data that is associated with the local document. While a JSON document can contain pointers to external data, interpreting the pointer is often application specific and usually does not support merging the external data to construct a richer data set. + +PF5b: The ability to annotate strings with their language. +: JSON-LD enables a developer to specify the language, such as English, French, or Japanese, in which a text string is expressed via the use of language tags. JSON does not provide such a feature. + +PF6b: A way to associate arbitrary datatypes, such as dates and times, with arbitrary property values. +: JSON-LD enables a developer to specify the data type of a property value, such as Date, unsigned integer, or Temperature by specifying it in the JSON-LD Context. JSON does not provide such a feature. + +PF7b: A facility to express one or more directed graphs, such as a social network, in a single document. +: JSON-LD\'s abstract data model supports the expression of information as a directed graph of labeled nodes and edges, which enables an open world data model to be supported. JSON\'s abstract data model only supports the expression of information as a tree of unlabeled nodes and edges, which restricts the types of relationships and structures that can be natively expressed in the language. + +PF8b: Supports signature sets. +: A signature set is an unordered set of signatures over a data payload. Use cases, such as cryptographic signatures applied to a legal contract, typically require more than one signature to be associated with the contract in order to legally bind two or more parties under the terms of the contract. Linked Data Proofs, including Linked Data Signatures, natively support sets of signatures. JWTs only enable a single signature over a single payload. + +PF9b: Embeddable in HTML such that search crawlers will index the machine-readable content. +: All major search crawlers natively parse and index information expressed as JSON-LD in HTML pages. LD-Proofs enable the current data format that search engines use to be extended to support digital signatures. JWTs have no mechanism to express data in HTML pages and are currently not indexed by search crawlers. + +PF10b: Data on the wire is easy to debug and serialize to database systems. +: When developers are debugging software systems, it is beneficial for them to be able to see the data that they are operating on using common debugging tools. Similarly, it is useful to be able to serialize data from the network to a database and then from the database back out to the network using a minimal number of pre and post processing steps. LD-Proofs enable developers to use common JSON tooling without having to convert the format into a different format or structure. JWTs base-64 encode payload information, resulting in complicated pre and post processing steps to convert the data into JSON data while not destroying the digital signature. Similarly, schema-less databases, which are typically used to index JSON data, cannot index information that is expressed in an opaque base-64 encoded wrapper. + +PF11b: Nesting signed data does not cause data size to double for every embedding. +: When a JWT is encapsulated by another JWT, the entire payload must be base-64 encoded in the initial JWT, and then base-64 encoded again in the encapsulating JWT. This is often necessary when a cryptographic signature is required on a document that contains a cryptographic signature, such as when a Notary signs a document that has been signed by someone else seeking the Notary\'s services. LD-Proofs do not require base-64 encoding the signed portion of a document and instead rely on a canonicalization process that is just as secure, and that only requires the cryptographic signature to be encoded instead of the entire payload. + +PF12b: Proof format supports Zero-Knowledge Proofs. +: The LD-Proof format is capable of modifying the algorithm that generates the hash or hashes that are cryptographically signed. This cryptographic agility enables digital signature systems, such as Zero-Knowledge Proofs, to be layered on top of LD-Proofs instead of an entirely new digital signature container format to be created. JWTs are designed such that an entirely new digital signature container format will be required to support Zero-Knowledge Proofs. + +PF13b: Proof format supports arbitrary proofs such as Proof of Work, Timestamp Proofs, and Proof of Stake. +: The LD-Proof format was designed with a broader range of proof types in mind and supports cryptographic proofs beyond simple cryptographic signatures. These proof types are in common usage in systems such as decentralized ledgers and provide additional guarantees to [verifiable credentials](#dfn-verifiable-credentials), such as the ability to prove that a particular claim was made at a particular time or that a certain amount of energy was expended to generate a particular credential. The JWT format does not support arbitrary proof formats. + +PF14b: Proofs can be expressed unmodified in other data syntaxes such as XML, YAML, N-Quads, and CBOR. +: The LD-Proof format utilizes a canonicalization algorithm to generate a cryptographic hash that is used as an input to the cryptographic proof algorithm. This enables the bytes generated as the cryptographic proof to be compact and expressible in a variety of other syntaxes such as XML, YAML, N-Quads, and CBOR. Since JWTs require the use of JSON to be generated, they are inextricably tied to the JSON syntax. + +PF15b: Changing property-value ordering, or introducing whitespace does not invalidate signature. +: Since LD-Proofs utilize a canonicalization algorithm, the introduction of whitespace that does not change the meaning of the information being expressed has no effect on the final cryptographic hash over the information. This means that simple changes in whitespace formatting, such as those changes made when writing data to a schema-less database and then retrieving the same information from the same database do not cause the digital signature to fail. JWTs encode the payload using the base-64 format which is not resistant to whitespace formatting that has no effect on the information expressed. This shortcoming of JWTs make it challenging to, for example, express signed data in web pages that search crawlers index. + +PF16b: Designed to easily support experimental signature systems. +: The LD-Proof format is naturally extensible, not requiring the format to be extended in a formal international standards working group in order to prevent namespace collisions. The JWT format requires entries in a centralized registry in order to avoid naming collisions and does not support experimentation as easily as the LD-Proof format does. LD-Proof format extension is done through the decentralized publication of cryptographic suites that are guaranteed to not conflict with other LD-Proof extensions. This approach enables developers to easily experiment with new cryptographic signature mechanisms that support selective disclosure, zero-knowledge proofs, and post-quantum algorithms. + +PF17b: Supports signature chaining. +: A signature chain is an ordered set of signatures over a data payload. Use cases, such as cryptographic signatures applied to a notarized document, typically require a signature by the signing party and then an additional one by a notary to be made after the original signing party has made their signature. Linked Data Proofs, including Linked Data Signatures, natively support chains of signatures. JWTs only enable a single signature over a single payload. + +PF18b: Does not require pre-processing or post-processing. +: In order to encode a [verifiable credential](#dfn-verifiable-credentials) or a [verifiable presentation](#dfn-verifiable-presentations) in a JWT, an extra set of steps are required to convert the data to and from the JWT format. No such extra converstion step are required for [verifiable credentials](#dfn-verifiable-credentials) and [verifiable presentations](#dfn-verifiable-presentations) protected by LD-Proofs. + +PF19b: Canonicalization requires only base-64 encoding. +: The JWT format utilizes a simple base-64 encoding format to generate the cryptographic hash of the data. The encoding format for LD-Proofs requires a more complex canonicalization algorithm to generate the cryptographic hash. The benefits of the JWT approach are simplicity at the cost of encoding flexibility. The benefits of the LD-Proof approach are flexibility at the cost of implementation complexity. + +## 11. Zero-Knowledge Proofs[](#zero-knowledge-proofs) + +*This section is non-normative* + +The Verifiable Credentials Data Model is designed to be compatible with a variety of existing and emerging digital proof formats. Each proof format has benefits and drawbacks. Many proof formats cannot selectively reveal attribute values from a verifiable credential; they can only reveal all (or none). + +Zero-Knowledge Proofs (ZKPs) are a proof format that enables data-minimization features in [verifiable presentations](#dfn-verifiable-presentations), such as selective disclosure and predicate proofs. + +### Full Disclosure[](#zero-knowledge-proofs) + +Currently, disclosing data is an all or nothing process, whether online or off. Many digital identity systems reveal all the attributes in a digital credential. The simplest method for signing a [verifiable credential](#dfn-verifiable-credentials) signs the entire credential and when presented, fully discloses all the attributes. + +Along with a full disclosure of all the attributes in a [verifiable credential](#dfn-verifiable-credentials), standard [verifiable presentations](#dfn-verifiable-presentations) reveal the actual signature. With both the data and signature in hand, a [verifier](#dfn-verifier) has a complete copy of the credential. Without care, this could enable the [verifier](#dfn-verifier) to impersonate the [holder](#dfn-holders). Also, since the signature is the same every time this credential is presented, the signature itself is a unique identifier and becomes PII (personally identifiable information). + +It is also possible to fully disclose the attributes in a zero-knowledge [verifiable credential](#dfn-verifiable-credentials). Unlike non-ZKP methods, zero-knowledge methods do not reveal the actual signature; instead, they only reveal a cryptographic proof of a valid signature. Only the [holder](#dfn-holders) of the signature has the information needed to present the [credential](#dfn-credential) to a [verifier](#dfn-verifier). This means that zero-knowledge methods provide a [holder](#dfn-holders) additional protection from impersonation. Because the signature is not revealed, it also cannot be used as a unique identifier. + +### Selective Disclosure[](#zero-knowledge-proofs) + +Selective disclosure means that a [holder](#dfn-holders) doesn\'t have to reveal all of the attributes contained in a [verifiable credential](#dfn-verifiable-credentials). This reduces the liability of handling or holding data that it is not necessary to share or collect. + +Non-ZKP methods for selective disclosure often require the credential issuer to create a unique [credential](#dfn-credential) for each individual attribute, or possible combination of attributes. This could quickly become impractical as the number of [credentials](#dfn-credential) or combinations thereof exponentially explodes. Atomic [credentials](#dfn-credential) (which only contain a single attribute) may also not guarantee that the data is properly paired when used in a [verifiable presentation](#dfn-verifiable-presentations). For example, a [holder](#dfn-holders) has two vehicle credentials, one for a 2018 Mazda with 15,000 miles and the other for a 1965 Lincoln with 350,000 miles. With atomic credentials it may be possible to claim the user has a 1965 Lincoln with 15,000 miles. + +Zero-knowledge methods allow a [holder](#dfn-holders) to choose which attributes to reveal and which attributes to withhold on a case-by-case basis without involving the [issuer](#dfn-issuers). The [credential](#dfn-credential) [issuer](#dfn-issuers) only needs to provide a single [verifiable credential](#dfn-verifiable-credentials) that contains all of the attributes. Each attribute is individually incorporated into the signature. This enables two options: to reveal the attribute or to prove that you know the value of the attribute without revealing it. For example, a credential with attributes for name, birthdate, and address can be used in a presentation to reveal only your name. + +Non-ZKP methods implementing selective disclosure often requires the cooperation of the [issuer](#dfn-issuers). Selective disclosure using zero-knowledge methods gives the [holder](#dfn-holders) personal control over what to reveal. A [verifiable presentation](#dfn-verifiable-presentations) based on zero-knowledge proof mechanisms only contains those attributes and associated values that are required to satisfy the presentation requirements. + +### Predicate Proofs[](#zero-knowledge-proofs) + +A predicate proof is a proof that answers a true-or-false question. For example, \"Are you over the age of 18?\" Using non-ZKP methods, predicate proofs must be provided by the [issuer](#dfn-issuers) as one of the attributes of a [verifiable credential](#dfn-verifiable-credentials). This means that in order for a non-ZKP [credential](#dfn-credential) to be used to prove age-over-18, it would need to contain the attribute age-over-18. This [credential](#dfn-credential) could not be used to reveal your birthdate, unless it also included a birthdate [claim](#dfn-claims). It also couldn\'t be used to prove age-over-25. To prove age-over-25, the [holder](#dfn-holders) would need to have received a [credential](#dfn-credential) with an age-over-25 [claim](#dfn-claims). + +Using zero-knowledge methods, predicate proofs can be generated by the [holder](#dfn-holders) at the time of [presentation](#dfn-presentations) without [issuer](#dfn-issuers) involvement. For example, a [verifiable credential](#dfn-verifiable-credentials) with the [claim](#dfn-claims) birthdate can be used in a [verifiable presentation](#dfn-verifiable-presentations) to prove age-over-18. The same [credential](#dfn-credential) could then be used in another [presentation](#dfn-presentations) to prove age-over-25, all without revealing the [holder\'s](#dfn-holders) birthdate. + +### Revocation[](#zero-knowledge-proofs) + +[Verifiable credentials](#dfn-verifiable-credentials) may need to be revocable. If an [issuer](#dfn-issuers) can revoke a [credential](#dfn-credential), [verifiers](#dfn-verifier) must be able to determine a [credential\'s](#dfn-credential) revocation status. + +Non-ZKP methods for checking revocation status may require the [verifier](#dfn-verifier) to directly contact the [issuer](#dfn-issuers). Less restrictive checks could be made against a list of revoked credential identifiers posted in a public registry. The [holder](#dfn-holders) is required to disclose the [credential](#dfn-credential) identifier to the [verifier](#dfn-verifier) so that it can be checked. The [verifier](#dfn-verifier) is then responsible for doing the work to check revocation. + +Using zero-knowledge methods, the [credential](#dfn-credential) identifier can be checked against a list of revoked credential identifiers without revealing the identifier. This reduces the ability of network monitors to correlate a [holder\'s](#dfn-holders) credential presentations, and removes the ability of an [issuer](#dfn-issuers) to be made aware of the presentation of [verifiable credentials](#dfn-verifiable-credentials) they have issued. + +### Correlation[](#zero-knowledge-proofs) + +Correlation is the ability to link data from multiple interactions to a single user. Correlation can be performed by a [verifier](#dfn-verifier), by [issuers](#dfn-issuers) and [verifiers](#dfn-verifier) working together, or by a third party observing interactions on the network. Correlation is a way to collect data about a [holder](#dfn-holders) without the [holder\'s](#dfn-holders) consent or knowledge. It is also a way to deanonymize private transactions. For example, a [holder](#dfn-holders) might use a [verifiable credential](#dfn-verifiable-credentials) to prove they are authorized to vote, then submit a secret ballot. If it is possible to correlate the [holder\'s](#dfn-holders) [credential](#dfn-credential) with the secret ballot, thereby linking a specific vote to a specific voter, it would be detrimental to the democratic process and could enable retaliation. + +One way to reduce correlation is through data minimization, by sharing only the information required to complete a transaction. Another way to reduce correlation is to make each interaction look unique. When interactions disclose unique identifiers, an observer can link multiple interactions to a single user. Non-ZKP methods with only a single identifier per user create correlation opportunities by embedding that identifier in multiple credentials or interactions. Zero-knowledge proofs remove this linkability between interactions. + +Non-ZKP methods that reveal all attributes and use unique identifiers are completely correlatable. Zero-knowledge methods enable data minimization and allow [holders](#dfn-holders) to have trusted interactions with [verifiers](#dfn-verifier) without dependence on unique identifiers. + +Although correlation can never be eliminated completely, the goal of zero-knowledge methods is to reduce the probability of correlation and to put control over the level of correlation into the hands of the [verifiable credential](#dfn-verifiable-credentials) [holder](#dfn-holders). + +### Drawbacks[](#zero-knowledge-proofs) + +Zero-knowledge methods are more complex than non-ZKP methods. Cryptographic engineers must understand complicated protocols and write code to create libraries that support zero-knowledge methods. System implementers can then use these libraries without being exposed to the underlying complexity, but must trust that the implementation was done correctly. They can utilize the features of selective disclosure and bring the benefits of the method to their customers without a significant increase in effort over using non-ZKP methods. + +Due to the underlying complexity, zero-knowledge methods require more CPU and memory to use. This also adds to the time required to create and verify proofs. This should be considered when using less capable devices such as IOT devices or older phones. + +Another drawback of zero-knowledge proofs is that they tend to be larger than simple signatures. + +There is a perception that zero-knowledge methods are new and untested. Zero-knowledge methods were first introduced in 1989 as a way to guard secrets. Although they may not be well understood by the general public, they have received considerable review and scrutiny in the cryptographic community. They are considered just as secure as many common cryptographic techniques in use today. + +## 12. Progressive Trust[](#progressive-trust) + +*This section is non-normative.* + +Entities that use [verifiable credentials](#dfn-verifiable-credentials) and [verifiable presentations](#dfn-verifiable-presentations) should follow protocols that enable progressive trust. Progressive trust refers to enabling individuals to share information about themselves only on an as needed basis, slowing building up more trust as more information is shared with another party. + +Progressive trust is strongly related to the principle of data minimization, and enabled by technologies such as selective disclosure and predicate proofs. We encourage the use of progressive trust as a guiding principle for implementers as they develop protocols for [issuers](#dfn-issuers), [holders](#dfn-holders), and [verifiers](#dfn-verifier). + +### 12.1 Data Minimization[](#data-minimization) + +Data minimization is a principle that encourages [verifiers](#dfn-verifier) to request the minimum amount of data necessary from [holders](#dfn-holders), and for [holders](#dfn-holders) to only provide the minimum amount of data to [verifiers](#dfn-verifier). This \"minimum amount of data\" depends on the situation and may change over the course of a [holder](#dfn-holders)\'s interaction with a [verifier](#dfn-verifier). + +For example, a [holder](#dfn-holders) may apply for a loan, with a bank acting as the [verifier](#dfn-verifier). There are several points at which the bank may want to determine whether the [holder](#dfn-holders) is qualified to continue in the process of applying for the loan; for instance, the bank may have a policy of only providing loans to existing account holders. A protocol that follows the principle of data minimization would allow the [holder](#dfn-holders) to reveal to the [verifier](#dfn-verifier) only that they are an existing account holder, before the bank requests any additional information, such as account balances or employment status. In this way, the applicant may progressively entrust the bank with more information, as the data needed by the bank to make its determinations is requested a piece at a time, as needed, rather than as a complete set, up front. + +### 12.2 Selective Disclosure[](#selective-disclosure) + +Selective disclosure is the ability of a [holder](#dfn-holders) to select some elements of a [verifiable credential](#dfn-verifiable-credentials) to share with a [verifier](#dfn-verifier), without revealing the rest. There are several different methods which support selective disclosure, we provide three examples: + +- **Atomic Credentials** - These are [verifiable credentials](#dfn-verifiable-credentials) which consist of a single claim. An [issuer](#dfn-issuers) may provide a set of atomic credentials that duplicates the claims of a standard credential. This atomicity allows a [holder](#dfn-holders) to disclose only those claims which need to be revealed to a [verifier](#dfn-verifier), rather than requiring all of the claims of a standard credential to be revealed. +- **Selective Disclosure Signatures** - Certain signature schemes natively support selective disclosure of [verifiable credential](#dfn-verifiable-credentials) claims. One example of these is [Camenisch-Lysyanskaya signatures](https://groups.csail.mit.edu/cis/pubs/lysyanskaya/cl02b.pdf). Such Signatures allow a [holder](#dfn-holders) to disclose only those claims which need to be revealed to a [verifier](#dfn-verifier), rather than requiring all of the credential\'s claims to be revealed. +- **Hashed Values** - With this method, the [issuer](#dfn-issuers) issues a single [verifiable credential](#dfn-verifiable-credentials) containing all the [issuer](#dfn-issuers)\'s [claims](#dfn-claims) about the subject. However, each [claim](#dfn-claims) value is created by hashing the actual value with a different nonce so that the [verifier](#dfn-verifier) cannot determine the actual value. There are several different ways of modeling this, and no standard way is currently defined. The [holder](#dfn-holders) includes the actual values of the [claims](#dfn-claims) that are to be revealed to the [verifier](#dfn-verifier) in the [verifiable presentation](#dfn-verifiable-presentations). + +### 12.3 Predicates[](#predicates) + +Another technique which may be used to support progressive trust is to use predicates as the values of revealed claims. Predicates allow a [holder](#dfn-holders) to provide True/False values to a [verifier](#dfn-verifier) rather than revealing claim values. + +Predicate proofs may be enabled by [verifiable credential](#dfn-verifiable-credentials) [issuers](#dfn-issuers) as claims, e.g., the `credentialSubject` may include an `ageOver18` property rather than a `birthdate` property. This would allow [holders](#dfn-holders) to provide proof that they are over 18 without revealing their birthdates. + +Certain signature types enable predicate proofs by allowing claims from a standard [verifiable credential](#dfn-verifiable-credentials) to be presented as predicates. For example, a [Camenisch-Lysyanskaya signed](https://groups.csail.mit.edu/cis/pubs/lysyanskaya/cl02b.pdf) [verifiable credential](#dfn-verifiable-credentials) that contains a `credentialSubject` with a `birthdate` property may be included in a [verifiable presentation](#dfn-verifiable-presentations) as a derived credential that contains an `ageOver18` property. + +### 12.4 Further Techniques[](#further-techniques) + +The examples provided in this section are intended to illustrate some possible mechanisms for supporting progressive trust, not provide an exhaustive or comprehensive list of all the ways progressive trust may be supported. Research in this area continues with the use of cutting-edge proof techniques such as [zk-SNARKS](https://z.cash/technology/zksnarks/) and [Bulletproofs](https://crypto.stanford.edu/bulletproofs/), as well as different signature protocols. + +A draft report by the [Credentials Community Group](https://www.w3.org/community/credentials/) on [data minimization](https://w3c-ccg.github.io/data-minimization/) may also be useful reading for implementers looking to enable progressive trust. + +## 13. Related Specifications[](#related-specifications) + +### 13.1 Web Authentication[](#web-authentication) + +The W3C [Web Authentication](https://www.w3.org/TR/webauthn/) specification extends the capabilities of in-browser web applications by enabling them to strongly authenticate users with the aid of scoped public key-based credentials. It defines the idea of [authenticators](https://www.w3.org/TR/webauthn/#authenticator), which are cryptographic entities that can generate and store public key credentials at the behest of a Relying Party, subject to user consent, mediated by the web browser to preserve user privacy. + +Since the key based credentials created by [Web Authentication Level 1](https://www.w3.org/TR/webauthn/) authenticators are narrowly scoped to a particular Relying Party origin, they are unsuited (in their current form) to general purpose signature and verification operations. However, many web developers working with [Verifiable Credentials](#dfn-verifiable-credentials) have expressed interest in leveraging the Web Authentication API, since it provides a secure browser-mediated interface to crucial key management infrastructure. + +The Web Authentication Working Group has agreed to address this use case in the WebAuthn Level 2 specification, and is currently working to enable the kind of [cross-origin usage](https://github.com/w3c/webauthn/issues/911) that would allow the WebAuthn API to be used for [verifiable presentations](#dfn-verifiable-presentations). For example, verifiable credential wallets could allow authentication based on verifiable presentations, by using WebAuthn authenticators to sign those presentations with challenges from verifier websites. + +## 14. Test suite[](#test-suite) + +*This section is non-normative.* + +The W3C Verifiable Claims Working Group has produced a [test suite](https://github.com/w3c/vc-test-suite/) in order for implementers to confirm their conformance with the current specifications. + +You can review the [current implementation report](https://w3c.github.io/vc-test-suite/implementations/), which contains conformance testing results for submitted implementations supporting the Verifiable Credentials Data Model specification. + +## A. References[](#references) + +### A.1 Informative references[](#informative-references) + +\[RFC3986\] +: [Uniform Resource Identifier (URI): Generic Syntax](https://tools.ietf.org/html/rfc3986). T. Berners-Lee; R. Fielding; L. Masinter. IETF. January 2005. Internet Standard. URL: + +\[vc-data-model\] +: [Verifiable Credentials Data Model 1.0](https://www.w3.org/TR/vc-data-model/). Manu Sporny; Grant Noble; Dave Longley; Daniel Burnett; Brent Zundel. W3C. 5 September 2019. W3C Proposed Recommendation. URL: + +[↑](#toc) diff --git a/src/Codebooks/AtContextsEnum.php b/src/Codebooks/AtContextsEnum.php index 912e997..3d1c527 100644 --- a/src/Codebooks/AtContextsEnum.php +++ b/src/Codebooks/AtContextsEnum.php @@ -7,4 +7,6 @@ enum AtContextsEnum: string { case W3Org2018CredentialsV1 = 'https://www.w3.org/2018/credentials/v1'; + + case W3OrgNsCredentialsV2 = 'https://www.w3.org/ns/credentials/v2'; } diff --git a/src/Codebooks/ClaimsEnum.php b/src/Codebooks/ClaimsEnum.php index 88c6a3a..b99c6f1 100644 --- a/src/Codebooks/ClaimsEnum.php +++ b/src/Codebooks/ClaimsEnum.php @@ -15,9 +15,15 @@ enum ClaimsEnum: string // @context case AtContext = '@context'; + case AtDirection = '@direction'; + + case AtLanguage = '@language'; + // @type case AtType = '@type'; + case AtValue = '@value'; + // Authentication Context Class Reference case Acr = 'acr'; @@ -447,6 +453,10 @@ enum ClaimsEnum: string case UserinfoSigningAlgValuesSupported = 'userinfo_signing_alg_values_supported'; + case ValidFrom = 'validFrom'; + + case ValidUntil = 'validUntil'; + // VerifiableCredential case Vc = 'vc'; diff --git a/src/Codebooks/ContentTypesEnum.php b/src/Codebooks/ContentTypesEnum.php index ee2444c..5c119b6 100644 --- a/src/Codebooks/ContentTypesEnum.php +++ b/src/Codebooks/ContentTypesEnum.php @@ -8,11 +8,27 @@ enum ContentTypesEnum: string { case ApplicationDcSdJwt = 'application/dc+sd-jwt'; - case ApplicationJwt = 'application/jwt'; - case ApplicationEntityStatementJwt = 'application/entity-statement+jwt'; + case ApplicationJwt = 'application/jwt'; + case ApplicationTrustMarkJwt = 'application/trust-mark+jwt'; case ApplicationTrustMarkStatusResponseJwt = 'application/trust-mark-status-response+jwt'; + + case ApplicationVc = 'application/vc'; + + case ApplicationVcCose = 'application/vc+cose'; + + case ApplicationVcJwt = 'application/vc+jwt'; + + case ApplicationVcSdJwt = 'application/vc+sd-jwt'; + + case ApplicationVp = 'application/vp'; + + case ApplicationVpCose = 'application/vp+cose'; + + case ApplicationVpJwt = 'application/vp+jwt'; + + case ApplicationVpSdJwt = 'application/vp+sd-jwt'; } diff --git a/src/Codebooks/CredentialFormatIdentifiersEnum.php b/src/Codebooks/CredentialFormatIdentifiersEnum.php index 41bf030..ef7b6da 100644 --- a/src/Codebooks/CredentialFormatIdentifiersEnum.php +++ b/src/Codebooks/CredentialFormatIdentifiersEnum.php @@ -10,6 +10,10 @@ enum CredentialFormatIdentifiersEnum: string // VC signed as a JWT, not using JSON-LD case JwtVcJson = 'jwt_vc_json'; + // VC Data Model v2.0 secured with SD-JWT + // https://www.w3.org/TR/vc-jose-cose/#with-sd-jwt + case VcSdJwt = 'vc+sd-jwt'; + // VC signed as a JWT, using JSON-LD case JwtVcJsonLd = 'jwt_vc_json-ld'; @@ -22,7 +26,4 @@ enum CredentialFormatIdentifiersEnum: string // IETF SD-JWT VC case DcSdJwt = 'dc+sd-jwt'; - - // Deprecated identifier for IETF SD-JWT VC. Use 'dc+sd-jwt' instead. - case VcSdJwt = 'vc+sd-jwt'; } diff --git a/src/Factories/ClaimFactory.php b/src/Factories/ClaimFactory.php index f8e4e78..2e74cc0 100644 --- a/src/Factories/ClaimFactory.php +++ b/src/Factories/ClaimFactory.php @@ -11,6 +11,7 @@ use SimpleSAML\OpenID\ValueAbstracts\GenericClaim; use SimpleSAML\OpenID\ValueAbstracts\JwksClaim; use SimpleSAML\OpenID\VerifiableCredentials\VcDataModel\Factories\VcDataModelClaimFactory; +use SimpleSAML\OpenID\VerifiableCredentials\VcDataModel2\Factories\VcDataModel2ClaimFactory; class ClaimFactory { @@ -18,6 +19,8 @@ class ClaimFactory protected VcDataModelClaimFactory $vcDataModelClaimFactory; + protected VcDataModel2ClaimFactory $vcDataModel2ClaimFactory; + public function __construct( protected readonly Helpers $helpers, @@ -43,6 +46,15 @@ public function forVcDataModel(): VcDataModelClaimFactory } + public function forVcDataModel2(): VcDataModel2ClaimFactory + { + return $this->vcDataModel2ClaimFactory ??= new VcDataModel2ClaimFactory( + $this->helpers, + $this, + ); + } + + /** * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException */ diff --git a/src/ValueAbstracts/LanguageValueObject.php b/src/ValueAbstracts/LanguageValueObject.php new file mode 100644 index 0000000..6c91165 --- /dev/null +++ b/src/ValueAbstracts/LanguageValueObject.php @@ -0,0 +1,84 @@ +value === '0') { + throw new InvalidValueException('Language value object @value must be a non-empty string.'); + } + + if ($this->direction !== null && !in_array($this->direction, ['ltr', 'rtl'], true)) { + throw new InvalidValueException('Language value object @direction must be "ltr" or "rtl".'); + } + + if ($this->language === '0') { + throw new InvalidValueException('Language value object @language must be a non-empty string.'); + } + } + + + /** + * @return non-empty-string + */ + public function getValue(): string + { + return $this->value; + } + + + /** + * @return non-empty-string|null + */ + public function getLanguage(): ?string + { + return $this->language; + } + + + /** + * @return 'ltr'|'rtl'|null + */ + public function getDirection(): ?string + { + return $this->direction; + } + + + /** + * @return array + */ + public function jsonSerialize(): array + { + $result = [ + ClaimsEnum::AtValue->value => $this->value, + ]; + + if ($this->language !== null) { + $result[ClaimsEnum::AtLanguage->value] = $this->language; + } + + if ($this->direction !== null) { + $result[ClaimsEnum::AtDirection->value] = $this->direction; + } + + return $result; + } +} diff --git a/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValue.php b/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValue.php new file mode 100644 index 0000000..5f8fc1f --- /dev/null +++ b/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValue.php @@ -0,0 +1,41 @@ +claimName; + } + + + public function getValue(): LanguageValueObject + { + return $this->languageValueObject; + } + + + /** + * @return array + */ + public function jsonSerialize(): array + { + return $this->languageValueObject->jsonSerialize(); + } +} diff --git a/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValueBag.php b/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValueBag.php new file mode 100644 index 0000000..2c71a5b --- /dev/null +++ b/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValueBag.php @@ -0,0 +1,80 @@ +values = [$firstValue, ...$values]; + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + */ + public function getFirstValueOrFail(): LocalizableStringValue + { + return $this->values[0] ?? throw new VcDataModelException('No values found'); + } + + + public function getName(): string + { + return $this->getFirstValueOrFail()->getName(); + } + + + /** + * @return \SimpleSAML\OpenID\VerifiableCredentials\VcDataModel\Claims\LocalizableStringValue[] + */ + public function getValue(): array + { + return $this->values; + } + + + /** + * Get a value by language tag (optional language filtering). + * + * @param non-empty-string|null $language + */ + public function getValueByLanguage(?string $language = null): ?LocalizableStringValue + { + if ($language === null) { + // Return first value if no language specified + return $this->values[0] ?? null; + } + + foreach ($this->values as $value) { + if ($value->getValue()->getLanguage() === $language) { + return $value; + } + } + + return null; + } + + + /** + * @return array> + */ + public function jsonSerialize(): array + { + return array_map( + fn(LocalizableStringValue $value): array => $value->jsonSerialize(), + $this->values, + ); + } +} diff --git a/src/VerifiableCredentials/VcDataModel/Claims/VcAtContextClaimValue.php b/src/VerifiableCredentials/VcDataModel/Claims/VcAtContextClaimValue.php index 7c8b8a1..dac3412 100644 --- a/src/VerifiableCredentials/VcDataModel/Claims/VcAtContextClaimValue.php +++ b/src/VerifiableCredentials/VcDataModel/Claims/VcAtContextClaimValue.php @@ -18,11 +18,12 @@ class VcAtContextClaimValue implements ClaimInterface public function __construct( protected readonly string $baseContext, protected readonly array $otherContexts, + AtContextsEnum $expectedBaseContext = AtContextsEnum::W3Org2018CredentialsV1, ) { - if ($this->baseContext !== AtContextsEnum::W3Org2018CredentialsV1->value) { + if ($this->baseContext !== $expectedBaseContext->value) { throw new VcDataModelException(sprintf( 'Invalid VC @context claim. Base context should be %s, %s given.', - AtContextsEnum::W3Org2018CredentialsV1->value, + $expectedBaseContext->value, $this->baseContext, )); } @@ -64,7 +65,7 @@ public function getName(): string */ public function getValue(): array { - return[ + return [ $this->baseContext, ...$this->otherContexts, ]; diff --git a/src/VerifiableCredentials/VcDataModel/Factories/VcDataModelClaimFactory.php b/src/VerifiableCredentials/VcDataModel/Factories/VcDataModelClaimFactory.php index 372635e..a7b3fe8 100644 --- a/src/VerifiableCredentials/VcDataModel/Factories/VcDataModelClaimFactory.php +++ b/src/VerifiableCredentials/VcDataModel/Factories/VcDataModelClaimFactory.php @@ -6,9 +6,13 @@ use DateTimeImmutable; use SimpleSAML\OpenID\Codebooks\ClaimsEnum; +use SimpleSAML\OpenID\Exceptions\InvalidValueException; use SimpleSAML\OpenID\Exceptions\VcDataModelException; use SimpleSAML\OpenID\Factories\ClaimFactory; use SimpleSAML\OpenID\Helpers; +use SimpleSAML\OpenID\ValueAbstracts\LanguageValueObject; +use SimpleSAML\OpenID\VerifiableCredentials\VcDataModel\Claims\LocalizableStringValue; +use SimpleSAML\OpenID\VerifiableCredentials\VcDataModel\Claims\LocalizableStringValueBag; use SimpleSAML\OpenID\VerifiableCredentials\VcDataModel\Claims\TypeClaimValue; use SimpleSAML\OpenID\VerifiableCredentials\VcDataModel\Claims\VcAtContextClaimValue; use SimpleSAML\OpenID\VerifiableCredentials\VcDataModel\Claims\VcClaimValue; @@ -106,7 +110,7 @@ public function buildTypeClaimValue(mixed $data): TypeClaimValue /** * @param non-empty-array $data */ - public function buildVcCredentialSubjectClaimValue(array $data, ?string $id = null): VcCredentialSubjectClaimValue + public function buildVcCredentialSubjectClaimValue(array $data): VcCredentialSubjectClaimValue { return new VcCredentialSubjectClaimValue($data); } @@ -144,7 +148,7 @@ public function buildVcCredentialSubjectClaimBag( $vcCredentialSubjectClaimValue = $this->buildVcCredentialSubjectClaimValue($vcCredentialSubjectClaimValueData); $vcCredentialSubjectClaimValues = array_map( - fn (array $data): VcCredentialSubjectClaimValue => $this->buildVcCredentialSubjectClaimValue($data), + $this->buildVcCredentialSubjectClaimValue(...), $data, ); @@ -400,4 +404,99 @@ public function buildVcEvidenceClaimBag(array $data): VcEvidenceClaimBag ...$vcEvidenceClaimValues, ); } + + + /** + * Build a LanguageValueObject from language value object data. + * + * @param mixed[] $data + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + */ + public function buildLanguageValueObject(array $data): LanguageValueObject + { + $value = $data[ClaimsEnum::AtValue->value] ?? null; + + if (!is_string($value) || ($value === '' || $value === '0')) { + throw new InvalidValueException('Language value object @value must be a non-empty string.'); + } + + $language = $data[ClaimsEnum::AtLanguage->value] ?? null; + if ($language !== null && (!is_string($language) || ($language === '' || $language === '0'))) { + throw new InvalidValueException('Language value object @language must be a non-empty string.'); + } + + $direction = $data[ClaimsEnum::AtDirection->value] ?? null; + if ($direction !== null && (!in_array($direction, ['ltr', 'rtl'], true))) { + throw new InvalidValueException('Language value object @direction must be "ltr" or "rtl".'); + } + + return new LanguageValueObject($value, $language, $direction); + } + + + /** + * Build a LocalizableStringValueBag from name or description property data. + * + * @param mixed $data String or array of language value objects + * @param non-empty-string $claimName The name of the claim (e.g., 'name' or 'description') + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + */ + public function buildLocalizableStringValueBag(mixed $data, string $claimName): LocalizableStringValueBag + { + if (is_string($data)) { + // Simple string case: create a single LanguageValueObject with just the value + if ($data === '' || $data === '0') { + throw new InvalidValueException( + sprintf('%s must be a non-empty string or language value object.', $claimName), + ); + } + + $languageValueObject = new LanguageValueObject($data); + return new LocalizableStringValueBag(new LocalizableStringValue($languageValueObject, $claimName)); + } + + if (!is_array($data)) { + throw new InvalidValueException( + sprintf('%s must be a string or language value object.', $claimName), + ); + } + + // Check if this is a single language value object (associative array with @value key) + // or an array of language value objects (indexed array or array of objects) + if ($this->helpers->arr()->isAssociative($data) && isset($data[ClaimsEnum::AtValue->value])) { + // Single language value object + $languageValueObject = $this->buildLanguageValueObject($data); + return new LocalizableStringValueBag(new LocalizableStringValue($languageValueObject, $claimName)); + } + + // Array of language value objects + if (!$this->helpers->arr()->isAssociative($data)) { + // Indexed array - each element should be a language value object + $localizableStringValues = []; + foreach ($data as $item) { + if (!is_array($item)) { + throw new InvalidValueException( + sprintf('%s array items must be language value objects.', $claimName), + ); + } + + $languageValueObject = $this->buildLanguageValueObject($item); + $localizableStringValues[] = new LocalizableStringValue($languageValueObject, $claimName); + } + + if ($localizableStringValues === []) { + throw new InvalidValueException( + sprintf('%s array must not be empty.', $claimName), + ); + } + + $firstValue = array_shift($localizableStringValues); + return new LocalizableStringValueBag($firstValue, ...$localizableStringValues); + } + + // Associative array without @value - invalid + throw new InvalidValueException( + sprintf('%s must be a string or language value object.', $claimName), + ); + } } diff --git a/src/VerifiableCredentials/VcDataModel2/Claims/VcCredentialStatusClaimBag.php b/src/VerifiableCredentials/VcDataModel2/Claims/VcCredentialStatusClaimBag.php new file mode 100644 index 0000000..873e10c --- /dev/null +++ b/src/VerifiableCredentials/VcDataModel2/Claims/VcCredentialStatusClaimBag.php @@ -0,0 +1,55 @@ +vcCredentialStatusClaimValueValues = [ + $vcCredentialStatusClaimValue, + ...$vcCredentialStatusClaimValueValues, + ]; + } + + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + return array_map( + fn( + VcCredentialStatusClaimValue $vcCredentialStatusClaimValue, + ): array => $vcCredentialStatusClaimValue->jsonSerialize(), + $this->getValue(), + ); + } + + + public function getName(): string + { + return ClaimsEnum::Credential_Subject->value; + } + + + /** + * @return \SimpleSAML\OpenID\VerifiableCredentials\VcDataModel\Claims\VcCredentialStatusClaimValue[] + */ + public function getValue(): array + { + return $this->vcCredentialStatusClaimValueValues; + } +} diff --git a/src/VerifiableCredentials/VcDataModel2/Claims/VcRefreshServiceClaimBag.php b/src/VerifiableCredentials/VcDataModel2/Claims/VcRefreshServiceClaimBag.php new file mode 100644 index 0000000..3bf7baf --- /dev/null +++ b/src/VerifiableCredentials/VcDataModel2/Claims/VcRefreshServiceClaimBag.php @@ -0,0 +1,54 @@ +vcRefreshServiceClaimValueValues = [ + $vcRefreshServiceClaimValue, + ...$vcRefreshServiceClaimValueValues, + ]; + } + + + /** + * @return mixed[] + */ + public function jsonSerialize(): array + { + return array_map( + fn( + VcRefreshServiceClaimValue $vcRefreshServiceClaimValue, + ): array => $vcRefreshServiceClaimValue->jsonSerialize(), + $this->getValue(), + ); + } + + + public function getName(): string + { + return ClaimsEnum::Refresh_Service->value; + } + + + /** + * @return \SimpleSAML\OpenID\VerifiableCredentials\VcDataModel2\Claims\VcRefreshServiceClaimValue[] + */ + public function getValue(): array + { + return $this->vcRefreshServiceClaimValueValues; + } +} diff --git a/src/VerifiableCredentials/VcDataModel2/Claims/VcRefreshServiceClaimValue.php b/src/VerifiableCredentials/VcDataModel2/Claims/VcRefreshServiceClaimValue.php new file mode 100644 index 0000000..26d5613 --- /dev/null +++ b/src/VerifiableCredentials/VcDataModel2/Claims/VcRefreshServiceClaimValue.php @@ -0,0 +1,16 @@ +value; + } +} diff --git a/src/VerifiableCredentials/VcDataModel2/Factories/VcDataModel2ClaimFactory.php b/src/VerifiableCredentials/VcDataModel2/Factories/VcDataModel2ClaimFactory.php new file mode 100644 index 0000000..01c7107 --- /dev/null +++ b/src/VerifiableCredentials/VcDataModel2/Factories/VcDataModel2ClaimFactory.php @@ -0,0 +1,110 @@ +helpers->arr()->isAssociative($data)) { + return new VcCredentialStatusClaimBag( + $this->buildVcCredentialStatusClaimValue($data), + ); + } + + // We have multiple credential status claims. Wrap them in a + // CredentialStatusClaimBag. + $data = $this->helpers->type()->enforceNonEmptyArrayOfNonEmptyArrays($data); + + $vcCredentialStatusClaims = []; + foreach ($data as $credentialStatusClaimValueData) { + $vcCredentialStatusClaims[] = $this->buildVcCredentialStatusClaimValue($credentialStatusClaimValueData); + } + + $firstCredentialStatusClaim = array_shift($vcCredentialStatusClaims); + + return new VcCredentialStatusClaimBag( + $firstCredentialStatusClaim, + ...$vcCredentialStatusClaims, + ); + } + + + /** + * @param non-empty-array $data + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + */ + public function buildVcRefreshServiceClaimValue2(array $data): VcRefreshServiceClaimValue + { + $type = $data[ClaimsEnum::Type->value] ?? throw new VcDataModelException( + 'No Type claim value available.', + ); + $typeClaimValue = $this->buildTypeClaimValue($type); + + return new VcRefreshServiceClaimValue($typeClaimValue, $data); + } + + + /** + * @param mixed[] $data + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + */ + public function buildVcRefreshServiceClaimBag2(array $data): VcRefreshServiceClaimBag + { + if ($this->helpers->arr()->isAssociative($data)) { + $data = [$data]; + } + + $data = $this->helpers->type()->enforceNonEmptyArrayOfNonEmptyArrays($data); + + $vcRefreshServiceClaimValueData = array_shift($data); + + $vcRefreshServiceClaimValue = $this->buildVcRefreshServiceClaimValue2($vcRefreshServiceClaimValueData); + + $vcRefreshServiceClaimValues = array_map( + $this->buildVcRefreshServiceClaimValue2(...), + $data, + ); + + return new VcRefreshServiceClaimBag( + $vcRefreshServiceClaimValue, + ...$vcRefreshServiceClaimValues, + ); + } +} diff --git a/src/VerifiableCredentials/VcDataModel2/VcSdJwt.php b/src/VerifiableCredentials/VcDataModel2/VcSdJwt.php new file mode 100644 index 0000000..0f7bc9c --- /dev/null +++ b/src/VerifiableCredentials/VcDataModel2/VcSdJwt.php @@ -0,0 +1,575 @@ +getPayload(); + + if (array_key_exists(ClaimsEnum::Vc->value, $payload)) { + throw new VcDataModelException('SD-JWT VC MUST NOT contain a "vc" claim.'); + } + + if (array_key_exists('vp', $payload)) { + throw new VcDataModelException('SD-JWT VC MUST NOT contain a "vp" claim.'); + } + + // Validate validFrom and validUntil claims + $this->getValidFrom(); + $this->getValidUntil(); + } + + + public function getCredentialFormatIdentifier(): CredentialFormatIdentifiersEnum + { + return CredentialFormatIdentifiersEnum::VcSdJwt; + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + */ + public function getVcAtContext(): VcAtContextClaimValue + { + if ($this->vcAtContextClaimValue instanceof VcAtContextClaimValue) { + return $this->vcAtContextClaimValue; + } + + $vcContext = $this->getPayloadClaim(ClaimsEnum::AtContext->value); + + if (!is_array($vcContext)) { + throw new VcDataModelException('Invalid @context claim.'); + } + + if (!is_string($baseContext = array_shift($vcContext))) { + throw new VcDataModelException('Invalid @context claim.'); + } + + return $this->vcAtContextClaimValue = $this->claimFactory->forVcDataModel2()->buildVcAtContextClaimValue( + $baseContext, + $vcContext, + ); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + */ + public function getVcId(): ?string + { + if ($this->vcId === false) { + return null; + } + + $vcId = $this->getPayloadClaim(ClaimsEnum::Id->value); + + if (is_null($vcId)) { + $this->vcId = false; + return null; + } + + return $this->vcId = $this->helpers->type()->enforceUri($vcId); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + */ + public function getVcType(): TypeClaimValue + { + if ($this->vcTypeClaimValue instanceof TypeClaimValue) { + return $this->vcTypeClaimValue; + } + + $vcType = $this->getPayloadClaim(ClaimsEnum::Type->value) ?? $this->getPayloadClaim(ClaimsEnum::AtType->value); + + if (is_null($vcType)) { + throw new VcDataModelException('Invalid Type claim.'); + } + + return $this->vcTypeClaimValue = $this->claimFactory->forVcDataModel2()->buildTypeClaimValue($vcType); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + * @throws \SimpleSAML\OpenID\Exceptions\JwsException + */ + public function getVcCredentialSubject(): VcCredentialSubjectClaimBag + { + if ($this->vcCredentialSubjectClaimBag instanceof VcCredentialSubjectClaimBag) { + return $this->vcCredentialSubjectClaimBag; + } + + $vcCredentialSubject = $this->getPayloadClaim(ClaimsEnum::Credential_Subject->value); + + if ((!is_array($vcCredentialSubject)) || $vcCredentialSubject === []) { + throw new VcDataModelException('Invalid Credential Subject claim.'); + } + + return $this->vcCredentialSubjectClaimBag = $this->claimFactory->forVcDataModel2() + ->buildVcCredentialSubjectClaimBag( + $vcCredentialSubject, + $this->getSubject(), + ); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\JwsException + */ + public function getVcIssuer(): VcIssuerClaimValue + { + if ($this->vcIssuerClaimValue instanceof VcIssuerClaimValue) { + return $this->vcIssuerClaimValue; + } + + $iss = $this->getIssuer(); + $vcIssuer = $this->getPayloadClaim(ClaimsEnum::Issuer->value); + + if (is_null($vcIssuer) && is_string($iss)) { + $vcIssuer = $iss; + } + + if (is_null($vcIssuer)) { + throw new VcDataModelException('Invalid Issuer claim.'); + } + + if (is_string($vcIssuer)) { + return $this->vcIssuerClaimValue = $this->claimFactory->forVcDataModel2()->buildVcIssuerClaimValue( + [ClaimsEnum::Id->value => $vcIssuer], + ); + } + + if (is_array($vcIssuer)) { + return $this->vcIssuerClaimValue = $this->claimFactory->forVcDataModel2()->buildVcIssuerClaimValue( + $vcIssuer, + ); + } + + throw new VcDataModelException('Invalid Issuer claim.'); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\JwsException + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + */ + public function getValidFrom(): DateTimeImmutable + { + if ($this->validFrom instanceof DateTimeImmutable) { + return $this->validFrom; + } + + $validFrom = $this->getPayloadClaim(ClaimsEnum::ValidFrom->value); + + if (is_null($validFrom)) { + $validFrom = $this->getPayloadClaim(ClaimsEnum::Issuance_Date->value); + } + + if (is_null($validFrom)) { + $nbf = $this->getNotBefore() ?? $this->getIssuedAt(); + if (is_int($nbf)) { + try { + return $this->validFrom = $this->helpers->dateTime()->fromTimestamp($nbf); + } catch (Exception $e) { + throw new VcDataModelException('Invalid Not Before or Issued At claim.', $e->getCode(), $e); + } + } + + throw new VcDataModelException('Valid From claim is missing.'); + } + + try { + $validFromStr = $this->helpers->type()->ensureNonEmptyString($validFrom, ClaimsEnum::ValidFrom->value); + $validFrom = $this->helpers->dateTime()->fromXsDateTime($validFromStr); + } catch (Exception $exception) { + throw new VcDataModelException('Invalid Valid From claim.', (int) $exception->getCode(), $exception); + } + + if ($validFrom->getTimestamp() - $this->timestampValidationLeeway->getInSeconds() > time()) { + throw new VcDataModelException('Credential is not valid yet.'); + } + + return $this->validFrom = $validFrom; + } + + + /** + * Alias for getValidFrom to remain fully backwards compatible with + * consumers expecting `getVcIssuanceDate`. + * + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\JwsException + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + */ + public function getVcIssuanceDate(): DateTimeImmutable + { + return $this->getValidFrom(); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\JwsException + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + */ + public function getValidUntil(): ?DateTimeImmutable + { + if ($this->validUntil === false) { + return null; + } + + if ($this->validUntil instanceof DateTimeImmutable) { + return $this->validUntil; + } + + $validUntil = $this->getPayloadClaim(ClaimsEnum::ValidUntil->value); + + if (is_null($validUntil)) { + $validUntil = $this->getPayloadClaim(ClaimsEnum::Expiration_Date->value); + } + + if (is_null($validUntil)) { + $exp = $this->getExpirationTime(); + if (is_int($exp)) { + try { + return $this->validUntil = $this->helpers->dateTime()->fromTimestamp($exp); + } catch (Exception $e) { + throw new VcDataModelException('Invalid Expiration Time claim.', $e->getCode(), $e); + } + } + + $this->validUntil = false; + return null; + } + + try { + $validUntilStr = $this->helpers->type()->ensureNonEmptyString($validUntil, ClaimsEnum::ValidUntil->value); + $validUntil = $this->helpers->dateTime()->fromXsDateTime($validUntilStr); + } catch (Exception $exception) { + throw new VcDataModelException('Invalid Valid Until claim.', (int) $exception->getCode(), $exception); + } + + if ($validUntil->getTimestamp() + $this->timestampValidationLeeway->getInSeconds() < time()) { + throw new VcDataModelException('Credential is expired.'); + } + + return $this->validUntil = $validUntil; + } + + + /** + * Alias for getValidUntil + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\JwsException + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + */ + public function getVcExpirationDate(): ?DateTimeImmutable + { + return $this->getValidUntil(); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + */ + public function getVcProof(): ?VcProofClaimValue + { + if ($this->vcProofClaimValue === false) { + return null; + } + + if ($this->vcProofClaimValue instanceof VcProofClaimValue) { + return $this->vcProofClaimValue; + } + + $vcProof = $this->getPayloadClaim(ClaimsEnum::Proof->value); + + if (is_null($vcProof)) { + $this->vcProofClaimValue = false; + return null; + } + + if (!is_array($vcProof)) { + throw new VcDataModelException('Invalid Proof claim.'); + } + + return $this->vcProofClaimValue = $this->claimFactory->forVcDataModel2()->buildVcProofClaimValue($vcProof); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + * @throws \SimpleSAML\OpenID\Exceptions\JwsException + */ + public function getVcCredentialStatus(): ?VcCredentialStatusClaimBag + { + if ($this->vcCredentialStatusClaimBag === false) { + return null; + } + + if ($this->vcCredentialStatusClaimBag instanceof VcCredentialStatusClaimBag) { + return $this->vcCredentialStatusClaimBag; + } + + $vcCredentialStatus = $this->getPayloadClaim(ClaimsEnum::Credential_Status->value); + + if (is_null($vcCredentialStatus)) { + $this->vcCredentialStatusClaimBag = false; + return null; + } + + if (!is_array($vcCredentialStatus)) { + throw new VcDataModelException('Invalid Credential Status claim.'); + } + + return $this->vcCredentialStatusClaimBag = $this->claimFactory->forVcDataModel2() + ->buildVcCredentialStatusClaimBag($vcCredentialStatus); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + */ + public function getVcCredentialSchema(): ?VcCredentialSchemaClaimBag + { + if ($this->vcCredentialSchemaClaimBag === false) { + return null; + } + + if ($this->vcCredentialSchemaClaimBag instanceof VcCredentialSchemaClaimBag) { + return $this->vcCredentialSchemaClaimBag; + } + + $vcCredentialSchema = $this->getPayloadClaim(ClaimsEnum::Credential_Schema->value); + + if (is_null($vcCredentialSchema)) { + $this->vcCredentialSchemaClaimBag = false; + return null; + } + + if (!is_array($vcCredentialSchema)) { + throw new VcDataModelException('Invalid Credential Schema claim.'); + } + + return $this->vcCredentialSchemaClaimBag = $this->claimFactory->forVcDataModel2() + ->buildVcCredentialSchemaClaimBag($vcCredentialSchema); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + * @throws \SimpleSAML\OpenID\Exceptions\JwsException + */ + public function getVcRefreshService(): ?VcRefreshServiceClaimBag + { + if ($this->vcRefreshServiceClaimBag === false) { + return null; + } + + if ($this->vcRefreshServiceClaimBag instanceof VcRefreshServiceClaimBag) { + return $this->vcRefreshServiceClaimBag; + } + + $vcRefreshService = $this->getPayloadClaim(ClaimsEnum::Refresh_Service->value); + + if (is_null($vcRefreshService)) { + $this->vcRefreshServiceClaimBag = false; + return null; + } + + if (!is_array($vcRefreshService)) { + throw new VcDataModelException('Invalid Refresh Service claim.'); + } + + return $this->vcRefreshServiceClaimBag = $this->claimFactory->forVcDataModel2() + ->buildVcRefreshServiceClaimBag2($vcRefreshService); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + */ + public function getVcTermsOfUse(): ?VcTermsOfUseClaimBag + { + if ($this->vcTermsOfUseClaimBag === false) { + return null; + } + + if ($this->vcTermsOfUseClaimBag instanceof VcTermsOfUseClaimBag) { + return $this->vcTermsOfUseClaimBag; + } + + $vcTermsOfUse = $this->getPayloadClaim(ClaimsEnum::Terms_Of_Use->value); + + if (is_null($vcTermsOfUse)) { + $this->vcTermsOfUseClaimBag = false; + return null; + } + + if (!is_array($vcTermsOfUse)) { + throw new VcDataModelException('Invalid Terms Of Use claim.'); + } + + return $this->vcTermsOfUseClaimBag = $this->claimFactory->forVcDataModel2() + ->buildVcTermsOfUseClaimBag($vcTermsOfUse); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + */ + public function getVcEvidence(): ?VcEvidenceClaimBag + { + if ($this->vcEvidenceClaimBag === false) { + return null; + } + + if ($this->vcEvidenceClaimBag instanceof VcEvidenceClaimBag) { + return $this->vcEvidenceClaimBag; + } + + $vcEvidence = $this->getPayloadClaim(ClaimsEnum::Evidence->value); + + if (is_null($vcEvidence)) { + $this->vcEvidenceClaimBag = false; + return null; + } + + if (!is_array($vcEvidence)) { + throw new VcDataModelException('Invalid Evidence claim.'); + } + + return $this->vcEvidenceClaimBag = $this->claimFactory->forVcDataModel2() + ->buildVcEvidenceClaimBag($vcEvidence); + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + */ + public function getVcName(): null|LocalizableStringValueBag + { + if ($this->vcName === false) { + return null; + } + + if ($this->vcName instanceof LocalizableStringValueBag) { + return $this->vcName; + } + + $vcName = $this->getPayloadClaim(ClaimsEnum::Name->value); + + if (is_null($vcName)) { + $this->vcName = false; + return null; + } + + try { + return $this->vcName = $this->claimFactory->forVcDataModel2() + ->buildLocalizableStringValueBag($vcName, ClaimsEnum::Name->value); + } catch (Exception $exception) { + throw new VcDataModelException('Invalid Name claim.', (int) $exception->getCode(), $exception); + } + } + + + /** + * @throws \SimpleSAML\OpenID\Exceptions\VcDataModelException + * @throws \SimpleSAML\OpenID\Exceptions\InvalidValueException + */ + public function getVcDescription(): null|LocalizableStringValueBag + { + if ($this->vcDescription === false) { + return null; + } + + if ($this->vcDescription instanceof LocalizableStringValueBag) { + return $this->vcDescription; + } + + $vcDescription = $this->getPayloadClaim(ClaimsEnum::Description->value); + + if (is_null($vcDescription)) { + $this->vcDescription = false; + return null; + } + + try { + return $this->vcDescription = $this->claimFactory->forVcDataModel2() + ->buildLocalizableStringValueBag($vcDescription, ClaimsEnum::Description->value); + } catch (Exception $exception) { + throw new VcDataModelException('Invalid Description claim.', (int) $exception->getCode(), $exception); + } + } +} diff --git a/tests/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValueBagTest.php b/tests/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValueBagTest.php new file mode 100644 index 0000000..dedfe8f --- /dev/null +++ b/tests/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValueBagTest.php @@ -0,0 +1,89 @@ +assertCount(2, $bag->getValue()); + $this->assertSame('name', $bag->getName()); + } + + + public function testGetValueByLanguage(): void + { + $value1 = new LocalizableStringValue(new LanguageValueObject('English', 'en'), 'name'); + $value2 = new LocalizableStringValue(new LanguageValueObject('Français', 'fr'), 'name'); + $value3 = new LocalizableStringValue(new LanguageValueObject('العربية', 'ar'), 'name'); + + $bag = new LocalizableStringValueBag($value1, $value2, $value3); + + $frValue = $bag->getValueByLanguage('fr'); + $this->assertInstanceOf( + LocalizableStringValue::class, + $frValue, + ); + $this->assertSame('Français', $frValue->getValue()->getValue()); + + $arValue = $bag->getValueByLanguage('ar'); + $this->assertInstanceOf(LocalizableStringValue::class, $arValue); + $this->assertSame('العربية', $arValue->getValue()->getValue()); + } + + + public function testGetValueByLanguageReturnsNullForMissing(): void + { + $value1 = new LocalizableStringValue(new LanguageValueObject('English', 'en'), 'name'); + $bag = new LocalizableStringValueBag($value1); + + $missing = $bag->getValueByLanguage('de'); + $this->assertNotInstanceOf(LocalizableStringValue::class, $missing); + } + + + public function testGetValueByLanguageNullReturnsFirst(): void + { + $value1 = new LocalizableStringValue(new LanguageValueObject('English', 'en'), 'name'); + $value2 = new LocalizableStringValue(new LanguageValueObject('Français', 'fr'), 'name'); + + $bag = new LocalizableStringValueBag($value1, $value2); + + $first = $bag->getValueByLanguage(); + $this->assertSame($value1, $first); + } + + + public function testJsonSerializeReturnsArrayOfLanguageObjects(): void + { + $value1 = new LocalizableStringValue(new LanguageValueObject('English', 'en'), 'name'); + $value2 = new LocalizableStringValue(new LanguageValueObject('Français', 'fr'), 'name'); + + $bag = new LocalizableStringValueBag($value1, $value2); + $serialized = $bag->jsonSerialize(); + + $this->assertIsArray($serialized); + $this->assertCount(2, $serialized); + $this->assertSame('English', $serialized[0]['@value']); + $this->assertSame('en', $serialized[0]['@language']); + $this->assertSame('Français', $serialized[1]['@value']); + $this->assertSame('fr', $serialized[1]['@language']); + } +} diff --git a/tests/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValueTest.php b/tests/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValueTest.php new file mode 100644 index 0000000..ec1bee0 --- /dev/null +++ b/tests/src/VerifiableCredentials/VcDataModel/Claims/LocalizableStringValueTest.php @@ -0,0 +1,41 @@ +assertSame($languageValueObject, $localizableString->getValue()); + $this->assertSame('name', $localizableString->getName()); + } + + + public function testJsonSerializeReturnsLanguageValueObjectData(): void + { + $languageValueObject = new LanguageValueObject('Test Value', 'en', 'ltr'); + $localizableString = new LocalizableStringValue($languageValueObject, 'description'); + + $serialized = $localizableString->jsonSerialize(); + + $this->assertArrayHasKey('@value', $serialized); + $this->assertArrayHasKey('@language', $serialized); + $this->assertArrayHasKey('@direction', $serialized); + $this->assertSame('Test Value', $serialized['@value']); + $this->assertSame('en', $serialized['@language']); + $this->assertSame('ltr', $serialized['@direction']); + } +} diff --git a/tests/src/VerifiableCredentials/VcDataModel/Claims/VcAtContextClaimValueTest.php b/tests/src/VerifiableCredentials/VcDataModel/Claims/VcAtContextClaimValueTest.php index 640fe7c..d5bf95d 100644 --- a/tests/src/VerifiableCredentials/VcDataModel/Claims/VcAtContextClaimValueTest.php +++ b/tests/src/VerifiableCredentials/VcDataModel/Claims/VcAtContextClaimValueTest.php @@ -14,17 +14,21 @@ final class VcAtContextClaimValueTest extends TestCase { protected string $baseContext = AtContextsEnum::W3Org2018CredentialsV1->value; + protected AtContextsEnum $expectedBaseContext = AtContextsEnum::W3Org2018CredentialsV1; + protected array $otherContexts = []; protected function sut( ?string $baseContext = null, ?array $otherContexts = null, + ?AtContextsEnum $expectedBaseContext = null, ): VcAtContextClaimValue { $baseContext ??= $this->baseContext; $otherContexts ??= $this->otherContexts; + $expectedBaseContext ??= $this->expectedBaseContext; - return new VcAtContextClaimValue($baseContext, $otherContexts); + return new VcAtContextClaimValue($baseContext, $otherContexts, $expectedBaseContext); } diff --git a/tests/src/VerifiableCredentials/VcDataModel/Factories/VcDataModelClaimFactoryLocalizableTest.php b/tests/src/VerifiableCredentials/VcDataModel/Factories/VcDataModelClaimFactoryLocalizableTest.php new file mode 100644 index 0000000..ecd36f3 --- /dev/null +++ b/tests/src/VerifiableCredentials/VcDataModel/Factories/VcDataModelClaimFactoryLocalizableTest.php @@ -0,0 +1,158 @@ +factory = new VcDataModelClaimFactory( + new Helpers(), + new ClaimFactory(new Helpers()), + ); + } + + + public function testBuildLanguageValueObjectFromSimpleArray(): void + { + $data = ['@value' => 'Test', '@language' => 'en']; + $lvo = $this->factory->buildLanguageValueObject($data); + + $this->assertSame('Test', $lvo->getValue()); + $this->assertSame('en', $lvo->getLanguage()); + $this->assertNull($lvo->getDirection()); + } + + + public function testBuildLanguageValueObjectWithDirection(): void + { + $data = ['@value' => 'مثال', '@language' => 'ar', '@direction' => 'rtl']; + $lvo = $this->factory->buildLanguageValueObject($data); + + $this->assertSame('مثال', $lvo->getValue()); + $this->assertSame('ar', $lvo->getLanguage()); + $this->assertSame('rtl', $lvo->getDirection()); + } + + + public function testBuildLanguageValueObjectThrowsOnMissingValue(): void + { + $data = ['@language' => 'en']; + $this->expectException(InvalidValueException::class); + $this->factory->buildLanguageValueObject($data); + } + + + public function testBuildLanguageValueObjectThrowsOnEmptyValue(): void + { + $data = ['@value' => '', '@language' => 'en']; + $this->expectException(InvalidValueException::class); + $this->factory->buildLanguageValueObject($data); + } + + + public function testBuildLanguageValueObjectThrowsOnInvalidDirection(): void + { + $data = ['@value' => 'Test', '@direction' => 'invalid']; + $this->expectException(InvalidValueException::class); + $this->factory->buildLanguageValueObject($data); + } + + + public function testBuildLocalizableStringValueFromString(): void + { + $result = $this->factory->buildLocalizableStringValueBag('Test String', 'name'); + + $this->assertInstanceOf(LocalizableStringValueBag::class, $result); + $this->assertSame('Test String', $result->getFirstValueOrFail()->getValue()->getValue()); + $this->assertNull($result->getFirstValueOrFail()->getValue()->getLanguage()); + } + + + public function testBuildLocalizableStringValueFromSingleLanguageObject(): void + { + $data = ['@value' => 'Test', '@language' => 'en']; + $result = $this->factory->buildLocalizableStringValueBag($data, 'description'); + + $this->assertInstanceOf(LocalizableStringValueBag::class, $result); + $this->assertSame('Test', $result->getFirstValueOrFail()->getValue()->getValue()); + $this->assertSame('en', $result->getFirstValueOrFail()->getValue()->getLanguage()); + } + + + public function testBuildLocalizableStringValueFromMultipleLanguageObjects(): void + { + $data = [ + ['@value' => 'English', '@language' => 'en'], + ['@value' => 'Français', '@language' => 'fr'], + ['@value' => 'العربية', '@language' => 'ar', '@direction' => 'rtl'], + ]; + $result = $this->factory->buildLocalizableStringValueBag($data, 'name'); + + $this->assertInstanceOf(LocalizableStringValueBag::class, $result); + + $values = $result->getValue(); + $this->assertCount(3, $values); + $this->assertSame('English', $values[0]->getValue()->getValue()); + $this->assertSame('en', $values[0]->getValue()->getLanguage()); + $this->assertSame('Français', $values[1]->getValue()->getValue()); + $this->assertSame('العربية', $values[2]->getValue()->getValue()); + $this->assertSame('rtl', $values[2]->getValue()->getDirection()); + } + + + public function testBuildLocalizableStringValueThrowsOnEmptyString(): void + { + $this->expectException(InvalidValueException::class); + $this->factory->buildLocalizableStringValueBag('', 'name'); + } + + + public function testBuildLocalizableStringValueThrowsOnInvalidType(): void + { + $this->expectException(InvalidValueException::class); + $this->factory->buildLocalizableStringValueBag(12345, 'name'); + } + + + public function testBuildLocalizableStringValueThrowsOnInvalidArrayItem(): void + { + $data = [ + ['@value' => 'English', '@language' => 'en'], + 'invalid string in array', + ]; + $this->expectException(InvalidValueException::class); + $this->factory->buildLocalizableStringValueBag($data, 'name'); + } + + + public function testBuildLocalizableStringValueThrowsOnEmptyArray(): void + { + $this->expectException(InvalidValueException::class); + $this->factory->buildLocalizableStringValueBag([], 'name'); + } +} diff --git a/tests/src/VerifiableCredentials/VcDataModel2/VcSdJwtTest.php b/tests/src/VerifiableCredentials/VcDataModel2/VcSdJwtTest.php new file mode 100644 index 0000000..2ab44ac --- /dev/null +++ b/tests/src/VerifiableCredentials/VcDataModel2/VcSdJwtTest.php @@ -0,0 +1,220 @@ + [ + "https://www.w3.org/ns/credentials/v2", + "https://www.w3.org/2018/credentials/examples/v1", + ], + "id" => "https://credential-issuer.example.com/credentials/3732", + "type" => [ + "VerifiableCredential", + "UniversityDegreeCredential", + ], + "issuer" => "https://credential-issuer.example.com", + "validFrom" => "2025-01-01T00:00:00Z", + "validUntil" => "2026-01-01T00:00:00Z", + "credentialSubject" => [ + "id" => "did:example:123", + "degree" => [ + "type" => "BachelorDegree", + "name" => "Bachelor of Science and Arts", + ], + ], + "iss" => "https://credential-issuer.example.com", + "nbf" => 1735689600, + "exp" => 1767225600, + "jti" => "https://credential-issuer.example.com/credentials/3732", + "sub" => "did:example:123", + ]; + + protected array $validPayload; + + protected array $sampleHeader = [ + 'alg' => 'ES256', + 'typ' => 'vc+sd-jwt', + 'kid' => 'F4VFObNusj3PHmrHxpqh4GNiuFHlfh-2s6xMJ95fLYA', + ]; + + + protected function setUp(): void + { + $this->signatureMock = $this->createMock(Signature::class); + + $jwsMock = $this->createMock(JWS::class); + $jwsMock->method('getPayload')->willReturn('json-payload-string'); + $jwsMock->method('getSignature')->willReturn($this->signatureMock); + + $this->jwsDecoratorMock = $this->createMock(JwsDecorator::class); + $this->jwsDecoratorMock->method('jws')->willReturn($jwsMock); + + $this->helpersMock = $this->createMock(Helpers::class); + $this->jsonHelperMock = $this->createMock(Helpers\Json::class); + $this->helpersMock->method('json')->willReturn($this->jsonHelperMock); + $typeHelperMock = $this->createMock(Helpers\Type::class); + $this->helpersMock->method('type')->willReturn($typeHelperMock); + $arrHelperMock = $this->createMock(Helpers\Arr::class); + $this->helpersMock->method('arr')->willReturn($arrHelperMock); + $dateTimeHelperMock = $this->createMock(Helpers\DateTime::class); + $this->helpersMock->method('dateTime')->willReturn($dateTimeHelperMock); + + $realDateTimeHelper = new Helpers\DateTime(); + $dateTimeHelperMock->method('fromXsDateTime') + ->willReturnCallback(fn(string $input): \DateTimeImmutable => $realDateTimeHelper->fromXsDateTime($input)); + $dateTimeHelperMock->method('fromTimestamp') + ->willReturnCallback( + fn(int $timestamp): \DateTimeImmutable => $realDateTimeHelper->fromTimestamp($timestamp), + ); + + $typeHelperMock->method('ensureNonEmptyString')->willReturnArgument(0); + $typeHelperMock->method('ensureInt')->willReturnArgument(0); + $typeHelperMock->method('ensureArray')->willReturnArgument(0); + $typeHelperMock->method('enforceUri')->willReturnArgument(0); + $typeHelperMock->method('enforceNonEmptyArrayOfNonEmptyArrays')->willReturnArgument(0); + + $arrHelperMock->method('getNestedValue') + ->willReturnCallback( + fn(array $array, string $key, string $key2): mixed => $array[$key][$key2] ?? null, + ); + + $this->claimFactoryMock = $this->createStub(ClaimFactory::class); + + $this->validPayload = $this->expiredPayload; + + $this->validPayload['exp'] = time() + 3600; + $this->validPayload['validUntil'] = (new \DateTimeImmutable()) + ->modify('+1 hour') + ->format(\DateTimeInterface::ATOM); + } + + + protected function sut(): VcSdJwt + { + $leewayMock = $this->createMock(\SimpleSAML\OpenID\Decorators\DateIntervalDecorator::class); + $leewayMock->method('getInSeconds')->willReturn(0); + + return new VcSdJwt( + $this->jwsDecoratorMock, + $this->createStub(\SimpleSAML\OpenID\Jws\JwsVerifierDecorator::class), + $this->createStub(\SimpleSAML\OpenID\Jwks\Factories\JwksDecoratorFactory::class), + $this->createStub(\SimpleSAML\OpenID\Serializers\JwsSerializerManagerDecorator::class), + $leewayMock, + $this->helpersMock, + $this->claimFactoryMock, + ); + } + + + public function testCanCreateInstance(): void + { + $this->signatureMock->method('getProtectedHeader')->willReturn($this->sampleHeader); + $this->jsonHelperMock->method('decode')->willReturn($this->validPayload); + + $this->assertInstanceOf(VcSdJwt::class, $this->sut()); + } + + + public function testGetPropertiesReturnTypes(): void + { + $this->signatureMock->method('getProtectedHeader')->willReturn($this->sampleHeader); + $this->jsonHelperMock->method('decode')->willReturn($this->validPayload); + + $sut = $this->sut(); + + $vcDataModelClaimFactoryMock = $this->createStub(VcDataModel2ClaimFactory::class); + $vcDataModelClaimFactoryMock->method('buildVcAtContextClaimValue') + ->willReturn($this->createStub(VcAtContextClaimValue::class)); + $vcDataModelClaimFactoryMock->method('buildTypeClaimValue') + ->willReturn($this->createStub(TypeClaimValue::class)); + $vcDataModelClaimFactoryMock->method('buildVcCredentialSubjectClaimBag') + ->willReturn($this->createStub(VcCredentialSubjectClaimBag::class)); + $vcDataModelClaimFactoryMock->method('buildVcIssuerClaimValue') + ->willReturn($this->createStub(VcIssuerClaimValue::class)); + + $this->claimFactoryMock->method('forVcDataModel2')->willReturn($vcDataModelClaimFactoryMock); + + $this->assertInstanceOf(VcAtContextClaimValue::class, $sut->getVcAtContext()); + $this->assertIsString($sut->getVcId()); + $this->assertInstanceOf(TypeClaimValue::class, $sut->getVcType()); + $this->assertInstanceOf(VcCredentialSubjectClaimBag::class, $sut->getVcCredentialSubject()); + $this->assertInstanceOf(VcIssuerClaimValue::class, $sut->getVcIssuer()); + $this->assertInstanceOf(DateTimeImmutable::class, $sut->getValidFrom()); + $this->assertInstanceOf(DateTimeImmutable::class, $sut->getValidUntil()); + + // Assert aliases + $this->assertInstanceOf(DateTimeImmutable::class, $sut->getVcIssuanceDate()); + $this->assertInstanceOf(DateTimeImmutable::class, $sut->getVcExpirationDate()); + + $this->assertSame(CredentialFormatIdentifiersEnum::VcSdJwt, $sut->getCredentialFormatIdentifier()); + } + + + public function testThrowsIfVcClaimExists(): void + { + $this->expectException(VcDataModelException::class); + $this->expectExceptionMessage('MUST NOT contain a "vc" claim'); + + $payload = $this->validPayload; + $payload['vc'] = ['test']; + + $this->signatureMock->method('getProtectedHeader')->willReturn($this->sampleHeader); + $this->jsonHelperMock->method('decode')->willReturn($payload); + + $this->sut(); + } + + + public function testThrowsIfVpClaimExists(): void + { + $this->expectException(VcDataModelException::class); + $this->expectExceptionMessage('MUST NOT contain a "vp" claim'); + + $payload = $this->validPayload; + $payload['vp'] = ['test']; + + $this->signatureMock->method('getProtectedHeader')->willReturn($this->sampleHeader); + $this->jsonHelperMock->method('decode')->willReturn($payload); + + $this->sut(); + } +}