JSONフィールドのカスタムGo型エイリアス
JSONフィールドの強力な型付けのためにGoでカスタム型エイリアスや名前付き型を作成します。enum、カスタムマーシャラー、ドメイン固有型を解説。
Patterns
詳細な説明
より強力なJSON型付けのためのカスタム型
Goではプリミティブに基づいた名前付き型を定義でき、生のstringやintでは提供できない型安全性、カスタムメソッド、ドメインセマンティクスを実現します。
Enum的な型
{
"id": 1,
"status": "active",
"role": "admin",
"priority": 3
}
type Status string
const (
StatusActive Status = "active"
StatusInactive Status = "inactive"
StatusPending Status = "pending"
)
type Role string
const (
RoleAdmin Role = "admin"
RoleEditor Role = "editor"
RoleViewer Role = "viewer"
)
type Priority int
const (
PriorityLow Priority = 1
PriorityMedium Priority = 2
PriorityHigh Priority = 3
)
type Ticket struct {
ID int `json:"id"`
Status Status `json:"status"`
Role Role `json:"role"`
Priority Priority `json:"priority"`
}
カスタム型が重要な理由
名前付き型は技術的に同じGo型の値の混同を防ぎます:
func AssignTicket(role Role, status Status) { ... }
// StatusをRoleが期待される場所に誤って渡すことはできない
カスタムマーシャリング
特別なシリアライゼーションが必要な型には、json.Marshaler と json.Unmarshaler を実装します:
type Cents int
func (c Cents) MarshalJSON() ([]byte, error) {
dollars := float64(c) / 100.0
return json.Marshal(dollars)
}
func (c *Cents) UnmarshalJSON(b []byte) error {
var dollars float64
if err := json.Unmarshal(b, &dollars); err != nil {
return err
}
*c = Cents(dollars * 100)
return nil
}
この型は内部的に整数セントとして金額を保存しますが、JSONでは小数ドルとしてシリアライズします。
アンマーシャル時のバリデーション
カスタム型はアンマーシャリング中に値を検証できます:
func (s *Status) UnmarshalJSON(b []byte) error {
var str string
json.Unmarshal(b, &str)
switch Status(str) {
case StatusActive, StatusInactive, StatusPending:
*s = Status(str)
return nil
}
return fmt.Errorf("invalid status: %s", str)
}
これにより、無効なステータス値がシステム内を伝播する代わりに、パース時に拒否されます。
ユースケース
Goでのドメイン駆動設計は、enum、金額値、識別子のカスタム型の恩恵を受けます。コンパイル時にバグをキャッチし、JSON APIデータの変換時にコードを自己文書化します。