概述
在Java中处理原始JSON值时,有时我们需要检查其有效性。有许多库可以帮助我们:Gson,JSON API 和 Jackson。每个工具都有其独特的优点和限制。
本教程将使用每种工具实现JSON字符串验证,并详细比较它们在实践中的主要差异。
2. JSON API 验证
JSON API是最轻量级且简单的库。
通常,检查一个String
是否是有效的JSON的方法是异常处理。因此,我们委托JSON解析并在值不正确时处理特定类型的错误,或者如果没有异常发生,假设值是正确的。
2.1. Maven依赖
首先,我们需要在pom.xml
中添加json依赖:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20211205</version>
</dependency>
2.2. 使用JSONObject验证
首先,我们要尝试创建一个JSONObject
来检查String
是否为JSON。如果值无效,我们将得到一个JSONException:
:
public boolean isValid(String json) {
try {
new JSONObject(json);
} catch (JSONException e) {
return false;
}
return true;
}
让我们用一个简单例子来尝试:
String json = "{\"email\": \"example@com\", \"name\": \"John\"}";
assertTrue(validator.isValid(json));
String json = "Invalid_Json";
assertFalse(validator.isValid(json));
然而,这种方法的缺点是,使用JSONObject
,String
只能表示对象,不能表示数组。
例如,看它如何处理数组:
String json = "[{\"email\": \"example@com\", \"name\": \"John\"}]";
assertFalse(validator.isValid(json));
2.3. 使用JSONArray验证
为了无论String
是对象还是数组都能进行验证,我们需要在创建JSONObject
失败时添加额外的条件。同样,如果String
不适合作为JSON数组,JSONArray
也会抛出JSONException:
:
public boolean isValid(String json) {
try {
new JSONObject(json);
} catch (JSONException e) {
try {
new JSONArray(json);
} catch (JSONException ne) {
return false;
}
}
return true;
}
因此,我们可以验证任何值:
String json = "[{\"email\": \"example@com\", \"name\": \"John\"}]";
assertTrue(validator.isValid(json));
3. Jackson 验证
Jackson库也提供了基于异常处理的JSON验证方式。它是一个功能更强大的工具,具有多种解析策略,但使用起来更为方便。
3.1. Maven依赖
接下来,我们在项目中添加jackson-databind Maven依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
3.2. 使用ObjectMapper验证
我们使用readTree()
方法读取整个JSON,如果语法不正确,会抛出JacksonException
。
换句话说,我们不需要额外的检查。它适用于对象和数组:
ObjectMapper mapper = new ObjectMapper()
.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.build()
public boolean isValid(String json) {
try {
mapper.readTree(json);
} catch (JacksonException e) {
return false;
}
return true;
}
让我们用例子来看看如何使用:
String json = "{\"email\": \"example@com\", \"name\": \"John\"}";
assertTrue(validator.isValid(json));
String json = "[{\"email\": \"example@com\", \"name\": \"John\"}]";
assertTrue(validator.isValid(json));
String json = "Invalid_Json";
assertFalse(validator.isValid(json));
注意,我们还启用了FAIL_ON_TRAILING_TOKENS
选项,确保如果有效JSON后跟有非空白文本,验证会失败。
如果没有这个选项,形式为{“email”:”example@com”}text
的JSON仍然会被认为是有效的,尽管它不符合规范。
4. Gson 验证
Gson是另一个常用库,允许我们使用相同的方法验证原始JSON值。这是一个复杂的工具,用于Java对象与各种JSON处理方式的映射。
4.1. Maven依赖
现在添加gson Maven依赖:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
4.2. 非严格验证
Gson提供了JsonParser
将指定JSON读入一个JsonElement
树。因此,如果在读取过程中出现错误,它将保证我们收到JsonSyntaxException
。
我们可以使用parse()
方法计算String
并处理异常,以处理格式错误的JSON值:
public boolean isValid(String json) {
try {
JsonParser.parseString(json);
} catch (JsonSyntaxException e) {
return false;
}
return true;
}
让我们编写一些测试来检查主要情况:
String json = "{\"email\": \"example@com\", \"name\": \"John\"}";
assertTrue(validator.isValid(json));
String json = "[{\"email\": \"example@com\", \"name\": \"John\"}]";
assertTrue(validator.isValid(json));
这种方法的主要区别在于,Gson默认策略认为单独的字符串和数字值作为JsonElement
节点是有效的。也就是说,单个字符串或数字也被视为有效。
例如,看它是如何处理单个字符串的:
String json = "Invalid_Json";
assertTrue(validator.isValid(json));
然而,如果我们希望将此类值视为格式错误,我们需要在JsonParser
上强制执行严格的类型策略。
4.3. 严格验证
为了实现严格的类型策略,我们需要创建一个TypeAdapter
并定义JsonElement
类为所需类型匹配。结果,JsonParser
将在遇到非JSON对象或数组类型时抛出JsonSyntaxException
。
我们可以使用特定的TypeAdapter
调用fromJson()
方法来读取原始JSON:
final TypeAdapter<JsonElement> strictAdapter = new Gson().getAdapter(JsonElement.class);
public boolean isValid(String json) {
try {
strictAdapter.fromJson(json);
} catch (JsonSyntaxException | IOException e) {
return false;
}
return true;
}
最后,我们可以检查JSON是否有效:
String json = "Invalid_Json";
assertFalse(validator.isValid(json));
5. 总结
在这篇文章中,我们了解了不同的方法来检查String
是否是有效的JSON。
每个方法都有其优缺点。虽然JSON API适合于简单的对象验证,但Gson对于作为JSON对象部分的原始值验证可能更具扩展性。然而,Jackson使用起来更方便。因此,我们应该选择最适合的那一个。
此外,我们还应检查是否有现成的库已在使用,或者是否适用于其他目标。
如往常一样,示例代码可以在GitHub上找到。