[Go] リクエスト内容によって、レスポンスを JSON か XML か切り替える


コード

リクエストの際に、Content-Type: application/xml の時は XML を返し、それ以外では JSON を返す方法になります。

package main

import (
    "encoding/json"
    "encoding/xml"
    "net/http"
)

type User struct {
    XMLName xml.Name `json:"-" xml:"user"`
    Name    string   `json:"name" xml:"name"`
    Age     int      `json:"age" xml:"age"`
}

func getUsers(w http.ResponseWriter, r *http.Request) {

    data := []User{
        User{Name: "田中", Age: 25},
        User{Name: "加藤", Age: 30},
    }

    if r.Header.Get("Content-Type") == "application/xml" {
        w.Header().Add("Content-Type", "application/xml")
        xm.NewEncoder(w).Encode(&data)
    } else {
        w.Header().Add("Content-Type", "application/json")
        json.NewEncoder(w).Encode(&data)
    }
}

func main() {
    http.HandleFunc("/", getUsers)
    http.ListenAndServe(":8080", nil)
}

ポイント

2 点ほど、知っておいた方が良いポイントがあります。

JSON では使わないけど、XML で使いたい要素

XML では <User> タグが表示されます。
こちらも小文字で使いたいけど、JSON で表示されないので、無視したいです。
この場合、下記のような書き方をします。

XMLName xml.Name `json:"-" xml:"user"`

のように、json:"-" とすることで、JSON 出力の場合、この要素を無視することができます。

NewEncoder vs Marshal

どちらでも同じ結果がになりますが、書く行数が少ない & 処理の早い Encoder がおススメです。

// Encoder を使うの場合
xml.NewEncoder(w).Encode(&data)

こちらが Marchal を使う場合になります。

// Marshal を使う場合
output, _ := xml.Marshal(&data)
w.Write(output)