Jackson JSON 在反序列化集合时窒息

Jackson JSON chokes when deserializing a Collection

Java 11,Spring Boot 2.5 和 Jackson 2.12 在这里。我有以下 Java 类:

// 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);
    }
}

和:

@Data
public class Exam {

    private Long id;
    private String name;
    private String displayName;
    private SortedSet<ExamUnit> units = new TreeSet<>();

}

那我有一个“考试” 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
    }
  ]
}

这是有效的JSON,您可以自己验证。它似乎确实遵循 Java 类型的模型。

然后我有一些代码来读取字符串并将其反序列化:

@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");

}

当这个测试运行时,它失败了:

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"])

在你的 ExamUnit class 中用 @JsonIgnore

注释你的 属性 private Exam exam;