Implementing Content Negotiation

1. Using Accept Header

Server-driven negotiation: client states preferences, server picks best representation.

Accept ValueServer Picks
application/jsonJSON
application/xml;q=0.9, application/jsonJSON (higher q)
*/*Default (usually JSON)
Unsupported type406 Not Acceptable

2. Using Content-Type Header

DirectionHeader
Request body formatClient sets Content-Type
Response body formatServer sets Content-Type
Unsupported request type415 Unsupported Media Type

3. Implementing Multiple Response Formats

Example: Format Selection

@GetMapping(value = "/users/{id}",
  produces = {"application/json", "application/xml", "text/csv"})
public User getUser(@PathVariable Long id) {
    return userService.findById(id);
}

4. Using Accept-Language Header

HeaderServer Returns
Accept-Language: en-USUS English
Accept-Language: es,en;q=0.8Spanish preferred, English fallback
Accept-Language: *Any language

5. Using Accept-Encoding Header

EncodingNotes
gzipUniversal support, ~70% reduction for JSON
br (Brotli)Better than gzip; modern browsers, HTTPS only
deflateLegacy, rarely used
identityNo compression

6. Implementing Quality Values

SyntaxMeaning
q=1.0 (default)Most preferred
q=0.5Half preference
q=0Not acceptable
Range: 0.0 to 1.03 decimal places max

7. Returning 406 Not Acceptable

WhenBody
Server cannot produce any client-acceptable formatOptional: list available formats

8. Using Default Content Type

ScenarioBest Practice
Missing Accept headerReturn JSON (modern default)
Accept: */*Return preferred format (JSON)
Document default in API specAvoid client surprises

9. Implementing Vendor-Specific Media Types

FormatExample
Vendor-prefixedapplication/vnd.example.user+json
Versionedapplication/vnd.example.v2+json
HALapplication/hal+json
JSON:APIapplication/vnd.api+json
Problem Detailsapplication/problem+json

10. Documenting Supported Formats

Spec ElementOpenAPI Field
Request formatsrequestBody.content
Response formatsresponses.{code}.content
Default formatList in description