Reputation: 6749
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
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
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
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
Reputation: 298
You need to change second example to
public TestClass(@JsonProperty("testValue") int testValue) {
this.testValue = Optional.of(testValue);
}
Upvotes: 0