javaspringjackson2jsr310jjwt

JJWT / Jackson alter the ObjectMapper used


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?


Solution

  • 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