Help us understand the problem. What is going on with this article?

Go言語Marshal系インターフェースの拡張で使えるNoMethodイディオム

More than 1 year has passed since last update.

NoMethod

Go言語、例えばJSONで、特に構造体などの(Un)Marshalerインターフェースを実装するとき、
外部ライブラリのJSONパーサを利用したかったり、ちょっとした処理を追加したいだけで基本的な処理は標準ライブラリと同じ処理をしてほしいときがあります。
しかし単に呼び直すと再実装されたMarshalメソッドを呼び出すことになるのでループしてしまいます。
メソッドを持たない別の型を宣言しラップすることでこれを解決できます。

type Gopher struct{}

func (g *Gopher) MarshalJSON() ([]byte, error) {
    type NoMethod Gopher
    g.onJSONEncoding() //行いたい処理
    raw := NoMethod(*g)
    return json.Marshal(raw)
}

応用

もう一つ、例えばTime型などjsonでサポートされていない型に対応させたいとき、Unmarshalメソッドを実装するために別の型を宣言しますがその型をそのままメンバにするとtime.Time型を直接使うのと比べていろいろと扱いづらいと思います。
これは元の型を埋め込んでいる冗長なメンバを持った一時的な構造体を定義することで解決できます。

type Time time.Time

func (t *Time) UnmarshalJSON(b []byte) error {
    var tt time.Time
    tt, err := time.Parse(`"2006-01-02"`, string(b))
    *t = Time(tt)
    return err
}

type Gopher struct {
    Birthday time.Time
}

func (g *Gopher) UnmarshalJSON(data []byte) error {
    type NoMethod Gopher
    var gg struct {
        Birthday Time
        *NoMethod
    }
    gg.NoMethod = (*NoMethod)(g)
    if err := json.Unmarshal(data, &gg); err != nil {
        return err
    }
    g.Birthday = time.Time(gg.Birthday)
    return nil
}

GoPlayground
https://play.golang.org/p/lVSwnkJFDLv

weloan
King Arthur's Gold、ご存知ですか サンドボックスPvP それはあまりに完成された存在 マイクラフォロワの中で建築の実用性を匠に表現した稀有な存在 自由度の高すぎた為に安易な調整が許されぬ怪物建築多くがその怪物に破れ積まれ あまりにも完成された存在 飛び交う爆弾と矢の間で適切な前線基地と適切でないシャレオツ砦堆積する攻城建築 KAG二度と戻らない夢の
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away