Disable Jackson ObjectMapper FAIL_ON_UNKNOWN_PROPERTIES Deserialization Feature
amiriahmad72 opened this issue · 1 comments
Problem
I use JacksonDeserializer
constructor with claimTypeMap
argument in order to parse the values of the claims into my custom types. After a while, I remove unnecessary filed from my custom type. After that, I got Error for all old generated valid JWTs (UnrecognizedPropertyException
).
Throwing UnrecognizedPropertyException
when json has Additional/Unknown fields is the default behavior of Jackson deserializer. So if the JWT generator service change its Claim Objects and add some fields, I got error until I add those to my custom type (even if I don't need them).
Solution
There are two solution for this problem.
- Using
@JsonIgnoreProperties(ignoreUnknown = true)
in Class level - Configure Jackson Object Mapper and disable
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
(set tofalse
).
I know the first solution solve my problem but I think the purpose of using JacksonDeserializer
constructor with claimTypeMap
argument is just to parse the values of the claims into given types (and Not Additional/Unknown fields checking).
And also Others like Spring Boot disable this feature by default
So we can change the constructor like this:
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);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
But maybe there are some people who count on this exception and use it as a validation. So we can overload the constructor like this:
public JacksonDeserializer(Map<String, Class<?>> claimTypeMap) {
this(claimTypeMap, false);
}
public JacksonDeserializer(Map<String, Class<?>> claimTypeMap, boolean failOnUnknownProperties) {
// 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);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, failOnUnknownProperties);
}
Fixed via #896