皆さんはじめまして、ディップ株式会社の町田です。 R&D推進室でGoを使った開発とその支援をしています。
今回はとあるGoのパッケージを公開しましたのでその紹介をしたいと思います。 Goの経験者向けの内容になってしまっていますが、最後までお付き合いいただけると幸いです。
go-json/opt
今回公開したパッケージは以下になります。 github.com
こんなことができます
JSONをUnmarshalした構造体から、元のJSONのフィールド有無を判定できるようになります。
例えば、以下のリクエストをJSONで受けるユーザー更新APIがあったとします。
項目名 | 型 | 必須 |
---|---|---|
user_id | 数値 | ◯ |
user_name | 文字列 | - |
age | 数値 | - |
リクエストを受ける構造体を基本の型で定義すると
type Request struct { UserID int32 `json:"user_id"` UserName *string `json:"user_name"` Age *int32 `json:"age"` }
JSONフィールドの有無を判別することができなくなります。
var req Request // user_nameフィールド有り、値がnullの場合 _ = json.Unmarshal([]byte(`{"user_id": 1, "user_name": null, "age": 25}`), &req) fmt.Println(req.UserID) // 1 fmt.Println(req.UserName) // nil fmt.Println(req.Age) // 25 // user_nameフィールド無しの場合 _ = json.Unmarshal([]byte(`{"user_id": 1, "age": 25}`), &req) fmt.Println(req.UserID) // 1 fmt.Println(req.UserName) // nil fmt.Println(req.Age) // 25
更新対象の項目がJSONにフィールドが設定されているものに限定する(差分のみが渡ってくる)仕様の場合、困ったことになります。
前者はuser_name
をnullに更新し、後者はuser_name
は更新対象外とする必要がありますが、
どちらもUserName=nil
になってしまうため、更新対象か否かが判断できません。
optパッケージで解決できます
リクエストを受ける構造体でgo-json/opt
パッケージを利用します
import "github.com/dip-dev/go-json/opt" type Request struct { UserID int32 `json:"user_id"` UserName opt.String `json:"user_name"` Age opt.Int32 `json:"age"` }
optパッケージではHasKey
メソッドを参照することでフィールドの有無を判定することができます。
var req Request // user_nameフィールド有り、値がnullの場合 _ = json.Unmarshal([]byte(`{"user_id": 1, "user_name": null, "age": 25}`), &req) fmt.Println(req.UserID) // 1 fmt.Println(req.UserName.Value()) // nil fmt.Println(req.UserName.HasKey()) // true fmt.Println(req.Age.Value()) // 25 fmt.Println(req.Age.HasKey()) // true // user_nameフィールド無しの場合 _ = json.Unmarshal([]byte(`{"user_id": 1, "age": 25}`), &req) fmt.Println(req.UserID) // 1 fmt.Println(req.UserName.Value()) // nil fmt.Println(req.UserName.HasKey()) // false fmt.Println(req.Age.Value()) // 25 fmt.Println(req.Age.HasKey()) // true
フィールドが無い項目はHasKey()
がfalseとなるため、処理分岐が可能となります。
おわりに
基本的な型は全て対応していますが、rune
等の一部の型には対応していません。
詳細な使い方についてはREADMEを参照ください。
こちらのパッケージが少しでも皆さんの開発のお役に立てれば嬉しいです。