Michael Puckett II
Michael Puckett II

Reputation: 6749

Error parsing Optional<T> with Jackson / Springboot

I have a class and would prefer to have the values Optional<T> such as Optional<Integer> value;.

In this project Springboot is used to create web controllers and the clients send / receive via json.

When the client puts or posts, and the parsing class in java has Optional<T> type parameters, it fails; otherwise it works fine. However; Optional<T> is preferred because we want to give the client the ability to omit fields if they aren't used.

For example:

This works:

public class TestClass {

    private final int testValue;

    public TestClass(@JsonProperty("testValue") int testValue) {
        this.testValue = testValue;
    }

    public int getTestValue() {
        return testValue;
    }
}

This doesn't:

public class TestClass {

    private final Optional<Integer> testValue;

    public TestClass(@JsonProperty("testValue") Optional<Integer> testValue) {
        this.testValue = testValue;
    }

    public Optional<Integer> getTestValue() {
        return testValue;
    }
}

Here are some version lines from Gradle.

springBootVersion = '1.5.8.RELEASE'

compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.6.4'
compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jdk8', version: '2.6.3' 

When POSTing with Postman and the value is an int things work. When I use Optional<Integer> I get the following error response from the web call.

Summarized:

"exception": "org.springframework.http.converter.HttpMessageNotReadableException", "message": "JSON parse error: 0; nested exception is com.fasterxml.jackson.databind.JsonMappingException: 0 (through reference chain: …(my class path)… [\"actions\"]->java.util.ArrayList[3])",

Upvotes: 0

Views: 1502

Answers (5)

Michael Puckett II
Michael Puckett II

Reputation: 6749

Without changing any existing code upgrading Jackson to version 2.8.6 fixed it.

I did follow another answer above, strangely, upgrading to a higher version of `2.9.6' did not work. It did however give me a new error message that lead me eventually to a thread where other folks also had to downgrade also.

Upvotes: 1

ksadjad
ksadjad

Reputation: 603

Optional means it is not necessarily have the object you looking for! So you can simply use a wrapper. You can return the object (if object is present) or you can return a 404 status if your object is not present.

public static <X> ResponseEntity<X> wrapOrNotFound(Optional<X> maybeResponse, HttpHeaders header) {
    return maybeResponse.map(response -> ResponseEntity.ok().headers(header).body(response))
            .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}

Upvotes: 0

Artem Karp
Artem Karp

Reputation: 19

java.util.Optional is not serializable

Upvotes: 0

Mike
Mike

Reputation: 5172

There's a Jackson module that helps serialize/deserialize Optional parameters.

<dependency>
   <groupId>com.fasterxml.jackson.datatype</groupId>
   <artifactId>jackson-datatype-jdk8</artifactId>
   <version>2.9.6</version>
</dependency>

Then register the module with your ObjectMapper:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module());

Example here: https://www.baeldung.com/jackson-optional

Upvotes: 0

muzychuk
muzychuk

Reputation: 298

You need to change second example to

public TestClass(@JsonProperty("testValue") int testValue) {
    this.testValue = Optional.of(testValue);
}

Upvotes: 0

Related Questions