如何使用Sprint Rest Template解析混合子对象的json

时间:2017-01-09 18:18:35

标签: spring resttemplate

我有一个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"
      }
    }
  ]
}

数据和结果类扩展了资源。

我正在使用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没有被解析为Resource的子类。我想做一些类似RestTemplate.getForObject(url,someClass)的东西,但java泛型(通配符)不支持这种做法。请帮忙

1 个答案:

答案 0 :(得分:1)

您希望使用jackson反序列化为动态类型,使用resourceType作为字段来指示实际类型。将这些添加到您的Resource类。

@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包含你需要的所有行为,然后一切都只是一个资源