This time we will learn in very easy steps how to transform it into a JSON REST API
we are going to use the last piece of code from the prior tutorial as our starting point.
Go has a baked in json encoding library that makes it very easy to do this task.
All we need to do is add a new function that will return the closures to handle the request (you will need to add "encoding/json" in your imports):
func ApiHandleCategory(c Category) func (w http.ResponseWriter, r *http.Request) {
return func (w http.ResponseWriter, r *http.Request) {
j, err := json.Marshal(c)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
} else {
w.Header().Set("Content-Type", "application/json")
w.Write(j)
}
}
}
Encoding our data into json is magically done by json.Marshal function. If all goes well you will receive the json representation of the data in a byte buffer which you can write to the response writer.
Finaly we expose the REST API with the url scheme /api/{category}
For example /api/compact
for _, cat := range inventory {
http.HandleFunc("/" + cat.Title, HandleCategory(cat))
http.HandleFunc("/api/" + cat.Title, ApiHandleCategory(cat))
http.HandleFunc("/" + cat.Title, HandleCategory(cat))
http.HandleFunc("/api/" + cat.Title, ApiHandleCategory(cat))
}
We are done. we have (albeit a read only) transformed our web site into a REST API with 9 lines of code.
Here is the full code:
package main
import (
"fmt"
"net/http"
"html/template"
"os"
"encoding/json"
)
type Car struct {
Name string
Count int
}
type Category struct {
Title string
Cars []Car
}
func HandleUnknown(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound);
fmt.Fprint(w, "Hello\n")
fmt.Fprint(w, "This url does not exist")
}
func HandleCategory(c Category) func (w http.ResponseWriter, r *http.Request) {
return func (w http.ResponseWriter, r *http.Request) {
tmpl, err := template.ParseFiles("template.html")
if err != nil {
fmt.Println("error - did not load template", err);
os.Exit(-2);
}
tmpl.Execute(w, c)
}
}
func ApiHandleCategory(c Category) func (w http.ResponseWriter, r *http.Request) {
return func (w http.ResponseWriter, r *http.Request) {
j, err := json.Marshal(c)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
} else {
w.Header().Set("Content-Type", "application/json")
w.Write(j)
}
}
}
func main() {
inventory := []Category {
Category { "compact", []Car { Car { "Hyundai i30", 3 }, Car { "Volkswagen Golf", 1 }, Car { "Chevrolet Cruze", 2 } } },
Category { "saloon", []Car { Car { "Toyota Camry", 3 }, Car { "Volkswagen Passat", 1 }, Car { "Audi A6", 2 } } },
Category { "sports", []Car { Car { "Chverolet Corvette", 3 }, Car { "Ferrari F12", 1 }, Car { "Porsche 911", 2 } } },
}
for _, cat := range inventory {
http.HandleFunc("/" + cat.Title, HandleCategory(cat))
http.HandleFunc("/api/" + cat.Title, ApiHandleCategory(cat))
}
http.HandleFunc("/", HandleUnknown)
http.ListenAndServe("localhost:8080", nil)
}
import (
"fmt"
"net/http"
"html/template"
"os"
"encoding/json"
)
type Car struct {
Name string
Count int
}
type Category struct {
Title string
Cars []Car
}
func HandleUnknown(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound);
fmt.Fprint(w, "Hello\n")
fmt.Fprint(w, "This url does not exist")
}
func HandleCategory(c Category) func (w http.ResponseWriter, r *http.Request) {
return func (w http.ResponseWriter, r *http.Request) {
tmpl, err := template.ParseFiles("template.html")
if err != nil {
fmt.Println("error - did not load template", err);
os.Exit(-2);
}
tmpl.Execute(w, c)
}
}
func ApiHandleCategory(c Category) func (w http.ResponseWriter, r *http.Request) {
return func (w http.ResponseWriter, r *http.Request) {
j, err := json.Marshal(c)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
} else {
w.Header().Set("Content-Type", "application/json")
w.Write(j)
}
}
}
func main() {
inventory := []Category {
Category { "compact", []Car { Car { "Hyundai i30", 3 }, Car { "Volkswagen Golf", 1 }, Car { "Chevrolet Cruze", 2 } } },
Category { "saloon", []Car { Car { "Toyota Camry", 3 }, Car { "Volkswagen Passat", 1 }, Car { "Audi A6", 2 } } },
Category { "sports", []Car { Car { "Chverolet Corvette", 3 }, Car { "Ferrari F12", 1 }, Car { "Porsche 911", 2 } } },
}
for _, cat := range inventory {
http.HandleFunc("/" + cat.Title, HandleCategory(cat))
http.HandleFunc("/api/" + cat.Title, ApiHandleCategory(cat))
}
http.HandleFunc("/", HandleUnknown)
http.ListenAndServe("localhost:8080", nil)
}