Start learning free

LESSON 24 OF 173 · BACKEND: YOUR FIRST API

Change Only the Price (PATCH)

Practice

With PUT, a client sends the whole product, even to change one number: name, price and category, including the ones that stay the same. PATCH is the method for a partial change. Its body holds only the keys to change, like {"price": 5}, and every other key keeps its value.

Go's JSON decoder helps here: Decode sets only the fields whose keys are in the body, and every other field keeps the value it already had. For example, with a struct that is not part of the shop:

type Settings struct {
	Theme string `json:"theme"`
	Size  int    `json:"size"`
}

s := Settings{Theme: "light", Size: 12}
json.NewDecoder(strings.NewReader(`{"size": 14}`)).Decode(&s)
fmt.Println(s.Theme, s.Size) // light 14

So your handler decodes the body straight into the product it found. A client may change a product's name, price and category, but never its id: other requests find the product by it. Decode would copy an "id" from the body too, so the handler sets the id back to the one from the path before it stores the product. The requests and answers your code must give, in this order:

PATCH /products/2  {"price": 5}
  →  200  {"id": 2, "name": "Notebook", "price": 5, "category": "office"}
GET /products/2  →  200  {"id": 2, "name": "Notebook", "price": 5, "category": "office"}
PATCH /products/3  {"name": "Desk lamp", "category": "office"}
  →  200  {"id": 3, "name": "Desk lamp", "price": 29, "category": "office"}
PATCH /products/1  {"id": 7, "price": 14}
  →  200  {"id": 1, "name": "Mug", "price": 14, "category": "kitchen"}
PATCH /products/4  {}
  →  200  {"id": 4, "name": "Pen", "price": 2, "category": "office"}
PATCH /products/99  {"price": 5}
  →  404  {"error": "Product not found"}
PUT /products/4  {"name": "Blue pen", "price": 3, "category": "office"}
  →  200  {"id": 4, "name": "Blue pen", "price": 3, "category": "office"}
GET /products  →  200  [{"id": 1, "name": "Mug", "price": 14, …}, {"id": 2, "name": "Notebook", "price": 5, …}, {"id": 3, "name": "Desk lamp", …}, {"id": 4, "name": "Blue pen", …}]

Your task: add a handler for PATCH /products/{id}. It finds the product with that id, decodes the body into it so only the keys sent change, keeps its id, stores it back in the slice and answers the whole product. When no product has that id, it answers 404 with {"error": "Product not found"}.


Assignment
Follow the Coding Tutorial to add the PATCH handler that changes only the keys the client sends.


Hint
The first lines are the same as in the PUT handler. Inside the if, product is a copy: decode the body into it, set its ID back to id, then store it at index i before you answer it and return.


STEP 1 OF 10
    Ctrl + Enter to check