# JSON-LD 入門 — Web の意味を機械に渡す構造化データ

> JSON-LD とは何か（Linked Data と RDF グラフ、@context / @id / @type の役割）を具体例で解説し、Web でどう使われているか——検索のリッチリザルト、Microdata / RDFa との比較、@id で結ぶ Site-wide / Page-level 設計、よくあるエラーと検証ツール——までを一気に押さえます。最後に、このサイト自身が JSON-LD をどう実装しているかを実例として開きます。

- 出典: SUZ-LAB（解説トピック）
- URL: https://suz-lab.co.jp/topics/json-ld-structured-data
- 公開: 2026-07-06
- 更新: 2026-07-06
- タグ: #JSON-LD #構造化データ #SEO #Schema.org #Next.js #Web

---


Web には人間向けの見た目（HTML＋CSS）と、機械向けの意味（構造化データ）の 2 つの層がある。
後者を担う事実上の標準が **JSON-LD**（JavaScript Object Notation for Linked Data）だ。
検索エンジンのリッチリザルト、ナレッジグラフ、SNS のカード、AI エージェントのデータ取得——
どれも「そのページが何について書かれているか」を機械可読で受け取れることが前提になっている。

この記事は、JSON-LD の**仕組み**（何を表しているのか）と、Web での**使われ方**
（どこに置き、何を得るのか）を具体例で解説する。最後に、**このサイト自身**が JSON-LD を
どう出しているかを開き、机上の理論ではなく動いている実装として見せる。

## JSON-LD とは — 「JSON のまま」意味を足す

セマンティック Web／Linked Data の狙いは、バラバラのサイトに散る情報を、標準化された
識別子でつなぎ、機械がリンクをたどって新しいデータを発見できるようにすることだ。
初期の XML ベースの記法は表現力は高かったが、開発者には重すぎて普及しなかった。
そこで **今日の Web で当たり前になった JSON の書き味そのままに、高度な意味づけを載せられる**
シリアライズ形式として設計されたのが JSON-LD で、2020 年 7 月に W3C 勧告「JSON-LD 1.1」が出ている。

JSON-LD が表すのは **方向を持つラベル付きの有向グラフ**だ。

- **ノード**（主語・目的語）＝ リソース（組織・記事・人など）
- **エッジ**（述語）＝ リソース間の関係（`publisher`、`author` など）

主語・述語・目的語をすべて **IRI**（国際化された URI）でラベル付けするので、
名前の衝突なく、分散した Web スケールで情報を結合できる。JSON-LD ドキュメントは、この
グラフを木構造の JSON にマッピングしたものだ、と捉えるとよい。

### 最小の例

```json
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "@id": "https://suz-lab.co.jp/topics/json-ld-structured-data",
  "headline": "JSON-LD 入門",
  "author": { "@type": "Organization", "name": "SUZ-LAB" }
}
</script>
```

`@` で始まる **キーワード**が意味の骨格を決める。主要なものは次の通り。

| キーワード | 役割 |
| --- | --- |
| `@context` | 各キーを Schema.org 等の語彙（IRI）へ紐付ける「辞書」。外部ファイルも参照できる |
| `@type` | オブジェクトの型（`Organization`・`TechArticle` など）や値のデータ型 |
| `@id` | そのノードを一意に識別する URI。**別ブロックからの参照キーにもなる**（後述） |
| `@graph` | 複数の独立ノードをまとめる入れ物。名前付きグラフの識別にも使う |
| `@value` / `@language` | 値に言語やデータ型を紐付ける「値オブジェクト」を作る（BCP 47 準拠） |
| `@vocab` / `@base` | 既定の語彙 URI と、相対 URI を解決する基準 IRI |

`@type` の `type`、`@id` の `id` のように、`@context` でエイリアスを張ればアットマーク無しでも書ける。

<Details summary="データモデリングの勘所 — 配列の順序と数値精度のワナ">

W3C のベストプラクティスが繰り返し強調するのは「開発者フレンドリーな JSON」であること。
その上で、RDF グラフに変換される都合から来る 2 つの落とし穴に注意する。

- **配列は既定で「順不同（Set）」**。JSON の配列は順序を持つが、RDF は順不同のトリプル集合
  として扱うため、変換時に順序が消える。順序が意味を持つなら `@context` で
  `"@container": "@list"` を宣言して `rdf:List` だと解釈させる。
- **数値の精度欠損**。多くの言語は数値を IEEE 754 倍精度で扱うので、大きな整数や精密な小数は
  往復で誤差が出る。金融・学術など厳密な値は、あえて文字列で包み `@type` で
  `xsd:decimal` / `xsd:integer` へ**型強制（Type Coercion）**するのが定石。
- **文字列ではなく「実体」で書く**。プロパティ値に名前の文字列を置くのではなく、`@type` と
  `@id` を持つオブジェクトにして実体化する。双方向・循環参照は、一方はネスト・逆方向は `@id`
  参照だけ、にして無限ループを避ける。

</Details>

## Web での使われ方① — 3 つの構造化データ方式

HTML に構造化データを埋める規格は歴史的に 3 つある。**JSON-LD が支配的**な理由は設計思想にある。

| 観点 | JSON-LD | Microdata | RDFa |
| --- | --- | --- | --- |
| 書き方 | `<script>` に独立した JSON ブロック | HTML タグに `itemprop` 属性 | HTML タグに `property` 属性 |
| 表示（DOM）との結合 | **非結合**。デザイン変更で壊れない | 強結合。マークアップ変更で壊れやすい | 強結合。冗長で壊れやすい |
| Google の推奨 | **最優先で推奨** | サポートするが新規は非推奨寄り | 事実上レガシー |
| 利用サイト内シェア（WDC 2023） | **66%** | 48% | 5% |
| 平均トリプル数/ページ | **55** | 36 | — |

決定的なのは **関心の分離**だ。JSON-LD は `<script type="application/ld+json">` に意味を
カプセル化するので、`<head>` でも `<body>` でも好きな場所に置け、見た目に 1px も干渉しない。
Microdata / RDFa は「ビュー」と「データ」を同じタグに縛るため、フロントを少し直しただけで
構造化データが巻き込まれて壊れる。WebDataCommons の大規模調査（約 34 億ページ）でも、
JSON-LD だけがトリプル密度を伸ばし続けており、単なる SEO テクニックを超えて
**サイト間をつなぐデータ基盤**として選ばれていることが読み取れる。

## Web での使われ方② — 検索のリッチリザルトと @id 設計

検索エンジンにコンテンツの意味（価格・在庫・著者・パンくずなど）を明示的に渡すと、
星評価・画像カード・FAQ などの **リッチリザルト**の対象になる。ここで効くのが `@id` を使った
**Site-wide / Page-level の分離**だ。

- **Site-wide（全ページ共通）**: `WebSite` / `Organization` を、正規 URL にアンカーを足した
  不変の `@id`（例 `https://example.com/#organization`）で一度だけ定義する。
- **Page-level（各ページ固有）**: `WebPage` / `Article` / `Product` など、その URL 固有の情報だけを
  書き、組織などは**再宣言せず** `{ "@id": "https://example.com/#organization" }` で**参照**する。

これで「同じ組織」がグラフ上の 1 ノードに束ねられ、全ページの記事が同じ発行元を指す。
成立条件は厳格で、**`@id` / `url` は canonical URL と 1 文字単位で一致**していなければならない
（www の有無・HTTPS・末尾スラッシュ）。ズレると内部でリレーションが切れて孤立する。

> このサイトは公開時に、canonical を「www 無し・HTTPS・末尾スラッシュ無し」の 1 本に正規化する
> 判断をしている。その経緯は [器を世に出すまで（Vercel とドメイン接続）](/logs/going-live-vercel-and-domain)
> に残した。JSON-LD の `@id` 一致は、この canonical 規律の上に乗っている。

<Details summary="よくある 10 のエラーと検証ツール">

構造化データは放置すると「不整合なパッチワーク」に劣化する。代表的な失敗:

- **Organization の重複宣言**（全ページでフル宣言）→ Site-wide で 1 回、以後は `@id` 参照に。
- **末尾スラッシュ／www の不一致** → canonical の文字列をそのままコピーして出す。
- **ゴースト FAQ**（HTML に無い Q&A を JSON-LD にだけ書く）→ スパム扱い。表示と一致させる。
- **末尾カンマ・スマートクォート** → 厳格な JSON パースエラーで丸ごと無視される。
- **相対 URL の画像** → `https://` から始まる絶対 URL を強制する。

検証は 3 層で行う。**構文**（JSON として妥当か）→ **語彙**（Schema.org の型・プロパティが正しいか）
→ **ポリシー**（Google が各機能に課す必須フィールドを満たすか）。ツールは用途で使い分ける。

- **Rich Results Test**（Google）… 検索機能への適合。ただし JSON-LD 内の `//` コメントを
  独自に無視して「合格」にしてしまう——標準 JSON（RFC 8259）ではコメントは構文違反なので、
  本番の標準パーサーではパースエラーになって弾かれる。**本番出力はコメント無しの純粋な JSON にする。**
- **Schema Markup Validator**（Schema.org）… 800 以上の全クラスを中立に語彙検証。
- **JSON-LD Playground**（W3C）… 展開／圧縮／フレーミングなど API 変換の挙動を観察。

</Details>

## このサイト自身の JSON-LD

ここまでの理論は、このサイト（`apps/web`）がそのまま実装している。抽象論ではなく
**動いている実例**として見てほしい——JSON-LD の記事が、JSON-LD で記述されている。
自分の主張を、自分で使って証明する——この姿勢は
[ドッグフーディング](/topics/dogfooding)の情報設計版だ。

**1. Site-wide を `@id` で 1 ノードに束ねる。** ルートレイアウトが全ページ共通で `Organization` と
`WebSite` を出し、`#organization` / `#website` の `@id` で相互参照する。

```ts
// src/lib/structured-data.ts（要約）
export function siteStructuredData() {
  const orgId = `${SITE.url}/#organization`;
  return [
    { "@type": "Organization", "@id": orgId, name: SITE.name, url: SITE.url, /* … */ },
    { "@type": "WebSite", "@id": `${SITE.url}/#website`, publisher: { "@id": orgId } },
  ];
}
```

**2. Page-level は再宣言せず参照する。** 各実験ログは `BlogPosting`、この解説記事は `TechArticle`
として出し、発行元は組織を**再宣言せず** `publisher: { "@id": ".../#organization" }` で指す。
まさに本文で説いた Site-wide / Page-level の分離だ。

```ts
// この記事（TechArticle）の構造化データ（要約）
{
  "@type": "TechArticle",
  headline: topic.title,
  isPartOf: { "@id": `${SITE.url}/#website` },       // サイトに属する
  publisher: { "@id": `${SITE.url}/#organization` }, // 組織は @id 参照で 1 ノードに
}
```

**3. 値の出所は 1 か所、JSON-LD は「写すだけ」。** URL・組織名・SNS リンクといった値は
`content/site-config.ts` を唯一の出所にし、`structured-data.ts` は Schema.org の形に写して
URL を絶対化するだけ——文言をコードに直書きしない。これはこのサイト全体の設計方針でもある。

**4. 型はコンテンツの性質で選ぶ。** 制作物ショーケースの画像ギャラリーは `ImageGallery` として
出している（[/showcase](/showcase)）。時系列の記録は `BlogPosting`、常設の技術解説は
`TechArticle`、と型を描き分けることで、機械にも「これは記事、これは作品集」と伝わる。

`@id` を「唯一のつなぎ目」にしてリンクの二重管理を消す発想は、このサイトが
[VMOST → Roadmap → Log を一本の線でつないだ](/logs/connecting-vmost-roadmap-logs) ときと同じだ。
人手のリンクは必ずドリフトする——**安定した ID を 1 つ決めて機械的に突き合わせる**、という
情報設計の原則が、ページ内の導線でも、検索エンジンへ渡すグラフでも一貫して効いている。

## 1.1 の進化と、その先

JSON-LD 1.1 は複雑な API 設計の制約を大きく外した。**スコープ適用コンテキスト**（親子で同じ
プロパティ名を別語彙に安全にマッピング）、**Protected Term**（重要な定義を後続の上書きから保護）、
**`@nest` / `@included`**（意味を持たない中間ラッパーを飛ばす）、そして
**フレーミング**（乱雑なグラフを、クライアントが要求する決定論的な木へ整形する）などだ。

その先では、セキュリティ強化の **JSON-LD 1.2**、人が書きやすい **YAML-LD**、IoT 向けの
コンパクトバイナリ **CBOR-LD** といった周辺エコシステムが動いている。とはいえ Web で 95% の
場面は、この記事で押さえた **`@context` / `@type` / `@id` と Site-wide/Page-level の `@id` 連結**で足りる。

---

**まとめ。** JSON-LD は「JSON のまま意味を足す」ことで、セマンティック Web を実務に降ろした。
Web では主に検索の構造化データとして使われ、勝ち筋は **表示から独立した `<script>` ブロック**と
**`@id` による Site-wide/Page-level の連結**にある。canonical を 1 本に正規化し、値の出所を
1 か所にまとめ、型をコンテンツの性質で選ぶ——このサイトはその通りに実装している。
考え方の全体像は [VMOST とは](/topics/vmost)、実装の記録は [実験ログ](/logs) にある。

