Skip to content

Commit decd9c2

Browse files
committed
Updates Jackson usage to use immutable ObjectReader/Writer instead of ObjectMapper
Jackson 2.10+ recommend using `ObjectReader` and `ObjectWriter` as opposed to `ObjectMapper` https://cowtowncoder.medium.com/jackson-3-0-immutability-w-builders-d9c532860d88
1 parent b6f8cb8 commit decd9c2

File tree

5 files changed

+34
-17
lines changed

5 files changed

+34
-17
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
## Release Notes
22

3+
### 0.12.8 (pending release)
4+
5+
This patch release:
6+
*
7+
* Updates Jackson usage (in `jjwt-jackson`) to use immutable classes instead of using `ObjectMapper` directly.
8+
39
### 0.12.7
410

511
This patch release:
@@ -445,6 +451,7 @@ provided the JJWT team.
445451
This patch release:
446452

447453
* Adds additional handling for rare JSON parsing exceptions and wraps them in a `JwtException` to allow the application to handle these conditions as JWT concerns.
454+
* Upgrades the `jjwt-jackson` module's Jackson dependency to `2.12.4`.
448455
* Upgrades the `jjwt-jackson` module's Jackson dependency to `2.12.6.1`.
449456
* Upgrades the `jjwt-orgjson` module's org.json:json dependency to `20220320`.
450457
* Upgrades the `jjwt-gson` module's gson dependency to `2.9.0`.

extensions/jackson/src/main/java/io/jsonwebtoken/jackson/io/JacksonDeserializer.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
import com.fasterxml.jackson.core.JsonParser;
1919
import com.fasterxml.jackson.databind.DeserializationContext;
20+
import com.fasterxml.jackson.databind.Module;
2021
import com.fasterxml.jackson.databind.ObjectMapper;
22+
import com.fasterxml.jackson.databind.ObjectReader;
2123
import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;
2224
import com.fasterxml.jackson.databind.module.SimpleModule;
2325
import io.jsonwebtoken.io.AbstractDeserializer;
@@ -37,7 +39,7 @@ public class JacksonDeserializer<T> extends AbstractDeserializer<T> {
3739

3840
private final Class<T> returnType;
3941

40-
private final ObjectMapper objectMapper;
42+
private final ObjectReader objectReader;
4143

4244
/**
4345
* Constructor using JJWT's default {@link ObjectMapper} singleton for deserialization.
@@ -116,24 +118,27 @@ public JacksonDeserializer(ObjectMapper objectMapper) {
116118
* @since 0.12.4
117119
*/
118120
public JacksonDeserializer(ObjectMapper objectMapper, Map<String, Class<?>> claimTypeMap) {
119-
this(objectMapper);
120-
Assert.notNull(claimTypeMap, "Claim type map cannot be null.");
121121
// register a new Deserializer on the ObjectMapper instance:
122-
SimpleModule module = new SimpleModule();
123-
module.addDeserializer(Object.class, new MappedTypeDeserializer(Collections.unmodifiableMap(claimTypeMap)));
124-
objectMapper.registerModule(module);
122+
this(objectMapper.registerModule(mappedTypeModule(claimTypeMap)));
125123
}
126124

127125
private JacksonDeserializer(ObjectMapper objectMapper, Class<T> returnType) {
128126
Assert.notNull(objectMapper, "ObjectMapper cannot be null.");
129127
Assert.notNull(returnType, "Return type cannot be null.");
130-
this.objectMapper = objectMapper;
128+
this.objectReader = objectMapper.reader();
131129
this.returnType = returnType;
132130
}
133131

134132
@Override
135133
protected T doDeserialize(Reader reader) throws Exception {
136-
return objectMapper.readValue(reader, returnType);
134+
return objectReader.readValue(reader, returnType);
135+
}
136+
137+
private static Module mappedTypeModule(Map<String, Class<?>> claimTypeMap) {
138+
Assert.notNull(claimTypeMap, "Claim type map cannot be null.");
139+
SimpleModule module = new SimpleModule();
140+
module.addDeserializer(Object.class, new MappedTypeDeserializer(Collections.unmodifiableMap(claimTypeMap)));
141+
return module;
137142
}
138143

139144
/**

extensions/jackson/src/main/java/io/jsonwebtoken/jackson/io/JacksonSerializer.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static ObjectMapper newObjectMapper() {
6464
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // https://github.com/jwtk/jjwt/issues/893
6565
}
6666

67-
protected final ObjectMapper objectMapper;
67+
private final ObjectWriter objectWriter;
6868

6969
/**
7070
* Constructor using JJWT's default {@link ObjectMapper} singleton for serialization.
@@ -80,13 +80,15 @@ public JacksonSerializer() {
8080
*/
8181
public JacksonSerializer(ObjectMapper objectMapper) {
8282
Assert.notNull(objectMapper, "ObjectMapper cannot be null.");
83-
this.objectMapper = objectMapper.registerModule(MODULE);
83+
this.objectWriter = objectMapper
84+
.registerModule(MODULE)
85+
.writer();
8486
}
8587

8688
@Override
8789
protected void doSerialize(T t, OutputStream out) throws Exception {
8890
Assert.notNull(out, "OutputStream cannot be null.");
89-
ObjectWriter writer = this.objectMapper.writer().without(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
91+
ObjectWriter writer = this.objectWriter.without(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
9092
writer.writeValue(out, t);
9193
}
9294
}

extensions/jackson/src/test/groovy/io/jsonwebtoken/jackson/io/JacksonDeserializerTest.groovy

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ class JacksonDeserializerTest {
4545

4646
@Test
4747
void testDefaultConstructor() {
48-
assertSame JacksonSerializer.DEFAULT_OBJECT_MAPPER, deserializer.objectMapper
48+
assertSame JacksonSerializer.DEFAULT_OBJECT_MAPPER.getDeserializationConfig(), deserializer.objectReader.config
4949
}
5050

5151
@Test
5252
void testObjectMapperConstructor() {
5353
def customOM = new ObjectMapper()
5454
deserializer = new JacksonDeserializer<>(customOM)
55-
assertSame customOM, deserializer.objectMapper
55+
assertSame customOM.getDeserializationConfig(), deserializer.objectReader.config
5656
}
5757

5858
@Test(expected = IllegalArgumentException)
@@ -152,7 +152,7 @@ class JacksonDeserializerTest {
152152
*/
153153
@Test
154154
void testIgnoreUnknownPropertiesWhenDeserializeWithCustomObject() {
155-
155+
156156
long currentTime = System.currentTimeMillis()
157157

158158
String json = """

extensions/jackson/src/test/groovy/io/jsonwebtoken/jackson/io/JacksonSerializerTest.groovy

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.jsonwebtoken.jackson.io
1717

1818
import com.fasterxml.jackson.databind.ObjectMapper
19+
import com.fasterxml.jackson.databind.ObjectWriter
1920
import io.jsonwebtoken.io.Serializer
2021
import io.jsonwebtoken.lang.Strings
2122
import org.junit.Before
@@ -47,14 +48,14 @@ class JacksonSerializerTest {
4748

4849
@Test
4950
void testDefaultConstructor() {
50-
assertSame JacksonSerializer.DEFAULT_OBJECT_MAPPER, ser.objectMapper
51+
assertSame JacksonSerializer.DEFAULT_OBJECT_MAPPER.getSerializationConfig(), ser.objectWriter.config
5152
}
5253

5354
@Test
5455
void testObjectMapperConstructor() {
5556
ObjectMapper customOM = new ObjectMapper()
5657
ser = new JacksonSerializer(customOM)
57-
assertSame customOM, ser.objectMapper
58+
assertSame customOM.getSerializationConfig(), ser.objectWriter.config
5859
}
5960

6061
@Test(expected = IllegalArgumentException)
@@ -65,8 +66,10 @@ class JacksonSerializerTest {
6566
@Test
6667
void testObjectMapperConstructorAutoRegistersModule() {
6768
ObjectMapper om = createMock(ObjectMapper)
69+
ObjectWriter writer = createMock(ObjectWriter)
6870
expect(om.registerModule(same(JacksonSerializer.MODULE))).andReturn(om)
69-
replay om
71+
expect(om.writer()).andReturn(writer)
72+
replay om, writer
7073
//noinspection GroovyResultOfObjectAllocationIgnored
7174
new JacksonSerializer<>(om)
7275
verify om

0 commit comments

Comments
 (0)