I have a problem with Jackson's deserialization mechanism in Spring Boot. My domain classes look like this:
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Post {
// ...
@ManyToOne
@JsonIncludeProperties({ "id", "course" })
private Lecture lecture;
@ManyToOne
@JsonIncludeProperties({ "id" })
private Course course;
}
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Lecture {
// ...
@JsonIgnoreProperties(value = { "lectures", "posts" }, allowSetters = true)
private Course course;
}
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Course {
// ...
@JsonIgnoreProperties(value = "course", allowSetters = true)
private Set<Lecture> lectures = new HashSet<>();
@JsonIgnoreProperties("course")
private Set<Post> posts = new HashSet<>();
}
Now to test the creation of Posts which have a Lecture set, I'm trying to test them by using the MockMvc bean. Therefore, I'm doing the following:
- creating an object of type
Post, - sending it via an HTTP POST to my
RestController, and - deserializing the JSON response back to
Post.class.
Everything works fine, but step (3) works only approx. 9/10 times (it never fails on my local setup, but only in the CI pipeline, which makes it a very hard to debug flaky test).
Post postToSave = generatePost();
postToSave.setLecture(generateLecture());
Post createdPost = request.postWithResponseBody("/api/post", postToSave, Post.class);
The error log looks like this:
com.fasterxml.jackson.databind.exc.MismatchedInputException: No _valueDeserializer assigned ... (through reference chain: a.b.c.Post["lecture"]->a.b.c.Lecture["course"])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1575)
at com.fasterxml.jackson.databind.deser.impl.FailingDeserializer.deserialize(FailingDeserializer.java:33)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:402)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:402)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3548)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3516)
I would appreciate any help on this issue.