使用ObjectMapper映射修剪的响应或包装获得的响应

时间:2016-08-16 12:13:14

标签: java json pojo objectmapper

详情---

api响应的一个POJO SomeResponseObject具有属性

@JsonProperty("s_summary")
private Map<String, SummaryObject> summary 

还有更多属性。这些在json中总结如下:

{  
 "s_summary": {
    "rewardSubscription": {
      "accountId": "XYZ",
      "startDate": "2015-12-29T19:00:00+05:30",
      "endDate": "2017-06-21T00:00:00+05:30",
      "isActive": true,
      "entityId": "ID123",
      "status": "ACTIVE"
    }
  }
}

我们的服务进一步修改此POJO(json)以返回响应:

{  
  "rewardSubscription": {
    "accountId": "XYZ",
    "startDate": "2015-12-29T19:00:00+05:30",
    "endDate": "2017-06-21T00:00:00+05:30",
    "isActive": true,
    "entityId": "ID123",
    "status": "ACTIVE"
  }
}

缩小范围---

现在我们正在编写针对此API调用的测试。我们最终无法将响应映射到任何特定的POJO(java响应类)。 测试代码 -

JSONObject responseObject = new JSONObject(responseFromService.getResponseBody())
      .getJSONObject("RESPONSE");
ObjectMapper objectMapper = new ObjectMapper();
SomeResponseObject summaryResponse = objectMapper.getObjectMapper()
      .readValue(responseObject.toString(), SomeResponseObject.class); // And this wouldn't work.

问题 -

我们有什么方法可以转换当前的API响应或以某种方式将其包装以映射到实际的POJO(SomeResponseObject.class)?

提前致谢。

1 个答案:

答案 0 :(得分:3)

问题

您会收到一个包含rewardSubscription字段的对象,或者在您的情况下,会收到一个带有rewardSubscription键的地图。您无法直接将地图转换为SomeResponseObject类型的对象。

解决方案

选项1

手动将json转换为地图并将其设置为SomeResponseObject实例:

JSONObject responseObject = new JSONObject(responseFromService.getResponseBody())
      .getJSONObject("RESPONSE");

ObjectMapper objectMapper = new ObjectMapper();
Map<String, SummaryObject> summaryMap = objectMapper.readValue(responseObject.toString(), new TypeReference<Map<String, SummaryObject>>() {});
SomeResponseObject response = new SomeResponseObject();
response.setSummaryMap(summaryMap);

选项2

为了不每次都手动转换地图,请写一个custom deserializer来处理这两种情况。 deserialize方法应与此类似:

@Override
public SomeResponseObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    JsonNode rootNode = jp.readValueAsTree();

    JsonNode sSummaryNode = rootNode.get("s_summary");
    if (sSummaryNode != null) {
        // Usual case.
        return objectMapper.treeToValue(sSummaryNode, SomeResponseObject.class);
    } else {
        // Special case - when received a map.
        Map<String, SummaryObject> summaryMap = objectMapper.readValue(rootNode.toString(), new TypeReference<Map<String, SummaryObject>>() {});
        SomeResponseObject response = new SomeResponseObject();
        response.setSummaryMap(summaryMap);
        return response;
    }
}

然后在你不关心的代码中:

ObjectMapper objectMapper = new ObjectMapper();
SomeResponseObject response = objectMapper.readValue(json, SomeResponseObject.class);