JSON/YAML/TOML
目次
- 概要
- 3つの形式の使い分け
- JSON
- JSONの相互運用性
- YAML
- YAMLの落とし穴
- TOML
- schemaと検証
- 安全な読み込み
- 差分レビューの観点
- 設定ファイルの設計
- 変換と互換性
- ケーススタディ: アプリ設定
- CLIで検証する
- アンチパターン
- JSONスキーマの深掘り
- YAML安全性の詳細
- TOML の標準化プロセス
- RFC 8259 の重要なセクション
- JSON Schemaの keyword 一覧(主要)
- YAML 1.2 仕様の Core Tags
- TOML Table の入れ子と Dotted Key
- 設定ファイル検証の実装パターン
- CI/CDでの設定検証フロー
- 実装上の注意点と Best Practice
- 仕様と実装の補足
- まとめ
- 参考文献
概要
JSON、YAML、TOMLは、設定、API、CI/CD、インフラ定義でよく使われるデータ形式です。見た目は似ていますが、得意な用途、落とし穴、レビューしやすさが違います。
JSONは機械間通信、YAMLは人間が書く設定、TOMLは明示的な設定ファイルに向きます。どれを使う場合も、型、必須項目、default、secretの扱いを決めることが重要です。
3つの形式の使い分け
| 形式 | 向いている用途 | 注意点 |
|---|---|---|
| JSON | API、ログ、機械間通信 | コメント不可、末尾カンマ不可 |
| YAML | CI、Kubernetes、設定 | インデント、暗黙型変換、複雑な機能 |
| TOML | アプリ設定、ツール設定 | 表現力は控えめだが読みやすい |
JSON
JSONは、JavaScript Object Notationに由来する軽量なデータ形式です。
{
"name": "site",
"enabled": true,
"ports": [80, 443]
}
JSONの型です。
| 型 | 例 |
|---|---|
| object | {"a": 1} |
| array | [1, 2, 3] |
| string | "hello" |
| number | 123 |
| boolean | true |
| null | null |
JSONはコメントが書けません。コメントが必要なら、外側のドキュメントを用意するか、JSONCのような別形式を使う判断になります。
JSONの相互運用性
RFC 8259は、JSONを軽量でテキストベースの言語非依存なデータ交換形式として定義しています。実務で重要なのは、「仕様上許されるか」だけでなく「多くの実装で同じように解釈されるか」です。
注意点です。
| 観点 | 注意 |
|---|---|
| objectのkey | 一意であるべき。重複時の挙動は実装差が出る |
| objectの順序 | 意味に依存しない方がよい |
| number | NaN、Infinity は標準JSONではない |
| 大きな整数 | JavaScriptなどで精度が落ちる可能性 |
| 文字コード | ネットワーク上ではUTF-8を基本に考える |
重複keyの例です。
{
"port": 8080,
"port": 9090
}
このようなJSONは、parserによって「後勝ち」「エラー」「両方保持」など挙動が分かれる可能性があります。設定ファイルでは、重複keyを検出できるlinterやschema validationを使う方が安全です。
数値にも注意します。
{
"id": 9007199254740993
}
JavaScriptの Number は安全に整数として表せる範囲に限界があります。IDのように計算しない値は、文字列として扱う設計もあります。
{
"id": "9007199254740993"
}
YAML
YAMLは、人間が書きやすい設定でよく使われます。
name: site
enabled: true
ports:
- 80
- 443
YAMLは読みやすい一方、インデントと暗黙の型変換に注意が必要です。
enabled: yes
date: 2026-04-29
実装やバージョンによって、yes や日付が文字列ではなく別の型として解釈されることがあります。曖昧さを避けるには、文字列を引用します。
enabled: "yes"
date: "2026-04-29"
YAMLの落とし穴
YAMLは、人間が書きやすい反面、機能が多く、レビューで見落としやすい形式です。
代表的な注意点です。
| 機能 | 注意 |
|---|---|
| インデント | 1段ずれるだけで意味が変わる |
| 暗黙型変換 | 文字列のつもりがbooleanやdateになることがある |
| anchor / alias | 同じ構造を再利用できるが、追跡が難しくなる |
| merge key | 値の由来が分かりにくくなる |
| 複数document | --- で複数のdocumentを含められる |
anchorとaliasの例です。
defaults: &defaults
retries: 3
timeout_ms: 1000
development:
<<: *defaults
debug: true
production:
<<: *defaults
debug: false
便利ですが、差分レビューでは「最終的にどの値になるか」が見えにくくなります。特に本番設定では、抽象化しすぎず、重要な値は明示する方が安全なことがあります。
KubernetesやCIのYAMLでは、1文字のインデント差が挙動を変えます。レビューでは、値そのものだけでなく「どの親要素の下にあるか」を確認します。
TOML
TOMLは、設定ファイルとして読みやすいことを重視した形式です。
name = "site"
enabled = true
ports = [80, 443]
[server]
host = "localhost"
port = 8000
TOMLは、key-valueとtableの形が明確です。Pythonの pyproject.toml やRustの Cargo.toml などで使われます。
schemaと検証
設定ファイルは、形式として正しくても意味として正しいとは限りません。
{
"port": "eighty"
}
port が数値であるべきなら、schemaで検証します。
schemaで決めることです。
- 必須項目
- 型
- 許可する値
- default
- deprecatedな項目
- secretを含むか
JSON Schemaの小さな例です。
{
"type": "object",
"required": ["server", "timeouts"],
"properties": {
"server": {
"type": "object",
"required": ["port"],
"properties": {
"port": {
"type": "integer",
"minimum": 1,
"maximum": 65535
}
}
},
"timeouts": {
"type": "object",
"properties": {
"request_timeout_ms": {
"type": "integer",
"minimum": 1
}
}
}
}
}
schemaは「形式チェック」だけでなく、設定の仕様書としても機能します。人間向けのREADMEと機械向けのschemaが一致していると、運用時の事故が減ります。
安全な読み込み
データ形式の読み込みでは、信頼できない入力を前提にします。
読み込み時の注意です。
| 形式 | 注意 |
|---|---|
| JSON | 入力サイズ、深いネスト、大きな数値 |
| YAML | 任意オブジェクト生成を避ける、安全なloaderを使う |
| TOML | 型を明示し、読み込み後にアプリ側で検証 |
Pythonの json ドキュメントでも、信頼できないJSONがCPUやメモリを消費する可能性に触れています。外部入力では、サイズ上限、timeout、schema validationを組み合わせます。
TOMLはPython 3.11以降なら標準ライブラリの tomllib で読み込めます。
import tomllib
with open("pyproject.toml", "rb") as f:
data = tomllib.load(f)
tomllib は読み込み専用です。書き出しが必要なら別ライブラリを選びます。
差分レビューの観点
設定ファイルのレビューでは、コードと違う観点が必要です。
| 観点 | 確認すること |
|---|---|
| 型 | 文字列と数値を取り違えていないか |
| 単位 | 秒、ミリ秒、MB、MiBが混ざっていないか |
| default | 未指定時の挙動は明確か |
| secret | tokenやpasswordが入っていないか |
| 環境差 | dev/prodの差分が安全か |
| コメント | 古い説明が残っていないか |
YAMLはインデントだけで構造が変わるため、差分レビューでは「どの階層に入ったか」を特に確認します。
設定ファイルの設計
よい設定ファイルは、アプリケーションの意図を読みやすくします。
- 名前を具体的にする
- 単位を名前に含める
- defaultをドキュメント化する
- 環境ごとの差分を小さくする
- secretと通常設定を分ける
- 使われていない項目を残さない
request_timeout_ms: 3000
max_upload_size_mb: 20
timeout: 3 より、単位を含めた方が誤解が減ります。
変換と互換性
JSON、YAML、TOMLは相互に変換できることがありますが、完全に同じ情報を表せるとは限りません。
| 観点 | 注意 |
|---|---|
| コメント | JSONには標準コメントがない |
| 日付 | YAML/TOMLでは日付型として解釈されることがある |
| 数値 | 大きな整数や小数の精度に注意 |
| key順序 | ツールによって保持されないことがある |
| 複数document | YAMLは --- で複数documentを持てる |
設定ファイルを別形式へ変換するときは、見た目だけでなく、型が変わっていないかを確認します。
この流れでは、元のコメントや細かい書式は失われることがあります。設定を機械変換する場合は、変換後のdiffとschema validationを必ず確認します。
ケーススタディ: アプリ設定
小さなWebアプリの設定を考えます。
server:
host: "0.0.0.0"
port: 8080
database:
url_env: "DATABASE_URL"
pool_size: 10
security:
session_cookie_name: "sid"
csrf_enabled: true
timeouts:
request_timeout_ms: 3000
shutdown_timeout_ms: 10000
この設計では、secretの値そのものを設定ファイルに入れず、環境変数名だけを入れています。url_env のように名前で意図を表すと、レビュー時にsecret混入を見つけやすくなります。
設定を読む側では、defaultを暗黙にしすぎない方が安全です。
def load_config(raw: dict) -> Config:
return Config(
port=int(raw["server"]["port"]),
request_timeout_ms=int(raw["timeouts"]["request_timeout_ms"]),
)
「ない場合はなんとなく0」ではなく、必須なら必須として失敗させます。設定の失敗は起動時に早く見つかる方が運用しやすいです。
CLIで検証する
設定ファイルは、CIで検証できるようにします。
JSONの整形と検証です。
python3 -m json.tool config.json
JSONを読みやすく整形します。
jq . config.json
YAMLやTOMLも、プロジェクトで使うparserと同じ系統のツールで検証すると安心です。
python3 - <<'PY'
import tomllib
with open("pyproject.toml", "rb") as f:
tomllib.load(f)
print("ok")
PY
CIでの検証フローです。
syntax checkは「読めるか」、schema validationは「形が合うか」、semantic validationは「意味として安全か」を確認します。
アンチパターン
よくあるアンチパターンです。
| アンチパターン | 問題 | 改善 |
|---|---|---|
| secretを設定ファイルに直書き | 漏えいしやすい | 環境変数名やsecret manager参照にする |
| 単位がない | 秒/ミリ秒を間違える | timeout_ms のように名前に入れる |
| defaultがコードに散らばる | 仕様が追えない | schema/READMEに寄せる |
| YAML anchorを多用 | 最終値が読みにくい | 重要設定は明示 |
| JSONにコメント代わりのkey | アプリが誤って読む | READMEやschema descriptionを使う |
| 型が曖昧 | "1" と 1 が混在 |
schemaで固定 |
コメント代わりのkeyの例です。
{
"_comment": "production setting",
"debug": false
}
小さな設定では便利に見えますが、アプリケーションが未知keyを許す設計だと、typoも通ってしまいます。未知keyを拒否するか、schemaで許可項目を明示します。
JSONスキーマの深掘り
JSON Schemaは単なる検証ツールではなく、APIドキュメント、OpenAPIスペック、GraphQL型定義と並んで、データ契約を定義する重要な機構です。
Draft バージョンの理解
JSON Schemaは複数のdraft versionが存在し、互換性を慎重に保っています。
| Draft | リリース年 | 主な変更 |
|---|---|---|
| Draft 3 | 2013 | 初期仕様 |
| Draft 4 | 2013 | RFC化の準備 |
| Draft 6 | 2017 | 新しいキーワード追加(const, examples) |
| Draft 7 | 2018 | if/then/elseで条件分岐可能 |
| Draft 2019-09 | 2019 | unevaluatedProperties, dependentRequired |
| Draft 2020-12 | 2020 | 最新版、$dynamicで動的スキーマ対応 |
古いdraftで書かれたスキーマは新しいバージョンのvalidatorでも動作することがほとんどですが、新しいキーワードが使えません。
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"type": "object",
"properties": {
"id": { "type": "integer", "const": 42 },
"name": { "type": "string" },
"price": { "type": "number", "minimum": 0 }
},
"required": ["id", "name"]
}
$schema で明示することで、バージョン差異による混乱を防げます。
Conditional Validation
Draft 7以降では if/then/else で複雑な条件付き検証が可能です。
{
"type": "object",
"properties": {
"event": { "type": "string", "enum": ["login", "logout"] },
"session_id": { "type": "string" }
},
"if": { "properties": { "event": { "const": "login" } } },
"then": { "required": ["session_id"] },
"else": { "required": [] }
}
このスキーマでは、event が “login” の場合、session_id は必須になります。
YAML安全性の詳細
YAMLの暗黙的なオブジェクト化は、セキュリティリスクとなります。Pythonの例です。
危険なYAML解析
import yaml
# 危険: arbitrary code executionの可能性
dangerous_yaml = "!!python/object/apply:os.system ['rm -rf /']"
yaml.load(dangerous_yaml) # !!ERROR: セキュリティ脅威
安全な解析
import yaml
safe_yaml = """
users:
- name: alice
role: admin
- name: bob
role: user
"""
data = yaml.safe_load(safe_yaml) # 安全: 辞書とリストのみ
信頼できないYAMLソースでは、常に safe_load() または load(..., Loader=yaml.SafeLoader) を使用します。
TOML の標準化プロセス
TOMLは v1.0.0に到達するまで、以下のマイルストーンを経ました。
| バージョン | リリース | 主な変更 |
|---|---|---|
| 0.1.0 | 2013年 | 初期版 |
| 0.4.0 | 2014年 | Tableの構文改善 |
| 0.5.0 | 2017年 | Offline ratificationプロセス開始 |
| 1.0.0 | 2021年 | 公式仕様確定 |
Python 3.11で tomllib が標準化されたことにより、TOML採用がさらに加速しました。
[tool.poetry]
name = "myproject"
version = "0.1.0"
[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.28.0"
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = "test_*.py"
この構造は、各toolセクションが独立した設定を管理できるため、プロジェクト全体の設定を一元管理できます。
RFC 8259 の重要なセクション
RFC 8259は、JSONの公式仕様として以下の重要な規定を含みます。
Number の精度
RFC 8259では、JSONの number 型の実装上の注意として、以下を記載しています:
A JSON number is represented in text as a sequence of digits with optional negation, fraction, or exponent.
具体的には、JavaScriptなどで以下の問題が発生します:
// IEEE 754倍精度浮動小数点数の限界
JSON.parse('{"id": 9007199254740993}')
// 結果: {id: 9007199254740992} ← 末尾の1が失われる
// 回避策: 大きな整数は文字列で表現
JSON.parse('{"id": "9007199254740993"}')
// 結果: {id: "9007199254740993"} ← 正確
JavaScriptの安全な整数範囲は、Number.MAX_SAFE_INTEGER (9007199254740991) までです。
String の Escape Sequence
RFC 8259では、JSONの文字列内で以下のエスケープシーケンスを定義しています:
\" (\\ (\ /) (\b (\f (\n (\r (\t (\uXXXX
具体例:
{
"path": "C:\\Users\\Documents",
"quote": "He said \"hello\"",
"unicode": "日本語: 日本語"
}
JSON Schemaの keyword 一覧(主要)
実際のバリデーション実装では、以下のkeywordが頻出です。
| Keyword | 用途 | 例 |
|---|---|---|
| type | 型チェック | "type": "object" |
| properties | オブジェクトのプロパティ定義 | "properties": {"name": {...}} |
| required | 必須フィールド | "required": ["id", "name"] |
| enum | 許可値リスト | "enum": ["active", "inactive"] |
| minimum / maximum | 数値範囲 | "minimum": 0, "maximum": 100 |
| minLength / maxLength | 文字列長 | "minLength": 1, "maxLength": 255 |
| pattern | 正規表現マッチ | "pattern": "^[a-z]+{{CONTENT}}quot; |
| oneOf / anyOf / allOf | スキーマの組み合わせ | "oneOf": [{...}, {...}] |
| $ref | 外部スキーマ参照 | "$ref": "#/definitions/User" |
| additionalProperties | 追加プロパティの許可 | "additionalProperties": false |
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"email": {
"type": "string",
"pattern": "^[^@]+@[^@]+\\.[^@]+{{CONTENT}}quot;
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"status": {
"type": "string",
"enum": ["active", "suspended", "deleted"]
}
},
"required": ["email", "status"],
"additionalProperties": false
}
YAML 1.2 仕様の Core Tags
YAMLは独自の型タグシステムを持ち、以下の core tags が定義されています:
| Tag | 説明 | 例 |
|---|---|---|
| !!str | 文字列 | !!str 123 → “123” |
| !!int | 整数 | !!int "42" → 42 |
| !!float | 浮動小数点数 | !!float .inf, .nan |
| !!bool | 論理値 | !!bool yes → true |
| !!null | null値 | !!null ~ |
| !!timestamp | ISO 8601日時 | 2026-05-03T10:00:00Z |
| !!seq | リスト | !!seq [1, 2, 3] |
| !!map | マップ | !!map {a: 1, b: 2} |
# 暗黙的型変換の例
implicit:
yes_string: "yes" # 文字列
yes_bool: yes # boolean
date_string: "2026-01-01" # 文字列
date_implicit: 2026-01-01 # date
# 明示的タグの例
explicit:
version: !!str 1.0 # 文字列として解析
enabled: !!bool "0" # false (0も真と解釈されるため明示)
TOML Table の入れ子と Dotted Key
TOML では、同じ情報を複数の記法で表現できます。
# 通常の記法
[database.connection]
host = "localhost"
port = 5432
# Dotted key での記法(同じ意味)
database.connection.host = "localhost"
database.connection.port = 5432
# 直列化と inline table
servers = [
{ name = "alpha", ip = "10.0.0.1" },
{ name = "beta", ip = "10.0.0.2" }
]
パーサーの多くは、両者を同じデータ構造に変換します。
設定ファイル検証の実装パターン
パターン1: Schema ベース(推奨)
import json
import jsonschema
schema = {
"type": "object",
"properties": {
"server": {
"type": "object",
"properties": {
"host": {"type": "string"},
"port": {"type": "integer", "minimum": 1, "maximum": 65535}
},
"required": ["host", "port"]
}
},
"required": ["server"]
}
config = {"server": {"host": "0.0.0.0", "port": 8080}}
try:
jsonschema.validate(config, schema)
print("Valid")
except jsonschema.ValidationError as e:
print(f"Invalid: {e.message}")
パターン2: Pydantic による型チェック(Pythonエコシステム)
from pydantic import BaseModel, Field
class ServerConfig(BaseModel):
host: str
port: int = Field(ge=1, le=65535)
class AppConfig(BaseModel):
server: ServerConfig
config_dict = {"server": {"host": "0.0.0.0", "port": 8080}}
config = AppConfig(**config_dict)
CI/CDでの設定検証フロー
実際のプロジェクトでは、以下のようなステップで検証を行います。
#!/bin/bash
# 1. 構文チェック
python3 -m json.tool config.json > /dev/null || exit 1
# 2. Schema検証
python3 - <<'PYTHON'
import json
import jsonschema
with open('config.json') as f:
config = json.load(f)
# schema validation logic here
PYTHON
# 3. Semantic check(ビジネスロジック)
./validate_config.py config.json || exit 1
# 4. 環境差チェック
diff -u config.default.json config.prod.json | grep '^[+-]' | wc -l
echo "All checks passed"
CI/CDパイプラインでは、これらをすべて自動化し、秘密情報の漏えいチェック、単位の整合性チェックなども含めます。
実装上の注意点と Best Practice
Large Payload の扱い
JSONやYAMLの大規模ファイルを扱う場合、メモリ効率を考慮する必要があります。
# ストリーミングJSON解析(ijson ライブラリ)
import ijson
with open('large_file.json', 'rb') as f:
for obj in ijson.items(f, 'item'):
# 1オブジェクトずつ処理
process(obj)
ファイルサイズが 1GB を超える場合、全体をメモリに読み込むのではなく、ストリーミング解析が必須です。
Charset エンコーディングの確認
JSON、YAML、TOML では、ファイルの charset エンコーディングが重要です。
| フォーマット | 推奨エンコーディング | 注意点 |
|---|---|---|
| JSON | UTF-8 | RFC 8259で UTF-8 推奨 |
| YAML | UTF-8 | YAML 1.2では UTF-8, UTF-16 サポート |
| TOML | UTF-8 | v1.0.0で UTF-8 のみ |
# ファイルのエンコーディング確認
file -i config.json
# output: config.json: application/json; charset=utf-8
エラーハンドリングの実装
本番環境では、parse エラーだけでなく、スキーマ検証エラーも適切にハンドルします。
import json
import logging
logger = logging.getLogger(__name__)
def safe_load_json(filepath):
try:
with open(filepath, 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
logger.error(f"Config file not found: {filepath}")
return None
except json.JSONDecodeError as e:
logger.error(f"Invalid JSON: {e.msg} at line {e.lineno}")
return None
except Exception as e:
logger.error(f"Unexpected error: {e}")
return None
Version Management
設定ファイルのバージョン管理は、互換性を保証する上で重要です。
# config.yaml
version: "1.0"
api:
base_url: "https://api.example.com"
timeout_sec: 30
# 将来のマイグレーション時
# version: "2.0"
# api:
# endpoints:
# default:
# base_url: "https://api.example.com"
# timeout_sec: 30
# legacy:
# base_url: "https://legacy.example.com"
バージョンを明示することで、アプリケーションのロジックで段階的に対応可能になります。
仕様と実装の補足
JSON仕様と エコシステム
RFC 7158と仕様の進化: json.org(https://json.org/)は、JSON(JavaScript Object Notation)の仕様を定義・管理する公式サイトです。RFC 7158 (2013年)で標準化されたJSON形式は、以下の要素で構成されています:
- オブジェクト: キーと値のペア(辞書、マップに相当)
- 配列: 値の順序付きリスト
- 文字列: Unicode文字のシーケンス
- 数値: 符号付き浮動小数点数
- 真偽値: true または false
- null: 値がないことを表す特殊値
シンプルさの哲学: JSONは意図的にシンプルな設計を採用しており、「全ての汎用プログラミング言語で容易に解析・生成できること」を目指しています。これにより、REST API、設定ファイル、データ交換フォーマットとして、プラットフォーム横断的な標準となっています。
JSONスキーマの標準化: JSON Schema(https://json-schema.org/)は、JSON文書の構造を形式的に記述するためのメタスキーマを定義しており、以下の検証機能が含まれます:
- プロパティの型チェック
- 必須フィールドの指定
- 数値の範囲制限
- 文字列のパターンマッチング
- 相互参照スキーマの組み合わせ
YAML - ヒューマンリーダブルなデータフォーマット
キー・バリューペアの階層構造: YAML(https://yaml.org/)は、人間が読み易い形式でデータ構造を表現するフォーマットです。JSONよりも簡潔な構文を採用しており、以下の特徴があります:
- インデント記法: ブレース・括弧を使わず、字下げでネストを表現
- 複数データ型: リスト、マップ、スカラー値、日付、タイムスタンプ
- アンカー・エイリアス: 同じデータの複数参照が可能
- コメント:
#以降の行をコメントとして記述可能
ユースケース: YAMLは主に以下の用途で採用されています:
- CI/CDパイプライン設定(GitHub Actions, GitLab CI, CircleCI)
- Kubernetes マニフェスト
- Ansible プレイブック
- Dockerコンポーズの設定ファイル
安全性の課題: YAMLは豊富な機能のため、特定の設定(arbitrary code executionが可能な型定義)では安全でない解析が行われる可能性があります。信頼できないYAMLソースを解析する際は、セーフモード(例: yaml.safe_load())の使用が推奨されています。
TOML - 設定ファイルのための言語
Pythonプロジェクトの標準化: TOML(https://toml.io/)は、アプリケーション設定ファイルの記述を目的に設計されたフォーマットです。以下の特徴を持ちます:
- セクション:
[section]により階層的な設定を表現 - キー・バリュー: JSONよりも読み易い構文
- 型の豊富さ: 文字列、数値、日付、配列、テーブルをネイティブサポート
- 日時形式: ISO 8601形式のタイムスタンプをネイティブ理解
Pythonエコシステムでの採用: Python 3.11以降のtomllibにより、Python標準ライブラリでTOML解析がサポートされました。これにより、以下のプロジェクトで設定ファイルフォーマットとして採用が進んでいます:
- Poetry(Pythonパッケージマネージャ)
- pyproject.toml(Pythonプロジェクト設定)
- Cargo.toml(Rustパッケージマネージャ)
構造化された設定: YAMLと異なり、TOMLはテーブル(table)という名前付きセクションを明示的に定義する設計を採用しており、「どのセクションがどのコンポーネントの設定か」が構造的に明確になります。
RFC Editor - インターネット標準
RFC 3629 (UTF-8)とRFC 20000系列: RFC Editor(https://rfc-editor.org/)は、インターネット技術標準(RFC - Request for Comments)を管理する公式リポジトリです。データフォーマット関連の主要RFCは以下のものです:
- RFC 3629: UTF-8、Unicode文字の8ビット符号化
- RFC 4648: Base64, Base32等の符号化方式
- RFC 5234: ABNF(Augmented Backus-Naur Form)、メタ言語の仕様
- RFC 7049: CBOR(Concise Binary Object Representation)、バイナリデータフォーマット
- RFC 8949: JSON Text Sequences、改行区切りのJSON
標準化プロセス: RFC発行には厳密なレビュープロセス(IETF - Internet Engineering Task Force)があり、「提案から標準化までの透明性」が確保されています。
Python Documentation - 型と形式
JSON モジュール: Python公式ドキュメント(https://docs.python.org)には、JSON、CSV、XML等の形式を扱うための標準ライブラリの仕様が記載されています。特にjsonモジュールは、Python オブジェクトとJSON形式の相互変換(serialization/deserialization)の実装方法を詳細に説明しています:
json.dumps(): Pythonオブジェクト → JSON文字列json.loads(): JSON文字列 → PythonオブジェクトJSONEncoder/JSONDecoder: カスタム型のエンコーディング
バイナリフォーマット: Pythonのstructモジュール、pickleモジュール、msgpack等の処理方法も記載されており、テキスト形式とバイナリ形式の使い分けの指針が提供されています。
Unicode Standard - 文字符号化体系
Unicode 15.0と拡張: Unicode.org(https://unicode.org/)は、世界中の文字・シンボルを統一的に符号化するUnicode標準を管理しています。以下の概念が定義されています:
- Code Point: 各文字に割り当てられた番号(0x0000から0x10FFFFまで)
- Planes: 文字群を65,536文字ごとのグループに分割
- Normalization: 同じ文字でも複数の符号化方式(NFC, NFKC等)をサポート
- Bidirectional Text: アラビア語・ヘブライ語等、右から左へ書く言語への対応
版管理: Unicodeは年1回のリリースサイクルを採用しており、新しい言語・絵文字・記号が段階的に追加されています。2024年版では、新しい絵文字700個以上が追加されました。
Oracle Database - エンタープライズデータフォーマット
SQL標準とバイナリ形式: Oracle Databaseドキュメント(https://docs.oracle.com)には、リレーショナルデータベースにおけるデータ型・フォーマット・ストレージ形式が詳細に説明されています:
- NUMBER型: 可変長浮動小数点数フォーマット
- VARCHAR2: 文字列の最大長とエンコーディング
- DATE/TIMESTAMP: 日時データの内部表現
- RAW/BLOB: バイナリデータの格納方式
まとめ
JSON、YAML、TOMLは、用途によって選び分ける道具です。形式そのものよりも、型、schema、default、secret、差分レビューのルールを整えることが、長く安全に使うために重要です。
データシリアライゼーションと型安全性
型情報の保存: JSON はテキスト形式であるため、「この数値は整数か浮動小数点数か」「この文字列は日付を表すか」といった型情報を保存できません。スキーマレスな JSON の課題は、以下で緩和されます:
- JSON Schema: 型情報、制約条件を形式的に定義
- OpenAPI: API のレスポンス型を明示
- Protocol Buffers: スキーマを IDL (Interface Definition Language) で定義し、コード生成
相互運用性: JSON の単純さゆえに、Python, JavaScript, Go, Rust など全ての言語で容易に parse/serialize が可能であり、マイクロサービスアーキテクチャでの標準フォーマットとなっています。
バイナリフォーマットと性能トレードオフ
MessagePack と Protocol Buffers: JSON より compact なバイナリフォーマットは、以下の利点を提供します:
- サイズ削減: JSON の 40~60% のサイズに圧縮(例:
{"name":"John"}→ バイナリで 数バイト) - パース性能: テキスト解析オーバーヘッドが無い
- 型安全性: スキーマベースの定義により型チェック可能
用途別選定: JSON は REST API や設定ファイルの標準、MessagePack は高頻度なマイクロサービス間通信(gRPC等)に最適です。
YAML と設定ファイル設計
プログラマテック vs テンプレート: YAML は人間が直接編集することを想定した設計であり、以下の特徴があります:
- 可視性: ネストが字下げで明示的に表現
- コメント:
#による説明 - 複数の型: 文字列、数値、日付、リスト、マップが native サポート
セキュリティ:YAML の危険な機能(arbitrary code execution が可能な型定義)のため、信頼できないソースの YAML は yaml.safe_load() で安全に解析します。
TOML と設定ファイルの構造
セクションによる階層化: TOML の [section] 記法により、階層的な設定を人間が読みやすい形で表現できます:
[database]
server = "192.168.1.1"
ports = [ 8000, 8001, 8002 ]
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00
Pythonエコシステムでの採用: Python 3.11+ では tomllib がコアライブラリに含まれ、Poetry など主要ツールが TOML を採用しています。
Unicode と 多言語対応
Normalization Forms: Unicode 文字は複数の表現が可能です(例: “é"は1文字または"e” + “acute accent” の2文字)。NFC(Composed)に正規化することで、データベースでの一致判定を確実にします:
import unicodedata
s1 = "café" # é が1文字
s2 = "café" # e + acute accent
unicodedata.normalize('NFC', s1) == unicodedata.normalize('NFC', s2) # True
言語固有の配列: CJK(中国語、日本語、韓国語)言語では、Unicode の Blocks が異なります:
- CJK Unified Ideographs: U+4E00–U+9FFF (約 21,000 文字)
- Hiragana: U+3040–U+309F (46 文字)
- Katakana: U+30A0–U+30FF (91 文字)
RFC エディタと 標準化プロセス
RFC 発行の厳密性: RFC (Request for Comments) は IETF による公式レビュープロセスを経ており、以下のステータスで管理されます:
- Proposed Standard: 提案段階、2年間のテストが推奨
- Draft Standard: 広く実装され、相互運用性が確認
- Internet Standard: 最も安定した標準
セキュリティ RFCs: RFC 3629 (UTF-8), RFC 4648 (Base64 Encoding) など、セキュリティに関連するデータフォーマット RFCs は特に厳密に審査されます。
Oracleとリレーショナルデータベース
型定義と内部表現: Oracle の NUMBER 型は可変長形式で符号化され、メモリ効率と精度のバランスを取っています。VARCHAR2 は可変長文字列で、最大 4,000 bytes (またはキャラクタ数) を格納できます。
バイナリラージオブジェクト: BLOB (Binary Large Object) と CLOB (Character Large Object) は数 GB のデータを格納でき、「構造化データ」と「非構造化データ」の境界線を表現します。
参考文献
公式・標準
- RFC 8259: The JavaScript Object Notation Data Interchange Format
- Python Documentation: json
- Python Documentation: tomllib
- YAML 1.2.2 Specification
- YAML Specification