Java 11, Spring Boot 2.5 and Jackson 2.12 here. I have the following Java classes:
// using lombok annos to generate getters & setters
@Data
public class ExamUnit implements Comparable<ExamUnit> {
private Long id;
private String name;
private String displayName;
private Long order;
private Exam exam;
// compareTo, equals & hashCode are necessary so that the TreeSet below sorts ExamUnits
// correctly, according to my needs
@Override
public int compareTo(ExamUnit other) {
if (this.equals(other)) {
return 0;
} else if (this.order < other.order) {
return 1;
}
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ExamUnit examUnit = (ExamUnit) o;
return Objects.equals(name, examUnit.name) &&
Objects.equals(displayName, examUnit.displayName) &&
Objects.equals(order, examUnit.order);
}
@Override
public int hashCode() {
return Objects.hash(name, displayName, order);
}
}
and:
@Data
public class Exam {
private Long id;
private String name;
private String displayName;
private SortedSet<ExamUnit> units = new TreeSet<>();
}
Then I have an "exam" JSON string:
{
"id": 1,
"name": "science",
"displayName": "Science Exam",
"units": [
{
"id": 1,
"name": "chemistry",
"displayName": "Chemistry Unit",
"order": 1
},
{
"id": 2,
"name": "biology",
"displayName": "Biology Unit",
"order": 2
}
]
}
This is valid JSON, as you can verify yourself. And it does appear to follow the model of the Java types correctly.
Then I have some code to read the string and deserialize it:
@Test
public void deserializeExamJson() {
String examJson = "{\n"
" \"id\": 1,\n"
" \"name\": \"science\",\n"
" \"displayName\": \"Science Exam\",\n"
" \"units\": [\n"
" {\n"
" \"id\": 1,\n"
" \"name\": \"chemistry\",\n"
" \"displayName\": \"Chemistry Unit\",\n"
" \"order\": 1\n"
" },\n"
" {\n"
" \"id\": 2,\n"
" \"name\": \"biology\",\n"
" \"displayName\": \"Biology Unit\",\n"
" \"order\": 2\n"
" }\n"
" ]\n"
"}";
Exam exam = null;
try {
exam = objectMapper.readValue(examJson, Exam.class);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
assertThat(exam.getName()).isEqualTo("science");
}
When this test runs, it fails with:
java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected VALUE_STRING: need JSON String that contains type id (for subtype of java.util.SortedSet)
at [Source: (StringReader); line: 6, column: 5] (through reference chain: com.me.myapp.Exam["units"])
CodePudding user response:
In your ExamUnit class annotate your property private Exam exam;
with @JsonIgnore