如何使用抽象 class 将 JSON 数据数组反序列化为 POJO?

How do I deserialize an array of JSON data into a POJO using an abstract class?

我正在尝试将一些 JSON 映射到 pojo 中。我已经看到如何使用实际数据中的信息来做到这一点,但就我而言,我真的没有任何东西可以识别数据有何不同,但我知道列表是由什么组成的。在下面的示例中,我可能会得到一份囚犯或建筑物的列表,但在这种情况下,我知道我得到的是一份囚犯列表。

我得到下面的JSON(我知道嵌套的数据很奇怪,但我得到的是JSON,我无法控制超过它。)

{
    "data": [{
        "data": {
            "create_date": "2015-09-30",
            "building": "12",
            "dob": "2/11/1965",
            "gender": "M",
            "location": {
                "zip": "10459"
            },
            "name": {
                "first": "James",
                "last": "Bond"

            },
            "id": "45"
        },
        "uri": "/prisoner/45"
    }, {
        "data": {
            "create_date": "2015-09-27",
            "building": "12",
            "dob": "12/15/1985",
            "gender": "M",
            "location": {
                "zip": "10459"
            },
            "name": {
                "first": "Hans",
                "last": "Gruber"

            },
            "id": "56"
        },
        "uri": "/prisoner/56"
    }],
    "totals": {
        "total": 2,
        "page": 1
    },
    "links": [{
        "uri": "/prisoners?limit=2"
    }]
}

我有一个 Data 对象,其中包含一个总计对象和一个链接对象。我还有一个包含嵌套的 Data 对象数组的 Datum 对象的集合(在本例中为列表)。 Datum 对象有一个 Thing 抽象 class 和一个 Uri 字符串。我有一个 Prisoner 和一个 Building class 扩展 Thing。在上面JSON,我知道我得到了一份囚犯名单。

我当前的代码:

ObjectMapper mapper = new ObjectMapper();
Data data = mapper.readValue(responseJSON.toString(), Data.class);

如果我进入 Datum 并将 Thing 对象更改为 Prisoner 对象,它工作得很好。我的问题是如何让它接受 PrisonerBuilding 但仍然有抽象的 Thing class 到位,或者至少让它更通用。我知道我可以制作多个 Datum classes,但我相信一定有办法拥有 1 个 Datum class。实际上,我可以获得数十种不同的数据可能性,而不仅仅是我示例中的 2 个。

您的意思是,您知道读取值时 Thing 的类型是什么?因为在那种情况下,您可以参数化 Data(即 Data<T extends Thing>),并将类型参数传播到 Datum 以指定您拥有的 Thing 的子类。然后你需要在调用 readValue 时告诉 Jackson 参数化类型,这可以像这样静态地完成:

mapper.readValue(jsonString, new TypeReference<Data<Prisoner>>(){});

这可以通过使用 ObjectMapper 中可用的 TypeFactory 构造参数化类型来动态完成。类似于:

mapper.readValue("", mapper.getTypeFactory()
                           .constructParametricType(Data.class, thingSubclass));