1. 概述

在这个教程中,我们将学习如何检查一个JSON数组,确认特定键是否存在以及其是否具有特定值。我们将使用两个处理JSON最流行的Java库:JacksonGson

2. 设置

首先,让我们创建一个JSON数组。我们将保持简单,每个对象只有一个键值对:

String exampleJson = "[{\"color\":\"red\"},{\"color\":\"blue\"},{\"color\":\"green\"}]";

数组中的每个对象都有相同的属性color和不同的值。在示例中,我们将检查color键是否存在,且值为green

3. 使用Jackson

要在项目中使用Jackson,我们需要将其导入到pom.xml

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

最新的版本可以在Maven仓库找到。

现在让我们用它来解决问题:

@Test
void givenJsonArray_whenUsingJackson_thenDetectKeyInArray() throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    JsonNode tree = objectMapper.readTree(exampleJson);

    Stream<JsonNode> s = StreamSupport.stream(tree.spliterator(), false);
    boolean result = s.map(entry -> entry.get("color"))
      .filter(Objects::nonNull)
      .anyMatch(color -> "green".equals(color.asText()));
    assertTrue(result);
}

我们的第一步是解析JSON。为此,我们使用了*ObjectMapper*。 我们使用readTree()方法将JSON字符串转换为JsonNode

接下来,我们将JsonNode转换为一个**。我们通过StreamSupport类完成这个操作,该类包含创建和处理流的工具集合。在这里,我们使用的具体工具是stream()方法,它接受一个* Spliterator*和一个布尔标志。标志允许我们在顺序流和并行流之间进行选择。

然后,有了我们的流准备就绪后,我们依次检查每个JsonNode。这里我们需要小心。我们无法确认输入的JSON是否有名为color的键。这可能导致在将值转换为字符串进行比较时出现NullPointerException

因此,我们首先尝试获取属性,然后过滤掉任何可能由于JsonNode没有名为color的键而产生的null值。当我们确信我们有值后,就可以调用anyMatch()。我们给出了一个比较每个值与我们选择的颜色green的谓词。

anyMatch()方法如果存在匹配则返回true。因此,我们在测试结束时的断言显示,选定的color键存在一个等于green的值。

4. 使用Gson

接下来,我们将使用Gson库采用非常相似的方法。要在项目中使用Gson,我们需要将其导入到pom.xml

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

最新的版本可以在Maven仓库找到。

我们将采取同样的策略,解析JSON字符串,将其转换为流,并使用anyMatch()查找我们的值:

@Test
void givenJsonArray_whenUsingGson_thenDetectKeyInArray() {
    Gson gson = new Gson();
    JsonArray parsed = gson.fromJson(exampleJson, JsonArray.class);

    Stream<JsonElement> s = StreamSupport.stream(parsed.spliterator(), false);
    boolean result = s.map(entry -> entry.getAsJsonObject()
      .get("color"))
      .filter(Objects::nonNull)
      .anyMatch(color -> "green".equals(color.getAsString()));
    assertTrue(result);
}

首先,我们使用fromJson()方法解析字符串,这给了我们一个JsonArray。由于第二个参数,我们可以指定解析JSON的目标类类型,所以得到了JsonArray类型。

接着的步骤应该看起来很熟悉。我们像以前一样使用StreamSupport工具生成JsonElement的流。唯一的差异是,我们需要在JsonElement上调用getAsJsonObject()。这使我们能够获取与color属性关联的值,并将其与字符串进行比较。

再次看到,流中的匹配成功找到。同样,我们像之前一样警惕JSON中没有名为color的属性可能导致的NullPointerException。如果我们能更确定哪些属性将可用,我们可以直接跳到anyMatch()步骤。

5. 总结

在这篇文章中,我们了解到可以使用Jackson和Gson来检查JSON数组中选定属性是否存在且值为特定值。两种实现类似,都遵循了解析JSON、将其转换为流,然后使用流工具进行匹配的计划。一旦有了流,我们可以使用任意数量的比较方法来评估数组中的条目,从而得到一个灵活的解决方案。

如往常一样,示例的完整代码可以在GitHub上找到。