go 35 lines · 4 steps

Content negotiation in Gin handlers

A single Gin handler serves the same product as JSON or XML by honoring the client's Accept header.

Explained by highlit
1package handlers
2 
3import (
4 "net/http"
5 
6 "github.com/gin-gonic/gin"
7)
8 
9type Product struct {
10 XMLName struct{} `json:"-" xml:"product"`
11 ID int `json:"id" xml:"id"`
12 Name string `json:"name" xml:"name"`
13 Price float64 `json:"price" xml:"price"`
14 Tags []string `json:"tags" xml:"tags>tag"`
15}
16 
17func GetProduct(c *gin.Context) {
18 id := c.Param("id")
19 
20 product, err := productStore.FindByID(c.Request.Context(), id)
21 if err != nil {
22 c.Negotiate(http.StatusNotFound, gin.Negotiate{
23 Offered: []string{gin.MIMEJSON, gin.MIMEXML},
24 Data: gin.H{"error": "product not found"},
25 })
26 return
27 }
28 
29 c.Negotiate(http.StatusOK, gin.Negotiate{
30 Offered: []string{gin.MIMEJSON, gin.MIMEXML},
31 Data: product,
32 JSONData: product,
33 XMLData: product,
34 })
35}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Content negotiation lets one endpoint respond in multiple formats based on the client's Accept header.
  2. 2Dual struct tags let the same Go type serialize cleanly to both JSON and XML.
  3. 3Offering a consistent format list on both success and error keeps negotiated responses uniform.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Content negotiation in Gin handlers — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code