【问题标题】:Mapping a trimmed response using ObjectMapper Or wrapping the response obtained使用 ObjectMapper 映射修剪后的响应或包装获得的响应
【发布时间】:2016-08-16 12:13:14
【问题描述】:

详情---

我的一个用于 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)?

提前致谢。

【问题讨论】:

  • 根据我的理解,您的问题是将 json 数据解析为 dto 对象?
  • 如果您将 json 格式的客户端响应解析为 pojo 类,则有很多选择,其中之一是 roo..它创建并使用其 api 将其转换为:dto.toJson( ); //aspect内部代码:return new JSONSerializer().exclude("*.class").serialize(this);
  • 还有许多第三方库可用,例如:jackson org.codehaus.jackson jackson-mapper-asl>跨度>
  • howtodoinjava.com/jackson/… 是教程之一...我喜欢 spring roo 亲自为我做的东西为实体/pojo 只需添加特定的注释'@RooJson'
  • @xyz - 不是我想要的。我们一直在使用映射器。问题是将修剪后的响应映射到定义的 POJO 或包装响应以匹配 POJO。

标签: java json pojo objectmapper


【解决方案1】:

问题

您收到一个带有 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

为了避免每次都手动转换 map,写一个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);

【讨论】:

    猜你喜欢
    • 2019-06-21
    • 2016-12-31
    • 2020-09-27
    • 2019-02-12
    • 1970-01-01
    • 2018-03-28
    • 2019-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多