go · level 2 · unit 7 · lesson 3
- meet it
- guess first
- your turn
- fix it
- nailed it
Tap a green word if you get lost.
meet it
An speaks JSON in both directions.
An API is a server that other programs talk to, usually in JSON. A shop app might send POST /basket with a JSON basket in the , and get a JSON reply back. Your handler reads one and writes the other.
Set a first, so the caller knows what is coming: w.Header().Set("Content-Type", "application/json"). Then w.WriteHeader(http.StatusCreated) can choose the status, 201 here, and json.NewEncoder(w).Encode(reply) writes JSON straight into w.
To read the request body, json.NewDecoder(r.Body).Decode(&basket) fills your value, much like Unmarshal. If it fails, or the data makes no sense, answer 400 for bad request and say why.
package main
import "encoding/json"
import "fmt"
import "net/http"
import "net/http/httptest"
import "strings"
func basket(w http.ResponseWriter, r *http.Request) {
var items map[string]int
if err := json.NewDecoder(r.Body).Decode(&items); err != nil {
http.Error(w, "bad basket", http.StatusBadRequest)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]int{"kinds": len(items)})
}
func main() {
rec := httptest.NewRecorder()
basket(rec, httptest.NewRequest("POST", "/basket", strings.NewReader(`{"tea": 2, "cake": 1}`)))
fmt.Print(rec.Code, " ", rec.Header().Get("Content-Type"), " ", rec.Body.String())
} strings.NewReader(text) turns a string into something a request body can be read from.
guess first
Spot the missing bracket. What status comes back?
Guess before you run it. Wrong guesses are how you learn, and nothing is marked.
package main
import "encoding/json"
import "fmt"
import "net/http"
import "net/http/httptest"
import "strings"
func signup(w http.ResponseWriter, r *http.Request) {
var user map[string]string
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, "that is not JSON", http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, "Welcome, %s!", user["name"])
}
func main() {
rec := httptest.NewRecorder()
signup(rec, httptest.NewRequest("POST", "/signup", strings.NewReader(`{"name": "Sam"`)))
fmt.Println(rec.Code)
}
your turn
Your turn. Run a pet API.
Add a pet of your own to the API's reply: a name and what kind of animal it is. Then read back the header that tells the caller the reply is JSON.
output
press run to see what happens
fix it
A bad order still goes out. Fix it!
output
press run to see what happens
- The status is 400, yet the reply still says the order is on its way. What happens after
http.Error? http.Errorwrites the reply, but the function carries on to the next line.- Add return on a new line straight after http.Error, inside the if block, then run.
nailed it
you built a real json api. :D
- Set
Content-Typetoapplication/jsonbefore writing JSON. Encodewrites the JSON reply, andDecodereads the request body.- Answer bad input with 400, then
returnstraight away.
new words in your collection
- API
- request body
- header
This lesson isn’t saved. A free account remembers every lesson you finish.