Implementing Content Negotiation
Server-driven negotiation: client states preferences, server picks best representation.
| Accept Value | Server Picks |
application/json | JSON |
application/xml;q=0.9, application/json | JSON (higher q) |
*/* | Default (usually JSON) |
| Unsupported type | 406 Not Acceptable |
| Direction | Header |
| Request body format | Client sets Content-Type |
| Response body format | Server sets Content-Type |
| Unsupported request type | 415 Unsupported Media Type |
@GetMapping(value = "/users/{id}",
produces = {"application/json", "application/xml", "text/csv"})
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
| Header | Server Returns |
Accept-Language: en-US | US English |
Accept-Language: es,en;q=0.8 | Spanish preferred, English fallback |
Accept-Language: * | Any language |
| Encoding | Notes |
gzip | Universal support, ~70% reduction for JSON |
br (Brotli) | Better than gzip; modern browsers, HTTPS only |
deflate | Legacy, rarely used |
identity | No compression |
6. Implementing Quality Values
| Syntax | Meaning |
q=1.0 (default) | Most preferred |
q=0.5 | Half preference |
q=0 | Not acceptable |
| Range: 0.0 to 1.0 | 3 decimal places max |
7. Returning 406 Not Acceptable
| When | Body |
| Server cannot produce any client-acceptable format | Optional: list available formats |
8. Using Default Content Type
| Scenario | Best Practice |
| Missing Accept header | Return JSON (modern default) |
Accept: */* | Return preferred format (JSON) |
| Document default in API spec | Avoid client surprises |
| Format | Example |
| Vendor-prefixed | application/vnd.example.user+json |
| Versioned | application/vnd.example.v2+json |
| HAL | application/hal+json |
| JSON:API | application/vnd.api+json |
| Problem Details | application/problem+json |
| Spec Element | OpenAPI Field |
| Request formats | requestBody.content |
| Response formats | responses.{code}.content |
| Default format | List in description |