0
# Retrofit2 Jackson Converter
1
2
A Retrofit Converter which uses Jackson for serialization to and from JSON. This converter integrates Jackson's powerful JSON processing capabilities with Retrofit's type-safe HTTP client, providing seamless JSON serialization and deserialization for HTTP request and response bodies.
3
4
## Package Information
5
6
- **Package Name**: converter-jackson
7
- **Package Type**: maven
8
- **Language**: Java
9
- **Installation**:
10
```xml
11
<dependency>
12
<groupId>com.squareup.retrofit2</groupId>
13
<artifactId>converter-jackson</artifactId>
14
<version>3.0.0</version>
15
</dependency>
16
```
17
18
Gradle:
19
```groovy
20
implementation 'com.squareup.retrofit2:converter-jackson:3.0.0'
21
```
22
23
- **Automatic Module Name**: `retrofit2.converter.jackson`
24
25
## Core Imports
26
27
```java
28
import retrofit2.converter.jackson.JacksonConverterFactory;
29
import com.fasterxml.jackson.databind.ObjectMapper;
30
import com.fasterxml.jackson.databind.DeserializationFeature;
31
import com.fasterxml.jackson.databind.SerializationFeature;
32
import okhttp3.MediaType;
33
import retrofit2.Retrofit;
34
import retrofit2.Converter;
35
```
36
37
## Basic Usage
38
39
```java
40
import retrofit2.Retrofit;
41
import retrofit2.converter.jackson.JacksonConverterFactory;
42
43
// Create Retrofit instance with Jackson converter using default ObjectMapper
44
Retrofit retrofit = new Retrofit.Builder()
45
.baseUrl("https://api.example.com/")
46
.addConverterFactory(JacksonConverterFactory.create())
47
.build();
48
49
// Use with custom ObjectMapper for configuration
50
ObjectMapper mapper = new ObjectMapper();
51
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
52
53
Retrofit retrofitCustom = new Retrofit.Builder()
54
.baseUrl("https://api.example.com/")
55
.addConverterFactory(JacksonConverterFactory.create(mapper))
56
.build();
57
```
58
59
## Architecture
60
61
The Jackson converter consists of several key components:
62
63
- **JacksonConverterFactory**: Main factory class that creates request and response converters
64
- **Request Body Conversion**: Converts Java objects to JSON for HTTP request bodies with optional streaming support
65
- **Response Body Conversion**: Converts JSON HTTP responses back to Java objects
66
- **ObjectMapper Integration**: Uses Jackson's ObjectMapper for complete control over JSON serialization behavior
67
- **Media Type Configuration**: Configurable content type for requests (defaults to application/json)
68
69
## Capabilities
70
71
### Converter Factory Creation
72
73
Creates converter factory instances with various configuration options.
74
75
```java { .api }
76
/**
77
* Create an instance using a default ObjectMapper instance for conversion.
78
* @return JacksonConverterFactory instance with default configuration
79
*/
80
public static JacksonConverterFactory create();
81
82
/**
83
* Create an instance using mapper for conversion.
84
* @param mapper The ObjectMapper instance to use for conversion
85
* @return JacksonConverterFactory instance with custom ObjectMapper
86
* @throws NullPointerException if mapper is null
87
*/
88
public static JacksonConverterFactory create(ObjectMapper mapper);
89
90
/**
91
* Create an instance using mapper and mediaType for conversion.
92
* @param mapper The ObjectMapper instance to use for conversion
93
* @param mediaType The MediaType to use for request bodies
94
* @return JacksonConverterFactory instance with custom configuration
95
* @throws NullPointerException if mapper is null
96
* @throws NullPointerException if mediaType is null
97
*/
98
public static JacksonConverterFactory create(ObjectMapper mapper, MediaType mediaType);
99
```
100
101
**Usage Examples:**
102
103
```java
104
// Default configuration
105
JacksonConverterFactory factory = JacksonConverterFactory.create();
106
107
// Custom ObjectMapper configuration
108
ObjectMapper mapper = new ObjectMapper();
109
mapper.registerModule(new JavaTimeModule());
110
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
111
JacksonConverterFactory customFactory = JacksonConverterFactory.create(mapper);
112
113
// Custom MediaType
114
MediaType customType = MediaType.get("application/vnd.api+json");
115
JacksonConverterFactory apiFactory = JacksonConverterFactory.create(mapper, customType);
116
```
117
118
### Streaming Configuration
119
120
Configures streaming mode for request body serialization to optimize memory usage.
121
122
```java { .api }
123
/**
124
* Return a new factory which streams serialization of request messages to bytes on the HTTP thread.
125
* This is either the calling thread for Call#execute(), or one of OkHttp's background
126
* threads for Call#enqueue(). Response bytes are always converted to message instances on
127
* one of OkHttp's background threads.
128
* @return JacksonConverterFactory instance with streaming enabled
129
*/
130
public JacksonConverterFactory withStreaming();
131
```
132
133
**Usage Example:**
134
135
```java
136
// Enable streaming for large request payloads
137
JacksonConverterFactory streamingFactory = JacksonConverterFactory
138
.create(customMapper)
139
.withStreaming();
140
141
Retrofit retrofit = new Retrofit.Builder()
142
.baseUrl("https://api.example.com/")
143
.addConverterFactory(streamingFactory)
144
.build();
145
```
146
147
### Request Body Conversion
148
149
Handles conversion of Java objects to JSON request bodies with support for both buffered and streaming serialization.
150
151
```java { .api }
152
/**
153
* Creates converter for request body serialization.
154
* Converts Java objects to RequestBody instances containing JSON data.
155
* @param type The type being converted
156
* @param parameterAnnotations Parameter annotations
157
* @param methodAnnotations Method annotations
158
* @param retrofit Retrofit instance
159
* @return Converter instance for request body conversion
160
*/
161
@Override
162
public Converter<?, RequestBody> requestBodyConverter(
163
Type type,
164
Annotation[] parameterAnnotations,
165
Annotation[] methodAnnotations,
166
Retrofit retrofit);
167
```
168
169
### Response Body Conversion
170
171
Handles conversion of JSON response bodies to Java objects.
172
173
```java { .api }
174
/**
175
* Creates converter for response body deserialization.
176
* Converts ResponseBody instances containing JSON data to Java objects.
177
* @param type The type being converted to
178
* @param annotations Method annotations
179
* @param retrofit Retrofit instance
180
* @return Converter instance for response body conversion
181
*/
182
@Override
183
public Converter<ResponseBody, ?> responseBodyConverter(
184
Type type,
185
Annotation[] annotations,
186
Retrofit retrofit);
187
```
188
189
### Internal Converter Classes
190
191
The factory creates internal converter instances that handle the actual conversion work.
192
193
```java { .api }
194
/**
195
* Internal converter for request body serialization.
196
* Converts Java objects to RequestBody instances containing JSON data.
197
*/
198
final class JacksonRequestBodyConverter<T> implements Converter<T, RequestBody> {
199
/**
200
* Convert a Java object to a RequestBody.
201
* @param value The object to convert
202
* @return RequestBody containing JSON representation
203
* @throws IOException if serialization fails
204
*/
205
public RequestBody convert(T value) throws IOException;
206
}
207
208
/**
209
* Internal converter for response body deserialization.
210
* Converts ResponseBody instances containing JSON data to Java objects.
211
*/
212
final class JacksonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
213
/**
214
* Convert a ResponseBody to a Java object.
215
* @param value The ResponseBody to convert
216
* @return Deserialized Java object
217
* @throws IOException if deserialization fails
218
*/
219
public T convert(ResponseBody value) throws IOException;
220
}
221
222
/**
223
* Internal streaming request body for memory-efficient serialization.
224
* Used when streaming mode is enabled via withStreaming().
225
*/
226
final class JacksonStreamingRequestBody extends RequestBody {
227
/**
228
* Get the content type for this request body.
229
* @return MediaType for the content
230
*/
231
public MediaType contentType();
232
233
/**
234
* Write the object data to the provided sink.
235
* @param sink The BufferedSink to write to
236
* @throws IOException if writing fails
237
*/
238
public void writeTo(BufferedSink sink) throws IOException;
239
}
240
```
241
242
## Integration with Retrofit Services
243
244
The converter integrates seamlessly with Retrofit service interfaces:
245
246
```java
247
public interface ApiService {
248
@POST("users")
249
Call<User> createUser(@Body User user);
250
251
@GET("users/{id}")
252
Call<User> getUser(@Path("id") long id);
253
254
@PUT("users/{id}")
255
Call<User> updateUser(@Path("id") long id, @Body User user);
256
}
257
258
// Service usage
259
ApiService service = retrofit.create(ApiService.class);
260
User newUser = new User("John", "john@example.com");
261
Call<User> call = service.createUser(newUser); // Automatic JSON serialization
262
```
263
264
## Error Handling
265
266
The converter handles various error scenarios:
267
268
- **Serialization Errors**: IOException propagated from Jackson during request body conversion
269
- **Deserialization Errors**: IOException propagated from Jackson during response body conversion
270
- **Configuration Errors**: NullPointerException for null parameters in factory methods
271
- **Resource Management**: Automatic cleanup of response body resources
272
273
## Advanced Configuration
274
275
### Custom ObjectMapper Features
276
277
```java
278
ObjectMapper mapper = new ObjectMapper();
279
280
// Configure deserialization behavior
281
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
282
mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
283
284
// Configure serialization behavior
285
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
286
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
287
288
// Register modules for specific data types
289
mapper.registerModule(new JavaTimeModule());
290
mapper.registerModule(new Jdk8Module());
291
292
JacksonConverterFactory factory = JacksonConverterFactory.create(mapper);
293
```
294
295
### Media Type Configuration
296
297
```java
298
// Custom content types for different APIs
299
MediaType jsonApi = MediaType.get("application/vnd.api+json");
300
MediaType hal = MediaType.get("application/hal+json");
301
302
JacksonConverterFactory factory = JacksonConverterFactory.create(mapper, jsonApi);
303
```
304
305
## Types
306
307
```java { .api }
308
/**
309
* A Converter.Factory which uses Jackson for JSON serialization.
310
* Extends Retrofit's Converter.Factory to provide Jackson-based conversion.
311
*/
312
public final class JacksonConverterFactory extends Converter.Factory {
313
/**
314
* Default media type used for request bodies: "application/json; charset=UTF-8"
315
*/
316
private static final MediaType DEFAULT_MEDIA_TYPE =
317
MediaType.get("application/json; charset=UTF-8");
318
319
// Factory methods and configuration options defined above
320
}
321
322
/**
323
* Jackson ObjectMapper for JSON processing configuration
324
*/
325
import com.fasterxml.jackson.databind.ObjectMapper;
326
327
/**
328
* Jackson type system for handling complex generic types
329
*/
330
import com.fasterxml.jackson.databind.JavaType;
331
332
/**
333
* Jackson reader interface for deserialization
334
*/
335
import com.fasterxml.jackson.databind.ObjectReader;
336
337
/**
338
* Jackson writer interface for serialization
339
*/
340
import com.fasterxml.jackson.databind.ObjectWriter;
341
342
/**
343
* HTTP media type specification
344
*/
345
import okhttp3.MediaType;
346
347
/**
348
* Retrofit converter interface for request/response transformation
349
*/
350
import retrofit2.Converter;
351
352
/**
353
* Retrofit converter factory interface
354
*/
355
public abstract class Converter.Factory {
356
/**
357
* Create a converter for request body serialization.
358
* @param type The type being converted
359
* @param parameterAnnotations Parameter annotations
360
* @param methodAnnotations Method annotations
361
* @param retrofit Retrofit instance
362
* @return Converter instance or null if this factory cannot handle the type
363
*/
364
public Converter<?, RequestBody> requestBodyConverter(
365
Type type,
366
Annotation[] parameterAnnotations,
367
Annotation[] methodAnnotations,
368
Retrofit retrofit);
369
370
/**
371
* Create a converter for response body deserialization.
372
* @param type The type being converted to
373
* @param annotations Method annotations
374
* @param retrofit Retrofit instance
375
* @return Converter instance or null if this factory cannot handle the type
376
*/
377
public Converter<ResponseBody, ?> responseBodyConverter(
378
Type type,
379
Annotation[] annotations,
380
Retrofit retrofit);
381
}
382
383
/**
384
* HTTP request body representation
385
*/
386
import okhttp3.RequestBody;
387
388
/**
389
* HTTP response body representation
390
*/
391
import okhttp3.ResponseBody;
392
393
/**
394
* Okio buffered sink for efficient I/O operations
395
*/
396
import okio.BufferedSink;
397
398
/**
399
* Java reflection Type interface for generic type handling
400
*/
401
import java.lang.reflect.Type;
402
403
/**
404
* Java annotation interface for runtime metadata
405
*/
406
import java.lang.annotation.Annotation;
407
```
408
409
## Best Practices
410
411
1. **Add Converter Last**: Because Jackson can handle all types, add this converter factory last in the chain to allow other converters (like protocol buffers) to handle their specific types first.
412
413
2. **Custom ObjectMapper**: Use a custom ObjectMapper to configure Jackson features like date handling, unknown property behavior, and custom serializers.
414
415
3. **Streaming for Large Payloads**: Use `withStreaming()` when dealing with large request objects to reduce memory usage.
416
417
4. **Error Handling**: Wrap Retrofit calls in try-catch blocks to handle Jackson serialization/deserialization errors appropriately.
418
419
5. **Thread Safety**: JacksonConverterFactory instances are thread-safe and can be reused across multiple Retrofit instances. The internal converters are also thread-safe as they use immutable ObjectReader and ObjectWriter instances.