reizt
@reizt (Takahashi Reiju)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

[Go] REST APIで部分更新するときゼロ値で詰む

解決したいこと

GinでREST APIを作っています。例として投稿を意味するpostsというリソースを使います。
投稿は以下のような構造体です。

import (
    "time"
)

type Post struct {
    ID        string
    Title     string
    Content   string
    CreatedAt time.Time
    UpdatedAt time.Time
}

/posts/:idにPATCHする際、以下のようにリクエストボディをバインドします(わかりやすさのため処理をmainにまとめてます。)

import (
  "github.com/gin-gonic/gin"
)

type PostUpdateInput struct {
	Title   string `json:"title"`
	Content string `json:"content"`
}

func main() {
    r := gin.Default()
    r.PATCH("/posts/:id", func (c *gin.Context){
        params := PostUpdateInput{}
        if err := c.ShouldBindJSON(&params); err != nil {
            c.Writer.WriteHeader(500)
            return
        }
        // 以下更新処理
    })
    // 以下略
}

まず以下のような投稿があったとします。

{
  "id": "xxxx",
  "title": "Hello world!",
  "content": "Example post"
}

ここで以下のJSONを/posts/xxxxにPATCHで送って投稿を部分更新したいです。

{
  "title": "Hello Japan!"
}

しかしこの時、paramsContentフィールドはstringのゼロ値、つまり空文字なので更新処理はContentが空文字として入力されたものか初期化されたものか区別できないので、この投稿を以下のように更新してしまいます。

{
  "id": "xxxx",
  "title": "Hello Japan!",
  "content": ""
}

これをうまく処理する方法はありますか?
ご存知の方、教えていただけると幸いです。

2

2Answer

未指定か空かを判別したい場合はポインタにし、nilチェックするようにしています。

type PostUpdateInput struct {
Title *string json:"title"
Content *string json:"content"
}

1Like

Comments

  1. @reizt

    Questioner

    ありがとうございます!
    そうなると`Title`を参照するときは`*params.Title`を使うと思いますが、nilポインタを参照しないように`if params.Title != nil`みたいな条件が必要になりますかね? 毎回これをするとなるとかなり面倒なんですが、、

Your answer might help someone💌