JSON-LD: Linked Data for JSON
JSON-LD は JSON にセマンティクス(意味)を付与するための W3C 標準です。Verifiable Credentials の W3C Data Model で使われています。
前提知識
JSON-LD は RDF(Resource Description Framework) の JSON 表現です。RDF の基本概念(トリプル、URI、グラフ)を理解していると、より深く理解できます。
JSON-LD とは
JSON-LD(JSON for Linking Data)は、JSON データに「意味」を持たせるための仕様です。
JSON-LD の位置づけ:
┌─────────────────────────────────────────────────────────────┐
│ │
│ JSON JSON-LD │
│ │
│ {"name": "John"} {"@context": "...", │
│ "name": "John"} │
│ │
│ 意味が不明確 意味が定義されている │
│ 「name」って何? 「foaf:name」= 人名 │
│ │
└─────────────────────────────────────────────────────────────┘
なぜ意味の定義が必要か
問題: 同じプロパティ名でも意味が違う
システム A: { "name": "John" } ← 人の名前
システム B: { "name": "Acme Corp" } ← 会社名
システム C: { "name": "Tokyo" } ← 地名
相互運用するとき:
「name」をどう解釈すべき?
人名?会社名?地名?
JSON-LD の解決策:
各プロパティに一意の識別子(URI)を割り当てる
{ "@context": { "name": "http://schema.org/name" },
"name": "John" }
→ schema.org/name = 「モノの名前」という明確な定義
@context の役割
基本的な構文
{
"@context": "https://schema.org/",
"name": "John",
"jobTitle": "Professor"
}
@context が行うこと:
1. 短い名前 → 完全な URI へのマッピング
"name" → "https://schema.org/name"
"jobTitle" → "https://schema.org/jobTitle"
2. URI があることで、その意味を調べられる
https://schema.org/name を見れば
「モノの名前を表すプロパティ」と定義されている
複数のコンテキスト
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://example.gov/credentials/license"
],
"type": ["VerifiableCredential", "DriversLicense"],
"issuer": "did:example:gov",
"licenseNumber": "DL-12345"
}
複数コンテキストのマージ:
最初のコンテキスト:
type → VC標準の定義
issuer → VC標準の定義
2番目のコンテキスト:
licenseNumber → 運転免許固有の定義
→ 標準語彙 + ドメイン固有語彙の組み合わせ
Verifiable Credentials での JSON-LD
VC の @context
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://example.gov/credentials/identity"
],
"type": ["VerifiableCredential", "IdentityCredential"],
"issuer": "did:example:gov",
"credentialSubject": {
"id": "did:example:holder",
"name": "山田太郎",
"birthDate": "1990-01-15"
}
}
VC での @context の意味:
┌─────────────────────────────────────────────────────────────┐
│ │
│ "https://www.w3.org/ns/credentials/v2" │
│ ├── "type" の意味を定義 │
│ ├── "issuer" の意味を定義 │
│ ├── "credentialSubject" の意味を定義 │
│ └── "proof" の意味を定義 │
│ │
│ "https://example.gov/credentials/identity" │
│ ├── "name" の意味を定義 │
│ └── "birthDate" の意味を定義 │
│ │
└─────────────────────────────────────────────────────────────┘
なぜ VC は JSON-LD を採用したか
理由 1: 相互運用性
異なる発行者が発行した VC でも
同じ @context を使えば同じ意味を持つ
発行者 A: { "credentialSubject": { "birthDate": "1990-01-15" } }
発行者 B: { "credentialSubject": { "birthDate": "1985-05-20" } }
→ 両方とも「生年月日」として処理できる
理由 2: 拡張性
標準にない属性を追加する場合
独自のコンテキストを作成すればよい
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://mycompany.example/vocab" ← 独自定義
]
理由 3: 署名の安定性
JSON-LD の正規化により
同じ意味のデータは同じバイト列になる
→ 署名が安定する
JSON-LD の主要キーワード
@id(識別子)
{
"@context": "https://schema.org/",
"@id": "https://example.com/person/12345",
"name": "John"
}
@id の役割:
このデータを一意に識別する URI
「https://example.com/person/12345 という人物は
name が John である」
VC では issuer や credentialSubject.id がこれに相当:
"issuer": "did:example:gov"
"credentialSubject": { "id": "did:example:holder" }
@type(型)
{
"@context": "https://schema.org/",
"@type": "Person",
"name": "John"
}
@type の役割:
このデータが「何か」を示す
VC では type 配列:
"type": ["VerifiableCredential", "UniversityDegreeCredential"]
注: JSON-LD では @type、VC では短縮形の type を使用
@graph(グラフ)
{
"@context": "https://schema.org/",
"@graph": [
{ "@id": "person:1", "@type": "Person", "name": "John" },
{ "@id": "person:2", "@type": "Person", "name": "Jane" }
]
}
@graph の役割:
複数のノード(データ)を含むグラフ
VC ではあまり使わないが
Verifiable Presentation で複数 VC を含む場合に類似:
"verifiableCredential": [
{ /* VC 1 */ },
{ /* VC 2 */ }
]
JSON-LD の正規化
なぜ正規化が必要か
問題: 同じ意味でも JSON の書き方は様々
{ "name": "John", "age": 30 }
{ "age": 30, "name": "John" }
{"name":"John","age":30}
→ 意味は同じだがバイト列が違う
→ 署名すると異なるハッシュになる
解決: 正規化
JSON-LD を RDF に変換し、一意の形式に正規化
→ 同じ意味 = 同じバイト列
→ 署名が安定
正規化ア ルゴリズム
主な正規化アルゴリズム:
┌─────────────────────────────────────────────────────────────┐
│ │
│ URDNA2015 │
│ Universal RDF Dataset Normalization Algorithm 2015 │
│ W3C 標準、VC で広く使用 │
│ │
│ JCS (JSON Canonicalization Scheme) │
│ RFC 8785 │
│ JSON-LD 以外でも使える │
│ │
└─────────────────────────────────────────────────────────────┘
VC Data Integrity で使われる cryptosuite:
eddsa-rdfc-2022 → RDFC-1.0 正規化 + EdDSA 署名
ecdsa-rdfc-2019 → RDFC-1.0 正規化 + ECDSA 署名
正規化の例
入力(順序が違う2つの JSON):
{"name": "John", "age": 30}
{"age": 30, "name": "John"}
正規化後(同じ出力):
<_:b0> <http://schema.org/age> "30"^^<xsd:integer> .
<_:b0> <http://schema.org/name> "John" .
→ 同じバイト列 → 同じハッシュ → 署名が一致