🕺

KeyがダイナミックなAPIのレスポンスをGolangでjson.Unmershalする

2023/06/17に公開

Slackに特定のカスタム絵文字が存在するか確認するGoのコードを書こうと思っていまして、emoji.listのAPIから取得することにしました。
https://api.slack.com/methods/emoji.list

ただ、こいつの成功時のレスポンスがこんな感じ

{
	"ok": true,
	"emoji": {
		"bowtie": "https:\/\/my.slack.com\/emoji\/bowtie\/46ec6f2bb0.png",
		"squirrel": "https:\/\/my.slack.com\/emoji\/squirrel\/f35f40c0e0.png",
		"shipit": "alias:squirrel",}
}

見ての通り、emoji配下のオブジェクトのKeyは、カスタム絵文字の名前になっているので、「Keyがダイナミックな場合のAPIレスポンスって、どんな構造体でUnmarshalすりゃいいんだ…?」と思って検索すると、以下のような記事が出てきました。

https://stackoverflow.com/questions/18412126/golang-parse-a-json-with-dynamic-key

なるほど、以下のような感じで、mapで表現すれば、いい感じにMappingしてくれるのね

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

type Info map[string]Person

ということで、実際のコードは以下のようになりました。

exist_custom_emoji.go
type EmojiListResponse struct {
	OK    bool              `json:"ok"`
	Emoji map[string]string `json:"emoji"`
}

func ExistCustomEmoji(emoji string) error {
	// ref. https://api.slack.com/methods/emoji.list
	endPoint := "https://slack.com/api/emoji.list"

	headers := api.Header{
		"Authorization": fmt.Sprintf("Bearer %s", os.Getenv("SLACK_BOT_TOKEN")),
	}

	// APIをキック
	emojiListJson, err := api.DoRequest("GET", endPoint, nil, nil, headers)
	if err != nil {
		return err
	}

	var emojiListResponse EmojiListResponse
	if err := json.Unmarshal([]byte(emojiListJson), &emojiListResponse); err != nil {
		return err
	}

	if _, ok := emojiListResponse.Emoji[emoji]; !ok {
		return NewNotFoundError("emoji not found")
	}

	return nil
}

めでたしめでたし。

Discussion