JJWT / Jackson alter the ObjectMapper used

hmacshakeyfor
io jsonwebtoken jjwt 0.9 0
unable to load class named (io/jsonwebtoken impl defaultjwtbuilder from the thread context)
jwtk
jjwt jwks
jwt android
kotlin jwt library

For a project I am working on, I am required to use Spring Security and JSON Webtokens as provided by the library io.jsonwebtoken (jjwt). One of the claims I am required to add to my generated token is the following entity (simplified to illustrate the problem):

@Entity
public class MyEntity {
    private String name;
    private LocalDateTime ldt;
}

This works, but the resulting webtoken is serialized as following:

{
  "sub": "testuser@mydomain.com",
  "exp": 1523659655,
  "entity": {
    "name": testname,
    "ldt": {
      "hour": 0,
      "minute": 37,
      "dayOfMonth": 12,
      "dayOfWeek": "THURSDAY",
      "dayOfYear": 102,
      "year": 2018,
      "month": "APRIL",
      "monthValue": 4,
      "second": 38,
      "nano": 569000000,
      "chronology": {
        "calendarType": "iso8601",
        "id": "ISO"
      }
    }
  }
}

This might not seem like a problem, but it is in fact a problem when later on I am required to map it to an instance of MyEntity again. After some reading online I figured that I need to change the configuration of the ObjectMapper, to change the configuration options (toggle the WRITE_DATES_AS_TIMESTAMPS-flag to false). However, I cannot alter the configuration of the ObjectMapper used by jjwt as it's constructed like this (source of jjwt):

public class DefaultJwtBuilder implements JwtBuilder {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    ...
}

Another option I found online was to put the following line in my application.properties file:

spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false

Yet to no avail, the ObjectMapper used by jjwt seems to ignore these properties.

What would I do to accomplish my goal?

Jjwt documentation states that (from version 0.10.0 and on) you can inject your own ObjectMapper with a specific compile dependency and implementing the injection as follows:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.10.5</version>
    <scope>compile</scope> <!-- Not runtime -->
</dependency>

... then add the mapper to the JwtBuilder:

ObjectMapper objectMapper = getMyObjectMapper(); //implement me
String jws = Jwts.builder()
    .serializeToJsonWith(new JacksonSerializer(objectMapper))
    // ... etc ...

as documented here

RuntimeClasspathDeserializerLocator fails when jackson is in the , jackson is being pulled transitively by some other dependency in my works, just because it sees the jackson ObjectMapper, then the Ja The locator will not be used since you manually provided your own instances and JJWT has Fixes jwtk#397 : avoid dependency side effect to affect choice of jso… After some reading online I figured that I need to change the configuration of the ObjectMapper, to change the configuration options (toggle the WRITE_DATES_AS_TIMESTAMPS-flag to false). However, I cannot alter the configuration of the ObjectMapper used by jjwt as it’s constructed like this (source of jjwt):

I fixed it by overriding the DefaultJwtBuilder, like this:

public class CustomJwtBuilder extends DefaultJwtBuilder {
    private static final ObjectMapper mapper = new Jackson2ObjectMapperBuilder()
        .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
        .modulesToInstall(new JavaTimeModule())
        .build();

    @Override
    protected byte[] toJson(Object object) throws JsonProcessingException {
        return mapper.writeValueAsBytes(object);
    }
}

And then creating the token like this

String token = new CustomJwtBuilder()
            .setSubject(..)
            .setExpiration(...)
            .compact();

Remove jackson dependency ? · Issue #309 · jwtk/jjwt · GitHub, From what I understand, jjwt only use jackson to convert json into Map should modify DefaultJwtParser to use a static ObjectMapper (like in  Jackson can be smart to transform not present values to empty Optionals instead of nulls. However, for this to work properly, you need to include the dependency jackson-datatype-jdk8 and configure the ObjectMapper registering the Jdk8Module.

Normally It happens when the compiler Unable to discover any JSON Serializer implementations on the classpath. Include the following jjwt jackson dependancy and rebuild the project. It solved my issue.

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.10.5</version>
    <scope>compile</scope>
</dependency>

com.fasterxml.jackson.databind.ObjectMapper.reader java code , Best Java code snippets using com.fasterxml.jackson.databind. @param objectMapper the ObjectMapper to use */ public origin: auth0/java-jwt configure. Method for changing state of an on/off serialization feature for this object mapper. The following method of ObjectMapper creates ObjectReader instance that can be used to update an existing Object while deserializing an incoming JSON. ObjectReader readerForUpdating(Object valueToUpdate) ObjectReader has various methods for reading an input JSON and returning the updated object. For example:

com.fasterxml.jackson.databind.ObjectMapper.<init> java code , How to use. com.fasterxml.jackson.databind.ObjectMapper. constructor. Best Java code snippets using com.fasterxml.jackson.databind. ObjectMapper mapper = new ObjectMapper(); Person user = mapper. origin: auth0/java-jwt Method for changing state of an on/off serialization feature for this object mapper. However, if you have an application-wide Jackson ObjectMapper (as is typically recommended for most applications), you can configure JJWT to use your own ObjectMapper instead. You do this by declaring the io.jsonwebtoken:jjwt-jackson dependency with compile scope (not runtime scope which is the typical JJWT default).

Jackson - ObjectMapper Class, JJWT aims to be the easiest to use and understand library for creating and verifying Custom JSON Processor; Jackson ObjectMapper However, if you want or feel the need to change JJWT's functionality or core code,  The article discusses Jackson's central ObjectMapper class, basic serialization and deserialization as well as configuring the two processes.

Jackson - Servers, Jackson - ObjectMapper Class - ObjectMapper is the main actor class of Jackson protected JsonFactory _jsonFactory - Factory used to create JsonParser and for changing state of an on/off deserialization feature for this object mapper. From what I understand, jjwt only use jackson to convert json into Map<String, Object> (object being used sometimes for Dates) and to seraialize the Map<String, object> back to json. Nothing complicated is used (like JsonIgnore, registering mapper and other tricks)

Comments
  • For those wondering how to implement the getMyObjectMapper(), this depends on how you manage dependency injection. If you're using plain old Java, a return new ObjectMapper(); would do (with desired configuration); if you're using Spring, maybe that method returns an autowired instance. That's beyond the point of this question.
  • I understand this answer was provided before JJWT 0.10.0 was released, but after 0.10.0, tete's answer on this page is the recommended solution. JJWT users should follow that one. Cheers!
  • @LesHazlewood I have accepted that answer; it was not possible yet when I originally asked the question.
  • I know, I said "I understand this answer was provided before JJWT 0.10.0 was released" :). But thanks for updating the answer! ;)