【问题标题】:How to read single JSON field with Jackson如何使用 Jackson 读取单个 JSON 字段
【发布时间】:2016-12-08 12:58:58
【问题描述】:

我有一个相当大的 JSON 响应,我对单个字段感兴趣 - status:

{
  "title": "Some title",
  "status": "pending",
  "data": {
    ...
  },
  "meta": {
    ...
  }
}

我需要做的就是将 JSON 响应的 status 值读取为字符串。我宁愿不必构建 POJO 来对其建模,因为在我的应用程序中,我只需要将 JSON 存储在特定状态的数据库中或丢弃它。

该应用程序已经将 Jackson 用于其他更复杂的情况,因此我更愿意坚持使用该库。到目前为止,我发现的所有示例都尝试将 JSON 映射到对象。

【问题讨论】:

  • "status" 是否总是响应中的第三行/第二个键值对?
  • 我刚刚发布了一个示例格式的响应。它可能来自 API 的 gzip,服务器将其解压缩,然后我可以访问它,它只是一个 Byte[] 流,我可以将其解码为 UTF8 字符串 - 除了它是有效的 JSON 之外,无法做出任何假设...

标签: java json jackson


【解决方案1】:

如果json响应不是很大,可以使用ObjectMapper.readTree将完整的json反序列化为JsonNode,并获取其中的特定属性。

例如:

ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(json);
JsonNode statusNode = jsonNode.get("status");
String statusValue = statusNode.textValue();

您还可以通过ObjectMapper.readValueother answer 中建议将完整的json 反序列化为ObjectNode

如果 json 响应很大并且反序列化完整 json 是一个问题,您可以考虑使用 Jackson Streaming API JsonParser 来解析 json。

以下是一个例子:

String statusValue = null;

JsonFactory jsonFactory = new JsonFactory();
try (JsonParser parser = jsonFactory.createParser(json)) {
    JsonToken startToken = parser.nextToken();
    while (parser.nextToken() != JsonToken.END_OBJECT) {
        String fieldName = parser.getCurrentName();
        if ("status".equals(fieldName)) {
            if (parser.nextToken() == JsonToken.VALUE_STRING) {
                statusValue = parser.getValueAsString();
                break;
            }
        } else {
            parser.skipChildren();
        }
    }
}

JsonParser 将 json 分解为一系列标记,您可以逐个迭代。在示例中,JsonParser.skipChildren 用于跳过完整的对象或数组,以便仅检查 json 层次结构的第一级。

【讨论】:

  • 感谢您的建议,赞成,我现在正在尝试这个!我接受了另一个答案,因为考虑到我的问题,它更直截了当。
  • 乐于助人。您可以尝试两种方法,找到最适合您情况的方法。
  • 问题中提出的用例不存在内存问题,因此可以使用完全反序列化的方法(通过JsonNode)。关于更大尺寸和流媒体的好点。对问题和答案+1。 :-)
  • @PNS 感谢您的评论并在您的回答中提及流式处理方法:) 我相信这可以帮助其他人在遇到类似问题时考虑不同的方法。
  • 没错。这就是拥有StackOverflow 的要点。我还主要使用 Jackson 的流式传输,而不是 POJO 或 JsonNode 方法。 :-)
【解决方案2】:

如果所需的字段是非空文本字段,则位于 JSON 对象的层次结构的“第一层”(即不是任何嵌套对象),该对象小到足以放入主内存,这是一种简单的方法检索它的值是使用类似的方法

  public static String readField(String json, String name) throws IOException {
    if (field != null) {
      ObjectNode object = new ObjectMapper().readValue(json, ObjectNode.class);
      JsonNode node = object.get(name);
      return (node == null ? null : node.textValue());
    }
    return null;
  }

ObjectNode 是一个通用的 Jackson 类,而不是 POJO。如果要使用多个值,ObjectMapper 应该被缓存(它甚至是线程安全的)。

跑步

System.out.println(readField(response, "status"));

使用上面的 JSON 响应字符串,返回

pending

正如预期的那样。在StackOverflow 中可以找到类似的解决方案elsewhere

对于非常大的 JSON 对象(例如,存储在文件中),应使用 Jackson 的流式处理方法,如其他答案中所建议的那样。

【讨论】:

    猜你喜欢
    • 2014-11-29
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 2023-03-14
    • 2012-07-25
    • 1970-01-01
    相关资源
    最近更新 更多