Content-Type Negotiation
RestClient supports multi-format content negotiation: it automatically sets Accept and
Content-Type headers based on its configured serializer/parser registry, and selects the
right parser for each response based on the server's Content-Type reply.
See Serializer Sets and Parser Sets for the underlying registry API.
Default behavior (single-format JSON)
With no explicit configuration, RestClient uses JsonSerializer / JsonParser and sends
Accept: application/json on every request:
RestClient client = RestClient.create();
MyBean bean = client.get("/api/item/1")
.run()
.body().as(MyBean.class); // parsed with JsonParser
Configuring a multi-format client
Register multiple serializers and parsers at build time using RestClient.Builder:
SerializerSet)ParserSet)Content-Type is absent or unmatchedRestClient client = RestClient.builder()
.serializer(JsonSerializer.DEFAULT, CborSerializer.DEFAULT, YamlSerializer.DEFAULT)
.parser(JsonParser.DEFAULT, CborParser.DEFAULT, YamlParser.DEFAULT)
.defaultSerializer(JsonSerializer.DEFAULT)
.defaultParser(JsonParser.DEFAULT)
.build();
RestClient derives the Accept header automatically from all registered parsers:
Accept: application/json, application/cbor, application/yaml
How the client selects a serializer for outbound bodies
When you call RestRequest.body(Object) (or the typed body helpers), the client needs a
serializer to convert the POJO to bytes. Selection order:
- If the request carries an explicit
Content-Typeheader, the matching serializer from theSerializerSetis used. - If no explicit
Content-Typeis set, thedefaultSerializeris used (falls back toJsonSerializer.DEFAULTif none configured).
Override the format for one request by setting the Content-Type header:
client.post("/api/items")
.body(myBean)
.header("Content-Type", "application/cbor")
.run()
.assertStatus().asCode().is(201);
How the client selects a parser for inbound responses
When you call ResponseBody.as(Class), the client reads the response Content-Type header
and calls RestClient.getMatchingParser(contentType). Selection order:
- The
ParserSetis queried for a parser whose media type matches the responseContent-Type. - If no match is found,
defaultParseris used. - If
defaultParseris null, the first parser in the registry is used. - If the registry is empty,
JsonParser.DEFAULTis used as a last resort.
// Server responds with Content-Type: application/cbor
MyBean bean = client.get("/api/item/1")
.run()
.body().as(MyBean.class); // → CborParser selected automatically
Overriding the Accept header per request
Force the server to respond in a specific format by setting the Accept header on the request:
MyBean bean = client.get("/api/item/1")
.header("Accept", "application/yaml")
.run()
.body().as(MyBean.class); // parsed with YamlParser
The per-request header takes precedence over the client-wide default derived from the
ParserSet.
Using a pre-built SerializerSet / ParserSet
For fine-grained control over media-type ordering, q-factors, or reuse across clients, build the registry objects directly:
SerializerSet serializers = SerializerSet.create()
.add(JsonSerializer.DEFAULT, CborSerializer.DEFAULT)
.build();
ParserSet parsers = ParserSet.create()
.add(JsonParser.DEFAULT, CborParser.DEFAULT)
.build();
RestClient client = RestClient.builder()
.serializers(serializers)
.parsers(parsers)
.build();
See Serializer Sets and Parser Sets for the full registry API.
Quick reference: negotiation flow
| Step | What happens |
|---|---|
| Client sends request | Accept header = union of all registered parser media types |
| Client sends body | Content-Type = matched serializer's media type (explicit header wins) |
| Server replies | Content-Type response header drives parser selection in getMatchingParser() |
| Fallback | defaultParser → first registered parser → JsonParser.DEFAULT |
See also
- Serializer Sets and Parser Sets — the underlying registry API
- POJO Marshalling — per-request language shortcuts
- ResponseBody — parsing the response body (NG; see Response Content for the classic client's
ResponseContent) - Request Content — setting the request body