【実務・中級編】HSLのJSON操作:PHPのjson_decodeの戻り値の曖昧さを型で解決する – Hack言語 コア・静的型システムとHHVMのアーキテクチャ解析バイブル

PHPの「闇」をHackの「型」で浄化する:JSONデコードの型安全性とHSLの活用術

いいか、よく聞け。PHPの `json_decode()` をそのまま使い続けるのは、爆弾を抱えてコードを書いているのと同じだ。

`mixed` が返ってくる? `assoc` フラグを忘れてstdClassが混入する? そんなものは静的解析を放棄した「怠慢」でしかない。HHVMの型システムを享受する我々にとって、JSONのパースは「外部からの境界線」であり、最も厳格にガードを固めるべき領域だ。

今日は、PHPの曖昧なJSON処理を、Hackの強力な型システムで完全に統制する方法を伝授する。

—

1. なぜ `json_decode` の戻り値は「悪」なのか

PHPの `json_decode` が返すのは `mixed` だ。これは型システムにおける「白紙委任状」だ。

  • プロパティの欠損が実行時まで発覚しない。
  • 予期せぬ型(nullや配列の入れ替わり)が混入し、`TypeError` を引き起こす。
  • 何より、コードを読む人間が「このJSONには何が入っているのか」を推測しなければならない。

Hackにおける正解は、「受信した瞬間にShapeまたはクラスへ強制変換(キャスト)し、以降の処理ではその型を保証する」ことだ。

—

2. 堅牢なJSONデコード:実戦的実装パターン

HSL (`Hack Standard Library`) の `HH\Lib\Json` を活用しつつ、型を強制するラッパーを定義する。ここでは、外部APIレスポンスを想定したパターンを示す。

namespace App\Infrastructure;

use namespace HH\Lib\Json;
use type HH\Lib\Json\DecodeException;

// JSONの構造を型として定義する
type UserApiResponse = shape(
‘id’ => int,
‘username’ => string,
‘email’ => ?string, // null許容も明示的に
‘is_active’ => bool,
);

final class JsonParser {
/

  • 型安全にJSONをデコードする
  • @throws DecodeException
  • @throws \InvalidArgumentException 型が一致しない場合

/
public static function decodeUser(string $json): UserApiResponse {
$decoded = Json\decode($json);

// ここで検証を行う。型チェックを透過させるためのマッピング処理
if (
$decoded is dict<_, _> &&
$decoded[‘id’] is int &&
$decoded[‘username’] is string &&
($decoded[‘email’] is string || $decoded[‘email’] is null) &&
$decoded[‘is_active’] is bool
) {
return shape(
‘id’ => $decoded[‘id’],
‘username’ => $decoded[‘username’],
‘email’ => $decoded[‘email’],
‘is_active’ => $decoded[‘is_active’],
);
}

throw new \InvalidArgumentException(‘Invalid JSON structure: UserApiResponse’);
}
}

この設計のポイント

1. 型ガード(Type Guard): `is` 演算子を使い、ランタイムで型を検証している。これを通れば、以降のコードは完全に `UserApiResponse` として扱える。
2. 早期リターン: 不正なデータが混入した瞬間、最深部で例外を投げる。これにより、ビジネスロジック層に汚染データが到達することを防ぐ。
3. HSLの活用: `HH\Lib\Json` は例外を投げるため、エラーハンドリングが予測可能だ。

—

3. パフォーマンスとスケーラビリティへの視座

「毎回検証すると遅くないか?」という懸念を持つ者は、HHVMのJITコンパイラの挙動を理解していない。

  • 静的解析のコスト: Hackの型チェックはコンパイル時に終わっている。実行時に型検証を行っているのは「境界線」のみだ。
  • ヒープメモリの節約: `stdClass` はメモリを食う。Shape型は内部的に配列に近い形で最適化されており、HHVMのメモリ管理において非常に効率的だ。
  • 深いネストへの対処: もしJSON構造が複雑すぎるなら、`shape` ではなく `Record` を検討しろ。データの不変性(Immutability)を担保でき、HHVMの最適化対象としてさらに強力だ。

—

4. プロの運用指針:コードレビューで叩くべきポイント

部下のコードをレビューする際、以下のコードを見つけたら即座に差し戻せ。

  • ✕ `(array)json_decode($json, true)`: 構造を保証していない。
  • ✕ `dynamic` 型へのキャスト: 型システムを無効化する逃げ道は許さない。
  • ✕ サービス層の深い場所で `json_decode` を呼ぶ: JSON操作はインフラストラクチャ層(APIクライアントやデータリポジトリ)で完結させ、ロジック層には「純粋なHackのオブジェクト(Shape/Class)」のみを渡すのが鉄則だ。

—

最後に:型は「制約」ではなく「武器」だ

多くのエンジニアが、型を「書くのが面倒な制約」だと勘違いしている。だがHackの型は、「未来の自分、あるいは同僚がバグを生み出す余地を消し去るための武器」だ。

JSONのような「外部からの不確定要素」こそ、最も手厚く型で囲い込むべきだ。それが、大規模なWebアプリケーションを数年単位でメンテナンスし続けるための、唯一にして最強の解である。

さあ、今すぐお前のコードベースにある `mixed` を駆逐せよ。型安全な世界は、すぐそこにある。

タイトルとURLをコピーしました