Jackson JSON serialization support extension for JJWT (Java JWT library) providing high-performance JSON processing capabilities for JWT token handling
npx @tessl/cli install tessl/maven-io-jsonwebtoken--jjwt-jackson@0.12.0JJWT Jackson extension is an optional extension module that provides Jackson-based JSON serialization and deserialization support for the JJWT (Java JWT) library. When present in the classpath, it enables high-performance JSON processing with Jackson's proven serialization framework for JWT token handling, offering advanced features like custom serializers, deserializers, and configuration options for optimal performance in JWT token management scenarios.
io.jsonwebtoken:jjwt-jackson:0.12.6pom.xml or Gradle build.gradleMaven:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.6</version>
</dependency>Gradle:
implementation 'io.jsonwebtoken:jjwt-jackson:0.12.6'import io.jsonwebtoken.jackson.io.JacksonSerializer;
import io.jsonwebtoken.jackson.io.JacksonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.jackson.io.JacksonSerializer;
import io.jsonwebtoken.jackson.io.JacksonDeserializer;
import java.security.Key;
// Using default Jackson configuration
JacksonSerializer<Object> serializer = new JacksonSerializer<>();
JacksonDeserializer<Object> deserializer = new JacksonDeserializer<>();
// Build JWT with Jackson serialization
String jwt = Jwts.builder()
.json(serializer)
.subject("user123")
.claim("role", "admin")
.signWith(key)
.compact();
// Parse JWT with Jackson deserialization
Claims claims = Jwts.parser()
.json(deserializer)
.verifyWith(key)
.build()
.parseSignedClaims(jwt)
.getPayload();The jjwt-jackson extension consists of three main components:
The extension automatically registers a custom Jackson module (jjwt-jackson) with specialized serializers and configures the ObjectMapper with optimal settings for JWT processing.
Serializes Java objects to JSON format using Jackson for JWT token creation.
public class JacksonSerializer<T> extends io.jsonwebtoken.io.AbstractSerializer<T> {
public JacksonSerializer();
public JacksonSerializer(ObjectMapper objectMapper);
}Constructors:
JacksonSerializer() - Creates serializer with JJWT's default ObjectMapper configurationJacksonSerializer(ObjectMapper objectMapper) - Creates serializer with custom ObjectMapper instanceUsage with custom ObjectMapper:
ObjectMapper customMapper = new ObjectMapper();
// Configure custom mapper as needed
customMapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true);
JacksonSerializer<Object> serializer = new JacksonSerializer<>(customMapper);
String jwt = Jwts.builder()
.json(serializer)
.claim("customData", myObject)
.compact();Deserializes JSON to Java objects using Jackson for JWT token parsing with support for custom claim type mapping.
public class JacksonDeserializer<T> extends io.jsonwebtoken.io.AbstractDeserializer<T> {
public JacksonDeserializer();
public JacksonDeserializer(ObjectMapper objectMapper);
public JacksonDeserializer(Map<String, Class<?>> claimTypeMap);
}Constructors:
JacksonDeserializer() - Creates deserializer with JJWT's default ObjectMapper configurationJacksonDeserializer(ObjectMapper objectMapper) - Creates deserializer with custom ObjectMapper instanceJacksonDeserializer(Map<String, Class<?>> claimTypeMap) - Creates deserializer with custom claim type mapping for specific claims (creates a new ObjectMapper internally)Usage with custom claim types:
import java.util.Map;
// Define custom claim types
Map<String, Class<?>> claimTypes = Map.of(
"user", User.class,
"permissions", Permission[].class,
"metadata", Metadata.class
);
JacksonDeserializer<Object> deserializer = new JacksonDeserializer<>(claimTypes);
Claims claims = Jwts.parser()
.json(deserializer)
.verifyWith(key)
.build()
.parseSignedClaims(jwt)
.getPayload();
// Claims are now deserialized to their proper types
User user = claims.get("user", User.class);
Permission[] permissions = claims.get("permissions", Permission[].class);Usage with custom ObjectMapper:
ObjectMapper customMapper = new ObjectMapper();
customMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
JacksonDeserializer<Object> deserializer = new JacksonDeserializer<>(customMapper);
Claims claims = Jwts.parser()
.json(deserializer)
.verifyWith(key)
.build()
.parseSignedClaims(jwt)
.getPayload();The extension provides a pre-configured ObjectMapper with optimal settings for JWT processing.
// Package-protected static constants in JacksonSerializer (not part of public API)
static final String MODULE_ID = "jjwt-jackson";
static final Module MODULE; // Jackson module with custom serializers
static final ObjectMapper DEFAULT_OBJECT_MAPPER; // Pre-configured ObjectMapper
// Package-protected utility method
static ObjectMapper newObjectMapper(); // Creates new ObjectMapper with jjwt-jackson moduleDefault Configuration:
jjwt-jackson module with custom serializersJsonParser.Feature.STRICT_DUPLICATE_DETECTION (true)DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES (false)JsonGenerator.Feature.AUTO_CLOSE_TARGET (false) during serializationEnable seamless serialization and deserialization of Plain Old Java Objects (POJOs) as JWT claims.
public class User {
private String name;
private String email;
private List<String> roles;
// Constructors, getters, setters
public User() {}
public User(String name, String email, List<String> roles) {
this.name = name;
this.email = email;
this.roles = roles;
}
// getters and setters...
}
// Serialize POJO as claim
User user = new User("John Doe", "john@example.com", Arrays.asList("admin", "user"));
String jwt = Jwts.builder()
.json(new JacksonSerializer<>())
.claim("user", user)
.signWith(key)
.compact();
// Deserialize claim back to POJO
Map<String, Class<?>> claimTypes = Map.of("user", User.class);
JacksonDeserializer<Object> deserializer = new JacksonDeserializer<>(claimTypes);
Claims claims = Jwts.parser()
.json(deserializer)
.verifyWith(key)
.build()
.parseSignedClaims(jwt)
.getPayload();
User deserializedUser = claims.get("user", User.class);When jjwt-jackson is present in the classpath, JJWT automatically discovers and uses it for JSON processing without explicit configuration. This works through Java's Service Provider Interface (SPI) mechanism - the extension registers JacksonSerializer and JacksonDeserializer in META-INF/services/ files.
For fine-grained control, explicitly set serializers on JWT builders and parsers:
// JWT Creation
String jwt = Jwts.builder()
.json(new JacksonSerializer<>(customObjectMapper))
.subject("user123")
.claim("data", customObject)
.signWith(key)
.compact();
// JWT Parsing
Claims claims = Jwts.parser()
.json(new JacksonDeserializer<>(claimTypeMap))
.verifyWith(key)
.build()
.parseSignedClaims(jwt)
.getPayload();The extension also supports serialization of JSON Web Keys (JWKs):
import io.jsonwebtoken.security.Jwks;
import io.jsonwebtoken.security.Jwk;
// Create or load a JWK
Jwk<?> jwk = Jwks.builder().build();
// Serialize JWK to JSON
byte[] jsonBytes = new JacksonSerializer<>().serialize(jwk);
String jwkJson = new String(jsonBytes, StandardCharsets.UTF_8);
// Parse JWK from JSON
Jwk<?> parsed = Jwks.parser().build().parse(jwkJson);The Jackson extension integrates with JJWT's error handling and will throw appropriate JJWT exceptions:
try {
Claims claims = Jwts.parser()
.json(new JacksonDeserializer<>())
.verifyWith(key)
.build()
.parseSignedClaims(invalidJwt)
.getPayload();
} catch (MalformedJwtException e) {
// Handle malformed JWT
} catch (io.jsonwebtoken.io.DeserializationException e) {
// Handle JSON deserialization errors
}Both JacksonSerializer and JacksonDeserializer are thread-safe and can be shared across multiple threads. The underlying Jackson ObjectMapper and ObjectWriter/ObjectReader instances handle concurrent access safely.
JacksonDeserializer(Map<String, Class<?>>) provides better performance than generic Object deserialization// Key interfaces from jjwt-api (for reference)
interface io.jsonwebtoken.io.Serializer<T> {
@Deprecated
byte[] serialize(T t) throws io.jsonwebtoken.io.SerializationException;
void serialize(T t, OutputStream out) throws io.jsonwebtoken.io.SerializationException;
}
interface io.jsonwebtoken.io.Deserializer<T> {
@Deprecated
T deserialize(byte[] bytes) throws io.jsonwebtoken.io.DeserializationException;
T deserialize(Reader reader) throws io.jsonwebtoken.io.DeserializationException;
}
// Jackson types (from jackson-databind)
class com.fasterxml.jackson.databind.ObjectMapper {
// Jackson's main configuration and processing class
}
class com.fasterxml.jackson.databind.Module {
// Jackson module for extending functionality
}