mirror of https://github.com/jwtk/jjwt.git
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
This commit is contained in:
parent
9007ae7c98
commit
0c55bfce67
|
@ -5,7 +5,8 @@
|
|||
This patch release:
|
||||
|
||||
* 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.
|
||||
* Upgrades the `jjwt-jackson` module's Jackson dependency to `2.9.10.7`.
|
||||
* Upgrades the `jjwt-jackson` module's Jackson dependency to `2.12.4`.
|
||||
* Updates Jackson usage (in `jjwt-jackson`) to use immutable classes instead of using `ObjectMapper` directly.
|
||||
|
||||
### 0.11.2
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.JsonParser;
|
|||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectReader;
|
||||
import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import io.jsonwebtoken.io.DeserializationException;
|
||||
|
@ -35,7 +36,7 @@ import java.util.Map;
|
|||
public class JacksonDeserializer<T> implements Deserializer<T> {
|
||||
|
||||
private final Class<T> returnType;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final ObjectReader objectReader;
|
||||
|
||||
@SuppressWarnings("unused") //used via reflection by RuntimeClasspathDeserializerLocator
|
||||
public JacksonDeserializer() {
|
||||
|
@ -68,14 +69,7 @@ public class JacksonDeserializer<T> implements Deserializer<T> {
|
|||
* @param claimTypeMap The claim name-to-class map used to deserialize claims into the given type
|
||||
*/
|
||||
public JacksonDeserializer(Map<String, Class> claimTypeMap) {
|
||||
// DO NOT reuse JacksonSerializer.DEFAULT_OBJECT_MAPPER as this could result in sharing the custom deserializer
|
||||
// between instances
|
||||
this(new ObjectMapper());
|
||||
Assert.notNull(claimTypeMap, "Claim type map cannot be null.");
|
||||
// register a new Deserializer
|
||||
SimpleModule module = new SimpleModule();
|
||||
module.addDeserializer(Object.class, new MappedTypeDeserializer(Collections.unmodifiableMap(claimTypeMap)));
|
||||
objectMapper.registerModule(module);
|
||||
this(objectMapperWithMappedTypes(claimTypeMap));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "WeakerAccess", "unused"}) // for end-users providing a custom ObjectMapper
|
||||
|
@ -86,7 +80,7 @@ public class JacksonDeserializer<T> implements Deserializer<T> {
|
|||
private JacksonDeserializer(ObjectMapper objectMapper, Class<T> returnType) {
|
||||
Assert.notNull(objectMapper, "ObjectMapper cannot be null.");
|
||||
Assert.notNull(returnType, "Return type cannot be null.");
|
||||
this.objectMapper = objectMapper;
|
||||
this.objectReader = objectMapper.reader();
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
|
@ -101,7 +95,19 @@ public class JacksonDeserializer<T> implements Deserializer<T> {
|
|||
}
|
||||
|
||||
protected T readValue(byte[] bytes) throws IOException {
|
||||
return objectMapper.readValue(bytes, returnType);
|
||||
return objectReader.readValue(bytes, returnType);
|
||||
}
|
||||
|
||||
private static ObjectMapper objectMapperWithMappedTypes(Map<String, Class> claimTypeMap) {
|
||||
// DO NOT reuse JacksonSerializer.DEFAULT_OBJECT_MAPPER as this could result in sharing the custom deserializer
|
||||
// between instances
|
||||
Assert.notNull(claimTypeMap, "Claim type map cannot be null.");
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
// register a new Deserializer
|
||||
SimpleModule module = new SimpleModule();
|
||||
module.addDeserializer(Object.class, new MappedTypeDeserializer(Collections.unmodifiableMap(claimTypeMap)));
|
||||
objectMapper.registerModule(module);
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +128,7 @@ public class JacksonDeserializer<T> implements Deserializer<T> {
|
|||
// check if the current claim key is mapped, if so traverse it's value
|
||||
String name = parser.currentName();
|
||||
if (claimTypeMap != null && name != null && claimTypeMap.containsKey(name)) {
|
||||
Class type = claimTypeMap.get(name);
|
||||
Class<?> type = claimTypeMap.get(name);
|
||||
return parser.readValueAsTree().traverse(parser.getCodec()).readValueAs(type);
|
||||
}
|
||||
// otherwise default to super
|
||||
|
|
|
@ -17,6 +17,7 @@ package io.jsonwebtoken.jackson.io;
|
|||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
||||
import io.jsonwebtoken.io.SerializationException;
|
||||
import io.jsonwebtoken.io.Serializer;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
|
@ -28,7 +29,7 @@ public class JacksonSerializer<T> implements Serializer<T> {
|
|||
|
||||
static final ObjectMapper DEFAULT_OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
private final ObjectWriter objectWriter;
|
||||
|
||||
@SuppressWarnings("unused") //used via reflection by RuntimeClasspathDeserializerLocator
|
||||
public JacksonSerializer() {
|
||||
|
@ -38,7 +39,7 @@ public class JacksonSerializer<T> implements Serializer<T> {
|
|||
@SuppressWarnings("WeakerAccess") //intended for end-users to use when providing a custom ObjectMapper
|
||||
public JacksonSerializer(ObjectMapper objectMapper) {
|
||||
Assert.notNull(objectMapper, "ObjectMapper cannot be null.");
|
||||
this.objectMapper = objectMapper;
|
||||
this.objectWriter = objectMapper.writer();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -54,6 +55,6 @@ public class JacksonSerializer<T> implements Serializer<T> {
|
|||
|
||||
@SuppressWarnings("WeakerAccess") //for testing
|
||||
protected byte[] writeValueAsBytes(T t) throws JsonProcessingException {
|
||||
return this.objectMapper.writeValueAsBytes(t);
|
||||
return this.objectWriter.writeValueAsBytes(t);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,14 +38,14 @@ class JacksonDeserializerTest {
|
|||
@Test
|
||||
void testDefaultConstructor() {
|
||||
def deserializer = new JacksonDeserializer()
|
||||
assertNotNull deserializer.objectMapper
|
||||
assertNotNull deserializer.objectReader
|
||||
}
|
||||
|
||||
@Test
|
||||
void testObjectMapperConstructor() {
|
||||
def customOM = new ObjectMapper()
|
||||
def deserializer = new JacksonDeserializer(customOM)
|
||||
assertSame customOM, deserializer.objectMapper
|
||||
assertSame customOM.getDeserializationConfig(), deserializer.objectReader.config
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException)
|
||||
|
|
|
@ -37,14 +37,14 @@ class JacksonSerializerTest {
|
|||
@Test
|
||||
void testDefaultConstructor() {
|
||||
def serializer = new JacksonSerializer()
|
||||
assertNotNull serializer.objectMapper
|
||||
assertNotNull serializer.objectWriter
|
||||
}
|
||||
|
||||
@Test
|
||||
void testObjectMapperConstructor() {
|
||||
def customOM = new ObjectMapper()
|
||||
def serializer = new JacksonSerializer<>(customOM)
|
||||
assertSame customOM, serializer.objectMapper
|
||||
assertSame customOM.getSerializationConfig(), serializer.objectWriter.config
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException)
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -74,7 +74,7 @@
|
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<buildNumber>${user.name}-${maven.build.timestamp}</buildNumber>
|
||||
|
||||
<jackson.version>2.9.10.7</jackson.version>
|
||||
<jackson.version>2.12.4</jackson.version>
|
||||
<orgjson.version>20180130</orgjson.version>
|
||||
<gson.version>2.8.5</gson.version>
|
||||
|
||||
|
|
Loading…
Reference in New Issue