1. 概述
在这个教程中,我们将学习如何检查一个JSON数组,确认特定键是否存在以及其是否具有特定值。我们将使用两个处理JSON最流行的Java库:Jackson和Gson。
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上找到。