简体   繁体   中英

Mapping a json string to an object with jackson will throw MismatchedInputException

I have a simple class

public class AuthenticationToken {

    public String token;

    public AuthenticationToken(String token) {
        this.token = token;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }
}

With jackson I am trying to map an string to this object like this

private String input = "{\"token\":\"adf\"}";


@Test
public void whenJsonString_ThenCreateAuthenticationObject() throws IOException {

    ObjectMapper jsonMapper = new ObjectMapper();
    AuthenticationToken tokenObject = jsonMapper.readValue(input, AuthenticationToken.class);
    assertThat(tokenObject).isNotNull();
}

But it throws the following exception

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `foo.AuthenticationToken` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)"{"token":"adf"}"; line: 1, column: 2]

I tried to annotate the property in my AuthenticationToken as a @JsonProperty but this also resulted in in this exception.

Annotate the class constructor with @JsonCreator

Marker annotation that can be used to define constructors and factory methods as one to use for instantiating new instances of the associated class.

public class AuthenticationToken {
    public String token;

    @JsonCreator
    public AuthenticationToken(@JsonProperty("token") final String token) {
        this.token = token;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }
}

Jackson will by default expect an " empty " constructor and will automatically fill your Object by the getters and setters that are provided for each field.

So removing the arguments of your constructor will already solve your problem:

public class AuthenticationToken {

    public String token;

    public AuthenticationToken() {}

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }
}

You could also just add an additional empty constructor if you want to keep your current one as it is. Tested both options for your Test Case, both work fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM