# Read & Write JSON

Copper provides `chttp.JSONReaderWriter` that can be used to read, validate, and respond in JSON format. `chttp.JSONReaderWriter` is available by default on Routers generated by the Copper CLI.

### Read JSON

In the example below, JSON is read from the request body into the `body` variable using the `ReadJSON` method. On failure, it writes an appropriate status code & response to the response body and returns `false`.

```go
func (ro *Router) HandleRocketLaunch(w http.ResponseWriter, r *http.Request) {
    var body struct {
        RocketID string `json:"rocket_id"`
    }
    
    if ok := ro.rw.ReadJSON(w, r, &body); !ok {
        return
    }
    
    // Handle request with body..
}
```

### Validate Request Body

The `ReadJSON` method integrates with `asaskevich/govalidator` to validate the request body. If the validation fails, the method responds with `400 Bad Request` status code.

```go
var body struct {
    RocketID string `json:"rocket_id" valid:"required`
}
```

### Write JSON

The `WriteJSON` method handles marshaling, error checking, and setting the `Content-Type: application/json` header.

Below is a full example of reading a validated request body, calling the business logic layer, handling errors, and finally writing an HTTP response.

```go
func (ro *Router) HandleRocketLaunch(w http.ResponseWriter, r *http.Request) {    
    var body struct {
        RocketID string `json:"rocket_id" valid:"required"`
    }
    
    if ok := ro.rw.ReadJSON(w, r, &body); !ok {
        return
    }
    
    launchID, err := ro.rockets.Launch(r.Context(), body.RocketID)
    if err != nil {
        ro.logger.Error("Failed to launch rocket", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    ro.rw.WriteJSON(w, chttp.WriteJSONParams{
        StatusCode: http.StatusCreated,
        Data: map[string]string{
            "launch_id": launchID,
        },
    })
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gocopper.gitbook.io/copper/http/read-and-write-json.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
