如何使用 Sprint Rest 模板解析 json 与混合子对象

How to parse json with mixed child objects using Sprint Rest Template

我有一个 json 回复,如下所示

{
  "resourceType": "Topic",
  "metadata": {
    "lastUpdated": "2016-12-15T14:51:33.490-06:00"
  },
  "entry": [
    {
      "resource": {
        "resourceType": "Outcome",
        "issue": [
          {
            "response": "error",
            "code": "exception"
          },
          {
            "response": "success",
            "code": "informational"
          },
    {
            "response": "success",
            "code": "informational"
          }
        ]
      }
    },
    {
      "resource": {
        "resourceType": "Data",
        "id": "80",
        "subject": {
          "reference": "dataFor/80"
        },
        "created": "2016-06-23T04:29:00",
        "status": "current"
      }
    },
 {
      "resource": {
        "resourceType": "Data",
        "id": "90",
        "subject": {
          "reference": "dataFor/90"
        },
        "created": "2016-06-23T04:29:00",
        "status": "current"
      }
    }
  ]
}

数据和结果Class 扩展资源。

我正在使用 Spring RestTemplate.getForObject(url, someClass)。我遇到以下错误

has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Could not read JSON: Unrecognized field "response" (Class com.model.Resource), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@77a3e67a; 

我知道 json 没有被解析为资源的子 class。我想做类似 RestTemplate.getForObject(url, someClass) 的事情,但这不受 java 泛型(通配符)支持。请帮忙

您需要使用 jackson 反序列化为动态类型,使用 resourceType 作为字段来指示实际类型。将这些添加到您的资源 class.

@JsonTypeInfo(property = "resourceType", use = Id.NAME)
@JsonSubTypes({ @Type(Data.class), 
            @Type(Outcome.class) 
          })

这是一个单元测试,可以证明该行为。

@Test
public void deserializeJsonFromResourceIntoData () throws IOException {
   Data data = (Data) new ObjectMapper().readValue("{" +
            "        \"resourceType\": \"Data\"," +
            "        \"id\": \"80\"," +
            "        \"subject\": {" +
            "          \"reference\": \"dataFor/80\"" +
            "        }," +
            "        \"created\": \"2016-06-23T04:29:00\"," +
            "        \"status\": \"current\"" +
            "      }", Resource.class);

    assertEquals(Integer.valueOf(80), data.getId());
    assertEquals("dataFor/80", data.getSubject().getReference());
}

至于转换,我在这里只是为了证明它的工作原理,然而,要真正多态,你可能希望让 Resource 包含你需要的所有行为,然后一切都只是一个 Resource .