JSON-LD 入門 — Web の意味を機械に渡す構造化データ
JSON-LD とは何か(Linked Data と RDF グラフ、@context / @id / @type の役割)を具体例で解説し、Web でどう使われているか——検索のリッチリザルト、Microdata / RDFa との比較、@id で結ぶ Site-wide / Page-level 設計、よくあるエラーと検証ツール——までを一気に押さえます。最後に、このサイト自身が JSON-LD をどう実装しているかを実例として開きます。
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 にマッピングしたものだ、と捉えるとよい。
最小の例
<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 でエイリアスを張ればアットマーク無しでも書ける。
データモデリングの勘所 — 配列の順序と数値精度のワナ
W3C のベストプラクティスが繰り返し強調するのは「開発者フレンドリーな JSON」であること。 その上で、RDF グラフに変換される都合から来る 2 つの落とし穴に注意する。
- 配列は既定で「順不同(Set)」。JSON の配列は順序を持つが、RDF は順不同のトリプル集合
として扱うため、変換時に順序が消える。順序が意味を持つなら
@contextで"@container": "@list"を宣言してrdf:Listだと解釈させる。 - 数値の精度欠損。多くの言語は数値を IEEE 754 倍精度で扱うので、大きな整数や精密な小数は
往復で誤差が出る。金融・学術など厳密な値は、あえて文字列で包み
@typeでxsd:decimal/xsd:integerへ**型強制(Type Coercion)**するのが定石。 - 文字列ではなく「実体」で書く。プロパティ値に名前の文字列を置くのではなく、
@typeと@idを持つオブジェクトにして実体化する。双方向・循環参照は、一方はネスト・逆方向は@id参照だけ、にして無限ループを避ける。
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 とドメイン接続) に残した。JSON-LD の
@id一致は、この canonical 規律の上に乗っている。
よくある 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 変換の挙動を観察。
このサイト自身の JSON-LD
ここまでの理論は、このサイト(apps/web)がそのまま実装している。抽象論ではなく
動いている実例として見てほしい——JSON-LD の記事が、JSON-LD で記述されている。
自分の主張を、自分で使って証明する——この姿勢は
ドッグフーディングの情報設計版だ。
1. Site-wide を @id で 1 ノードに束ねる。 ルートレイアウトが全ページ共通で Organization と
WebSite を出し、#organization / #website の @id で相互参照する。
// 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 の分離だ。
// この記事(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)。時系列の記録は BlogPosting、常設の技術解説は
TechArticle、と型を描き分けることで、機械にも「これは記事、これは作品集」と伝わる。
@id を「唯一のつなぎ目」にしてリンクの二重管理を消す発想は、このサイトが
VMOST → Roadmap → Log を一本の線でつないだ ときと同じだ。
人手のリンクは必ずドリフトする——安定した 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 とは、実装の記録は 実験ログ にある。



