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.00
# JJWT Jackson Extension
1
2
JJWT 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.
3
4
## Package Information
5
6
- **Package Name**: jjwt-jackson
7
- **Package Type**: maven
8
- **Language**: Java
9
- **Maven Coordinates**: `io.jsonwebtoken:jjwt-jackson:0.12.6`
10
- **Jackson Version**: 2.12.7.1
11
- **Installation**: Add dependency to your Maven `pom.xml` or Gradle `build.gradle`
12
13
Maven:
14
```xml
15
<dependency>
16
<groupId>io.jsonwebtoken</groupId>
17
<artifactId>jjwt-jackson</artifactId>
18
<version>0.12.6</version>
19
</dependency>
20
```
21
22
Gradle:
23
```groovy
24
implementation 'io.jsonwebtoken:jjwt-jackson:0.12.6'
25
```
26
27
## Core Imports
28
29
```java
30
import io.jsonwebtoken.jackson.io.JacksonSerializer;
31
import io.jsonwebtoken.jackson.io.JacksonDeserializer;
32
import com.fasterxml.jackson.databind.ObjectMapper;
33
```
34
35
## Basic Usage
36
37
```java
38
import io.jsonwebtoken.Jwts;
39
import io.jsonwebtoken.jackson.io.JacksonSerializer;
40
import io.jsonwebtoken.jackson.io.JacksonDeserializer;
41
import java.security.Key;
42
43
// Using default Jackson configuration
44
JacksonSerializer<Object> serializer = new JacksonSerializer<>();
45
JacksonDeserializer<Object> deserializer = new JacksonDeserializer<>();
46
47
// Build JWT with Jackson serialization
48
String jwt = Jwts.builder()
49
.json(serializer)
50
.subject("user123")
51
.claim("role", "admin")
52
.signWith(key)
53
.compact();
54
55
// Parse JWT with Jackson deserialization
56
Claims claims = Jwts.parser()
57
.json(deserializer)
58
.verifyWith(key)
59
.build()
60
.parseSignedClaims(jwt)
61
.getPayload();
62
```
63
64
## Architecture
65
66
The jjwt-jackson extension consists of three main components:
67
68
- **JacksonSerializer**: Handles serialization of Java objects to JSON for JWT creation
69
- **JacksonDeserializer**: Handles deserialization of JSON to Java objects for JWT parsing
70
- **JacksonSupplierSerializer**: Internal serializer for handling Supplier objects
71
72
The extension automatically registers a custom Jackson module (`jjwt-jackson`) with specialized serializers and configures the ObjectMapper with optimal settings for JWT processing.
73
74
## Capabilities
75
76
### JSON Serialization
77
78
Serializes Java objects to JSON format using Jackson for JWT token creation.
79
80
```java { .api }
81
public class JacksonSerializer<T> extends io.jsonwebtoken.io.AbstractSerializer<T> {
82
public JacksonSerializer();
83
public JacksonSerializer(ObjectMapper objectMapper);
84
}
85
```
86
87
**Constructors:**
88
- `JacksonSerializer()` - Creates serializer with JJWT's default ObjectMapper configuration
89
- `JacksonSerializer(ObjectMapper objectMapper)` - Creates serializer with custom ObjectMapper instance
90
91
**Usage with custom ObjectMapper:**
92
```java
93
ObjectMapper customMapper = new ObjectMapper();
94
// Configure custom mapper as needed
95
customMapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true);
96
97
JacksonSerializer<Object> serializer = new JacksonSerializer<>(customMapper);
98
99
String jwt = Jwts.builder()
100
.json(serializer)
101
.claim("customData", myObject)
102
.compact();
103
```
104
105
### JSON Deserialization
106
107
Deserializes JSON to Java objects using Jackson for JWT token parsing with support for custom claim type mapping.
108
109
```java { .api }
110
public class JacksonDeserializer<T> extends io.jsonwebtoken.io.AbstractDeserializer<T> {
111
public JacksonDeserializer();
112
public JacksonDeserializer(ObjectMapper objectMapper);
113
public JacksonDeserializer(Map<String, Class<?>> claimTypeMap);
114
}
115
```
116
117
**Constructors:**
118
- `JacksonDeserializer()` - Creates deserializer with JJWT's default ObjectMapper configuration
119
- `JacksonDeserializer(ObjectMapper objectMapper)` - Creates deserializer with custom ObjectMapper instance
120
- `JacksonDeserializer(Map<String, Class<?>> claimTypeMap)` - Creates deserializer with custom claim type mapping for specific claims (creates a new ObjectMapper internally)
121
122
**Usage with custom claim types:**
123
```java
124
import java.util.Map;
125
126
// Define custom claim types
127
Map<String, Class<?>> claimTypes = Map.of(
128
"user", User.class,
129
"permissions", Permission[].class,
130
"metadata", Metadata.class
131
);
132
133
JacksonDeserializer<Object> deserializer = new JacksonDeserializer<>(claimTypes);
134
135
Claims claims = Jwts.parser()
136
.json(deserializer)
137
.verifyWith(key)
138
.build()
139
.parseSignedClaims(jwt)
140
.getPayload();
141
142
// Claims are now deserialized to their proper types
143
User user = claims.get("user", User.class);
144
Permission[] permissions = claims.get("permissions", Permission[].class);
145
```
146
147
**Usage with custom ObjectMapper:**
148
```java
149
ObjectMapper customMapper = new ObjectMapper();
150
customMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
151
152
JacksonDeserializer<Object> deserializer = new JacksonDeserializer<>(customMapper);
153
154
Claims claims = Jwts.parser()
155
.json(deserializer)
156
.verifyWith(key)
157
.build()
158
.parseSignedClaims(jwt)
159
.getPayload();
160
```
161
162
### Default ObjectMapper Configuration
163
164
The extension provides a pre-configured ObjectMapper with optimal settings for JWT processing.
165
166
```java { .api }
167
// Package-protected static constants in JacksonSerializer (not part of public API)
168
static final String MODULE_ID = "jjwt-jackson";
169
static final Module MODULE; // Jackson module with custom serializers
170
static final ObjectMapper DEFAULT_OBJECT_MAPPER; // Pre-configured ObjectMapper
171
172
// Package-protected utility method
173
static ObjectMapper newObjectMapper(); // Creates new ObjectMapper with jjwt-jackson module
174
```
175
176
**Default Configuration:**
177
- Registers `jjwt-jackson` module with custom serializers
178
- Enables `JsonParser.Feature.STRICT_DUPLICATE_DETECTION` (true)
179
- Disables `DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES` (false)
180
- Configures `JsonGenerator.Feature.AUTO_CLOSE_TARGET` (false) during serialization
181
182
### POJO Claim Support
183
184
Enable seamless serialization and deserialization of Plain Old Java Objects (POJOs) as JWT claims.
185
186
```java
187
public class User {
188
private String name;
189
private String email;
190
private List<String> roles;
191
192
// Constructors, getters, setters
193
public User() {}
194
public User(String name, String email, List<String> roles) {
195
this.name = name;
196
this.email = email;
197
this.roles = roles;
198
}
199
200
// getters and setters...
201
}
202
203
// Serialize POJO as claim
204
User user = new User("John Doe", "john@example.com", Arrays.asList("admin", "user"));
205
206
String jwt = Jwts.builder()
207
.json(new JacksonSerializer<>())
208
.claim("user", user)
209
.signWith(key)
210
.compact();
211
212
// Deserialize claim back to POJO
213
Map<String, Class<?>> claimTypes = Map.of("user", User.class);
214
JacksonDeserializer<Object> deserializer = new JacksonDeserializer<>(claimTypes);
215
216
Claims claims = Jwts.parser()
217
.json(deserializer)
218
.verifyWith(key)
219
.build()
220
.parseSignedClaims(jwt)
221
.getPayload();
222
223
User deserializedUser = claims.get("user", User.class);
224
```
225
226
## Integration with JJWT
227
228
### Automatic Discovery
229
230
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.
231
232
### Manual Configuration
233
234
For fine-grained control, explicitly set serializers on JWT builders and parsers:
235
236
```java
237
// JWT Creation
238
String jwt = Jwts.builder()
239
.json(new JacksonSerializer<>(customObjectMapper))
240
.subject("user123")
241
.claim("data", customObject)
242
.signWith(key)
243
.compact();
244
245
// JWT Parsing
246
Claims claims = Jwts.parser()
247
.json(new JacksonDeserializer<>(claimTypeMap))
248
.verifyWith(key)
249
.build()
250
.parseSignedClaims(jwt)
251
.getPayload();
252
```
253
254
### JWK Serialization
255
256
The extension also supports serialization of JSON Web Keys (JWKs):
257
258
```java
259
import io.jsonwebtoken.security.Jwks;
260
import io.jsonwebtoken.security.Jwk;
261
262
// Create or load a JWK
263
Jwk<?> jwk = Jwks.builder().build();
264
265
// Serialize JWK to JSON
266
byte[] jsonBytes = new JacksonSerializer<>().serialize(jwk);
267
String jwkJson = new String(jsonBytes, StandardCharsets.UTF_8);
268
269
// Parse JWK from JSON
270
Jwk<?> parsed = Jwks.parser().build().parse(jwkJson);
271
```
272
273
## Error Handling
274
275
The Jackson extension integrates with JJWT's error handling and will throw appropriate JJWT exceptions:
276
277
- **SerializationException** - When serialization fails
278
- **DeserializationException** - When deserialization fails
279
- **MalformedJwtException** - When JSON structure is invalid
280
281
```java
282
try {
283
Claims claims = Jwts.parser()
284
.json(new JacksonDeserializer<>())
285
.verifyWith(key)
286
.build()
287
.parseSignedClaims(invalidJwt)
288
.getPayload();
289
} catch (MalformedJwtException e) {
290
// Handle malformed JWT
291
} catch (io.jsonwebtoken.io.DeserializationException e) {
292
// Handle JSON deserialization errors
293
}
294
```
295
296
## Thread Safety
297
298
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.
299
300
## Performance Considerations
301
302
- **Reuse instances**: Create serializer/deserializer instances once and reuse them
303
- **Custom ObjectMapper**: When using a custom ObjectMapper, ensure it's properly configured for your performance requirements
304
- **Claim type mapping**: Using typed claims with `JacksonDeserializer(Map<String, Class<?>>)` provides better performance than generic Object deserialization
305
306
## Types
307
308
```java { .api }
309
// Key interfaces from jjwt-api (for reference)
310
interface io.jsonwebtoken.io.Serializer<T> {
311
@Deprecated
312
byte[] serialize(T t) throws io.jsonwebtoken.io.SerializationException;
313
void serialize(T t, OutputStream out) throws io.jsonwebtoken.io.SerializationException;
314
}
315
316
interface io.jsonwebtoken.io.Deserializer<T> {
317
@Deprecated
318
T deserialize(byte[] bytes) throws io.jsonwebtoken.io.DeserializationException;
319
T deserialize(Reader reader) throws io.jsonwebtoken.io.DeserializationException;
320
}
321
322
// Jackson types (from jackson-databind)
323
class com.fasterxml.jackson.databind.ObjectMapper {
324
// Jackson's main configuration and processing class
325
}
326
327
class com.fasterxml.jackson.databind.Module {
328
// Jackson module for extending functionality
329
}
330
```