如何在 Java 中验证 JSON 字符串?或者我可以使用正则表达式解析它吗?
20 回答
一个疯狂的想法,尝试解析它并捕获异常:
import org.json.*;
public boolean isJSONValid(String test) {
try {
new JSONObject(test);
} catch (JSONException ex) {
// edited, to include @Arthur's comment
// e.g. in case JSONArray is valid as well...
try {
new JSONArray(test);
} catch (JSONException ex1) {
return false;
}
}
return true;
}
此代码使用org.json JSON API 实现,该实现可在 github、maven和部分Android 上获得。
杰克逊图书馆
一种选择是使用Jackson library。首先导入最新版本(现在是):
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.0</version>
</dependency>
然后,您可以按如下方式实现正确答案:
import com.fasterxml.jackson.databind.ObjectMapper;
public final class JSONUtils {
private JSONUtils(){}
public static boolean isJSONValid(String jsonInString ) {
try {
final ObjectMapper mapper = new ObjectMapper();
mapper.readTree(jsonInString);
return true;
} catch (IOException e) {
return false;
}
}
}
谷歌 GSON 选项
另一种选择是使用Google Gson。导入依赖:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.5</version>
</dependency>
同样,您可以将建议的解决方案实施为:
import com.google.gson.Gson;
public final class JSONUtils {
private static final Gson gson = new Gson();
private JSONUtils(){}
public static boolean isJSONValid(String jsonInString) {
try {
gson.fromJson(jsonInString, Object.class);
return true;
} catch(com.google.gson.JsonSyntaxException ex) {
return false;
}
}
}
下面是一个简单的测试:
//A valid JSON String to parse.
String validJsonString = "{ \"developers\": [{ \"firstName\":\"Linus\" , \"lastName\":\"Torvalds\" }, " +
"{ \"firstName\":\"John\" , \"lastName\":\"von Neumann\" } ]}";
// Invalid String with a missing parenthesis at the beginning.
String invalidJsonString = "\"developers\": [ \"firstName\":\"Linus\" , \"lastName\":\"Torvalds\" }, " +
"{ \"firstName\":\"John\" , \"lastName\":\"von Neumann\" } ]}";
boolean firstStringValid = JSONUtils.isJSONValid(validJsonString); //true
boolean secondStringValid = JSONUtils.isJSONValid(invalidJsonString); //false
请注意,由于尾随逗号可能会出现“次要”问题,这些问题将在 release 中修复3.0.0
。
使用Google Gson,您可以使用 JsonParser:
import com.google.gson.JsonParser;
JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException
您可以使用JSONUtils库中提供的.mayBeJSON(String str)。
这取决于您要通过验证来证明什么。当然,按照其他人的建议解析 json 比使用正则表达式更好,因为 json 的语法比仅用正则表达式表示的要复杂。
如果 json 只会被你的 java 代码解析,那么使用相同的解析器来验证它。
但是仅仅解析并不一定会告诉你它是否会在其他环境中被接受。例如
- 许多解析器会忽略对象或数组中的尾随逗号,但旧版本的 IE 在遇到尾随逗号时可能会失败。
- 其他解析器可能接受尾随逗号,但在其后添加未定义/空条目。
- 一些解析器可能允许不带引号的属性名称。
- 一些解析器可能对字符串中的非 ASCII 字符做出不同的反应。
如果您的验证需要非常彻底,您可以:
- 尝试不同的解析器,直到找到一个在我上面提到的所有极端情况下都失败的解析器
- 或者您可以使用 javax.script.* 运行 jsonlint,
- 或使用解析器结合使用 javax.script.* 运行 jshint。
String jsonInput = "{\"mob no\":\"9846716175\"}";//Read input Here
JSONReader reader = new JSONValidatingReader();
Object result = reader.read(jsonInput);
System.out.println("Validation Success !!");
请下载stringtree-json库
关于解析的一点:
Json,实际上是所有语言,都使用一种语法,它是一组可以用作替换的规则。为了解析 json,您基本上需要反向计算这些替换
Json 是一种上下文无关语法,这意味着您可以拥有无限嵌套的对象/数组,并且 json 仍然有效。正则表达式仅处理常规语法(因此名称中的“reg”),它是不允许无限嵌套的上下文无关语法的子集,因此不可能仅使用正则表达式来解析所有有效的 json。您可以使用一组复杂的正则表达式和循环,假设没有人会嵌套超过 100 层,但这仍然非常困难。
如果您准备编写自己的解析器
,您可以在制定语法后制作递归下降解析器
这是一个使用gson库进行严格 json 解析的工作示例:
public static JsonElement parseStrict(String json) {
// throws on almost any non-valid json
return new Gson().getAdapter(JsonElement.class).fromJson(json);
}
另请参阅如何使用 GSON 检查 JSON 在 Java 中是否有效以及更多信息和扩展测试用例以及各种无效示例中的其他详细答案。
答案部分正确。我也面临同样的问题。解析 json 并检查异常似乎是常用的方法,但输入 json 的解决方案失败,例如
{"outputValueSchemaFormat": "","sortByIndexInRecord": 0,"sortOrder":847874874387209"descending"}kajhfsadkjh
如您所见,json 无效,因为有尾随垃圾字符。但是,如果您尝试使用 jackson 或 gson 解析上述 json,那么您将获得有效 json 的解析映射,并且垃圾尾随字符将被忽略。当您使用解析器检查 json 有效性时,这不是必需的解决方案。
有关此问题的解决方案,请参见此处。
PS:这个问题是我提出并回答的。
检查给定字符串是否是Kotlin中的有效 JSON 。我将MByD Java 的答案转换为 Kotlin
fun isJSONValid(test: String): Boolean {
try {
JSONObject(test);
} catch (ex: JSONException) {
try {
JSONArray(test);
} catch (ex1: JSONException) {
return false;
}
}
return true;
}
使用该javax.json
库的解决方案:
import javax.json.*;
public boolean isTextJson(String text) {
try {
Json.createReader(new StringReader(text)).readObject();
} catch (JsonException ex) {
try {
Json.createReader(new StringReader(text)).readArray();
} catch (JsonException ex2) {
return false;
}
}
return true;
}
在这里您可以找到一个可以验证 JSON 文件的工具,或者您可以使用任何 JSON 库反序列化您的 JSON 文件,如果操作成功,那么它应该是有效的(例如google-json,如果输入将引发异常它解析的是无效的 JSON)。
使用 Playframework 2.6,java api 中的 Json 库也可以用来简单地解析字符串。该字符串可以是 json 数组的 json 元素。由于返回的值在这里并不重要,我们只需捕获解析错误以确定该字符串是否为正确的 json 字符串。
import play.libs.Json;
public static Boolean isValidJson(String value) {
try{
Json.parse(value);
return true;
} catch(final Exception e){
return false;
}
}
恕我直言,最优雅的方式是使用Java API for JSON Processing (JSON-P),这是符合JSR 374的 JavaEE 标准之一。
try(StringReader sr = new StringReader(jsonStrn)) {
Json.createReader(sr).readObject();
} catch(JsonParsingException e) {
System.out.println("The given string is not a valid json");
e.printStackTrace();
}
使用 Maven,添加对 JSON-P 的依赖:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.1.4</version>
</dependency>
访问JSON-P 官方页面了解更多信息。
正如你所看到的,有很多解决方案,他们主要是解析 JSON 来检查它,最后你必须解析它才能确定。
但是,根据具体情况,您可以通过预先检查来提高性能。
我调用 API 时所做的只是检查第一个字符是否为“{”,最后一个字符是否为“}”。如果不是这样,我不会费心创建解析器。
我找到了一个非常简单的解决方案。
请先net.sf.json-lib
为它安装这个库。
import net.sf.json.JSONException;
import net.sf.json.JSONSerializer;
private static boolean isValidJson(String jsonStr) {
boolean isValid = false;
try {
JSONSerializer.toJSON(jsonStr);
isValid = true;
} catch (JSONException je) {
isValid = false;
}
return isValid;
}
public static void testJson() {
String vjson = "{\"employees\": [{ \"firstName\":\"John\" , \"lastName\":\"Doe\" },{ \"firstName\":\"Anna\" , \"lastName\":\"Smith\" },{ \"firstName\":\"Peter\" , \"lastName\":\"Jones\" }]}";
String ivjson = "{\"employees\": [{ \"firstName\":\"John\" ,, \"lastName\":\"Doe\" },{ \"firstName\":\"Anna\" , \"lastName\":\"Smith\" },{ \"firstName\":\"Peter\" , \"lastName\":\"Jones\" }]}";
System.out.println(""+isValidJson(vjson)); // true
System.out.println(""+isValidJson(ivjson)); // false
}
完毕。享受
import static net.minidev.json.JSONValue.isValidJson;
然后调用这个函数传入你的 JSON 字符串:)
public static boolean isJSONValid(String test) {
try {
isValidJSON(test);
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createParser(test);
while (!parser.isClosed()) {
parser.nextToken();
}
} catch (Exception e) {
LOGGER.error("exception: ", e);
return false;
}
return true;
}
private static void isValidJSON(String test) {
try {
new JSONObject(test);
} catch (JSONException ex) {
try {
LOGGER.error("exception: ", ex);
new JSONArray(test);
} catch (JSONException ex1) {
LOGGER.error("exception: ", ex1);
throw new Exception("Invalid JSON.");
}
}
}
上述解决方案涵盖了两种情况:
- 重复键
- 不匹配的引号或缺少括号等。
您可以尝试下面的代码,为我工作:
import org.json.JSONObject;
import org.json.JSONTokener;
public static JSONObject parseJsonObject(String substring)
{
return new JSONObject(new JSONTokener(substring));
}
您可以使用Validol声明性验证库中的WellFormedJson
类。
声明本身可能如下所示:
new WellFormedJson(
new Unnamed<>(Either.right(new Present<>(jsonRequestString)))
)
检查阶段如下所示:
Result<JsonElement> result =
(new WellFormedJson(
new Named<>(
"vasya",
Either.right(
new Present<>(
"{\"guest\":{\"name\":\"Vadim Samokhin\",\"email\":\"samokhinvadim@gmail.com\"},\"source\":1,\"items\":[{\"id\":1900},{\"id\":777}]}"
)
)
)
))
.result();
assertTrue(result.isSuccessful());
assertEquals(
"{\"guest\":{\"name\":\"Vadim Samokhin\",\"email\":\"samokhinvadim@gmail.com\"},\"source\":1,\"items\":[{\"id\":1900},{\"id\":777}]}",
result.value().raw().toString()
);
assertEquals(
"{\"name\":\"Vadim Samokhin\",\"email\":\"samokhinvadim@gmail.com\"}",
result.value().raw().getAsJsonObject().get("guest").toString()
);
对于这样一个简单的任务来说,这似乎有点过头了,但是当您必须验证一个复杂的请求时,它就会大放异彩。查看validol 的快速入门部分。