A Retrofit Converter which uses Jackson for serialization to and from JSON
npx @tessl/cli install tessl/maven-com-squareup-retrofit2--converter-jackson@3.0.0A 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.
Package Name: converter-jackson
Package Type: maven
Language: Java
Installation:
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>converter-jackson</artifactId>
<version>3.0.0</version>
</dependency>Gradle:
implementation 'com.squareup.retrofit2:converter-jackson:3.0.0'Automatic Module Name: retrofit2.converter.jackson
import retrofit2.converter.jackson.JacksonConverterFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import okhttp3.MediaType;
import retrofit2.Retrofit;
import retrofit2.Converter;import retrofit2.Retrofit;
import retrofit2.converter.jackson.JacksonConverterFactory;
// Create Retrofit instance with Jackson converter using default ObjectMapper
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(JacksonConverterFactory.create())
.build();
// Use with custom ObjectMapper for configuration
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Retrofit retrofitCustom = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(JacksonConverterFactory.create(mapper))
.build();The Jackson converter consists of several key components:
Creates converter factory instances with various configuration options.
/**
* Create an instance using a default ObjectMapper instance for conversion.
* @return JacksonConverterFactory instance with default configuration
*/
public static JacksonConverterFactory create();
/**
* Create an instance using mapper for conversion.
* @param mapper The ObjectMapper instance to use for conversion
* @return JacksonConverterFactory instance with custom ObjectMapper
* @throws NullPointerException if mapper is null
*/
public static JacksonConverterFactory create(ObjectMapper mapper);
/**
* Create an instance using mapper and mediaType for conversion.
* @param mapper The ObjectMapper instance to use for conversion
* @param mediaType The MediaType to use for request bodies
* @return JacksonConverterFactory instance with custom configuration
* @throws NullPointerException if mapper is null
* @throws NullPointerException if mediaType is null
*/
public static JacksonConverterFactory create(ObjectMapper mapper, MediaType mediaType);Usage Examples:
// Default configuration
JacksonConverterFactory factory = JacksonConverterFactory.create();
// Custom ObjectMapper configuration
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JacksonConverterFactory customFactory = JacksonConverterFactory.create(mapper);
// Custom MediaType
MediaType customType = MediaType.get("application/vnd.api+json");
JacksonConverterFactory apiFactory = JacksonConverterFactory.create(mapper, customType);Configures streaming mode for request body serialization to optimize memory usage.
/**
* Return a new factory which streams serialization of request messages to bytes on the HTTP thread.
* This is either the calling thread for Call#execute(), or one of OkHttp's background
* threads for Call#enqueue(). Response bytes are always converted to message instances on
* one of OkHttp's background threads.
* @return JacksonConverterFactory instance with streaming enabled
*/
public JacksonConverterFactory withStreaming();Usage Example:
// Enable streaming for large request payloads
JacksonConverterFactory streamingFactory = JacksonConverterFactory
.create(customMapper)
.withStreaming();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(streamingFactory)
.build();Handles conversion of Java objects to JSON request bodies with support for both buffered and streaming serialization.
/**
* Creates converter for request body serialization.
* Converts Java objects to RequestBody instances containing JSON data.
* @param type The type being converted
* @param parameterAnnotations Parameter annotations
* @param methodAnnotations Method annotations
* @param retrofit Retrofit instance
* @return Converter instance for request body conversion
*/
@Override
public Converter<?, RequestBody> requestBodyConverter(
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations,
Retrofit retrofit);Handles conversion of JSON response bodies to Java objects.
/**
* Creates converter for response body deserialization.
* Converts ResponseBody instances containing JSON data to Java objects.
* @param type The type being converted to
* @param annotations Method annotations
* @param retrofit Retrofit instance
* @return Converter instance for response body conversion
*/
@Override
public Converter<ResponseBody, ?> responseBodyConverter(
Type type,
Annotation[] annotations,
Retrofit retrofit);The factory creates internal converter instances that handle the actual conversion work.
/**
* Internal converter for request body serialization.
* Converts Java objects to RequestBody instances containing JSON data.
*/
final class JacksonRequestBodyConverter<T> implements Converter<T, RequestBody> {
/**
* Convert a Java object to a RequestBody.
* @param value The object to convert
* @return RequestBody containing JSON representation
* @throws IOException if serialization fails
*/
public RequestBody convert(T value) throws IOException;
}
/**
* Internal converter for response body deserialization.
* Converts ResponseBody instances containing JSON data to Java objects.
*/
final class JacksonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
/**
* Convert a ResponseBody to a Java object.
* @param value The ResponseBody to convert
* @return Deserialized Java object
* @throws IOException if deserialization fails
*/
public T convert(ResponseBody value) throws IOException;
}
/**
* Internal streaming request body for memory-efficient serialization.
* Used when streaming mode is enabled via withStreaming().
*/
final class JacksonStreamingRequestBody extends RequestBody {
/**
* Get the content type for this request body.
* @return MediaType for the content
*/
public MediaType contentType();
/**
* Write the object data to the provided sink.
* @param sink The BufferedSink to write to
* @throws IOException if writing fails
*/
public void writeTo(BufferedSink sink) throws IOException;
}The converter integrates seamlessly with Retrofit service interfaces:
public interface ApiService {
@POST("users")
Call<User> createUser(@Body User user);
@GET("users/{id}")
Call<User> getUser(@Path("id") long id);
@PUT("users/{id}")
Call<User> updateUser(@Path("id") long id, @Body User user);
}
// Service usage
ApiService service = retrofit.create(ApiService.class);
User newUser = new User("John", "john@example.com");
Call<User> call = service.createUser(newUser); // Automatic JSON serializationThe converter handles various error scenarios:
ObjectMapper mapper = new ObjectMapper();
// Configure deserialization behavior
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
// Configure serialization behavior
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// Register modules for specific data types
mapper.registerModule(new JavaTimeModule());
mapper.registerModule(new Jdk8Module());
JacksonConverterFactory factory = JacksonConverterFactory.create(mapper);// Custom content types for different APIs
MediaType jsonApi = MediaType.get("application/vnd.api+json");
MediaType hal = MediaType.get("application/hal+json");
JacksonConverterFactory factory = JacksonConverterFactory.create(mapper, jsonApi);/**
* A Converter.Factory which uses Jackson for JSON serialization.
* Extends Retrofit's Converter.Factory to provide Jackson-based conversion.
*/
public final class JacksonConverterFactory extends Converter.Factory {
/**
* Default media type used for request bodies: "application/json; charset=UTF-8"
*/
private static final MediaType DEFAULT_MEDIA_TYPE =
MediaType.get("application/json; charset=UTF-8");
// Factory methods and configuration options defined above
}
/**
* Jackson ObjectMapper for JSON processing configuration
*/
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Jackson type system for handling complex generic types
*/
import com.fasterxml.jackson.databind.JavaType;
/**
* Jackson reader interface for deserialization
*/
import com.fasterxml.jackson.databind.ObjectReader;
/**
* Jackson writer interface for serialization
*/
import com.fasterxml.jackson.databind.ObjectWriter;
/**
* HTTP media type specification
*/
import okhttp3.MediaType;
/**
* Retrofit converter interface for request/response transformation
*/
import retrofit2.Converter;
/**
* Retrofit converter factory interface
*/
public abstract class Converter.Factory {
/**
* Create a converter for request body serialization.
* @param type The type being converted
* @param parameterAnnotations Parameter annotations
* @param methodAnnotations Method annotations
* @param retrofit Retrofit instance
* @return Converter instance or null if this factory cannot handle the type
*/
public Converter<?, RequestBody> requestBodyConverter(
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations,
Retrofit retrofit);
/**
* Create a converter for response body deserialization.
* @param type The type being converted to
* @param annotations Method annotations
* @param retrofit Retrofit instance
* @return Converter instance or null if this factory cannot handle the type
*/
public Converter<ResponseBody, ?> responseBodyConverter(
Type type,
Annotation[] annotations,
Retrofit retrofit);
}
/**
* HTTP request body representation
*/
import okhttp3.RequestBody;
/**
* HTTP response body representation
*/
import okhttp3.ResponseBody;
/**
* Okio buffered sink for efficient I/O operations
*/
import okio.BufferedSink;
/**
* Java reflection Type interface for generic type handling
*/
import java.lang.reflect.Type;
/**
* Java annotation interface for runtime metadata
*/
import java.lang.annotation.Annotation;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.
Custom ObjectMapper: Use a custom ObjectMapper to configure Jackson features like date handling, unknown property behavior, and custom serializers.
Streaming for Large Payloads: Use withStreaming() when dealing with large request objects to reduce memory usage.
Error Handling: Wrap Retrofit calls in try-catch blocks to handle Jackson serialization/deserialization errors appropriately.
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.