Search code examples
kotlinjwt

com.auth.java-jwt - Deserializing claim with a kotlin object inside the java main object


I have a claim object that is a java object (JsonUserTokenClaims is the exemple) which as a kotlin object inside. I am trying to deserialize the object like this:

claims.get("user").as(JsonUserTokenClaims.class)

But I get this error since I added the kotlin class JsonInfo inside the main java class:

com.auth0.jwt.exceptions.JWTDecodeException: Couldn't map the Claim value to JsonUserTokenClaims

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.example.JsonInfo` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: com.example.JsonUserTokenClaims["info"])

I am running the latest version of com.auth/java-jwt

The easy solution would be to modify/change the ObjectCodec used by java-jwt, but I can't seem to find how to do that. If this solution is even possible that is.

Edit: A better view on what the classes looks like

I have seen several place where a solution could be some Lombok annotations, but I want to avoid this library if I can

JsonUserTokenClaims

    private Integer id;

    private JsonInfo info;

    public Integer getId() {

        return id;
    }

    public void setId(
        final Integer id) {

        this.id = id;
    }

    public JsonInfo getInfo() {

        return info;
    }

    public void setInfo(
        final JsonInfo info) {

        this.info = info;
    }

JsonInfo

data class JsonInfo(val id: Int, val name: String)

Solution

  • As mentioned in the comment, the issue is caused by Jackson (used internally by the JWT library) requiring a "creator" (usually, a default constructor or a constructor annotated with @JsonCreator), and the constructor coming from your data class isn't recognised out of the box. As you pointed out, you have a few options:

    1. configure the Jackson instance used by the library to deal with Kotlin’s primary constructors via the Kotlin module – I'm not familiar with this JWT library, but based on its JavaDoc it doesn't seem to let you configure the underlying Jackson mapper instance
    2. you can annotate your properties this way:
      data class JsonInfo(@JsonProperty("id") val id: Int, @JsonProperty("name") val name: String)