【发布时间】:2012-04-27 19:53:08
【问题描述】:
如何在 Java 中验证 JSON 字符串?或者我可以使用正则表达式解析它吗?
【问题讨论】:
-
尝试用 gson 解析?通过正则表达式验证可能不是一个好主意
-
json.org 有很多解析器的链接
标签: java json validation
如何在 Java 中验证 JSON 字符串?或者我可以使用正则表达式解析它吗?
【问题讨论】:
标签: java json validation
一个疯狂的想法,尝试解析它并捕获异常:
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 实现,可用on github、in maven 和部分on Android。
【讨论】:
杰克逊图书馆
一种选择是使用Jackson library。先导入最新版本(现在是):
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.0</version>
</dependency>
然后,您可以按如下方式实现correct answer:
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;
}
}
}
Google 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
请注意,由于尾随逗号可能存在一个“小”问题,该问题将在版本 3.0.0 中修复。
【讨论】:
new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ") 无异常解析为 IntNode(28)。没想到...
有了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 代码解析,那么使用相同的解析器来验证它。
但是仅仅解析并不一定会告诉你它是否会在其他环境中被接受。例如
如果您的验证需要非常彻底,您可以:
【讨论】:
关于解析的一点:
Json,实际上是所有语言,都使用 grammar,这是一组可以用作替换的规则。为了解析 json,您基本上需要反向解决这些替换
Json 是一种上下文无关语法,这意味着您可以拥有无限嵌套的对象/数组,并且 json 仍然有效。正则表达式仅处理正则语法(因此名称中的“reg”),它是不允许无限嵌套的上下文无关语法的子集,因此不可能仅使用正则表达式来解析所有有效的json。您可以使用一组复杂的正则表达式和循环,假设没有人会嵌套超过 100 层,但这仍然非常困难。
如果您准备编写自己的解析器
搞定语法后,你可以做一个递归下降解析器
【讨论】:
String jsonInput = "{\"mob no\":\"9846716175\"}";//Read input Here
JSONReader reader = new JSONValidatingReader();
Object result = reader.read(jsonInput);
System.out.println("Validation Success !!");
请下载stringtree-json库
【讨论】:
这是一个使用 gson 库进行严格 json 解析的工作示例:
public static JsonElement parseStrict(String json) {
// throws on almost any non-valid json
return new Gson().getAdapter(JsonElement.class).fromJson(json);
}
另请参阅我在How to check if JSON is valid in Java using GSON 中的其他详细答案,其中包含更多信息和带有各种无效示例的扩展测试用例。
【讨论】:
答案部分正确。我也面临同样的问题。解析 json 并检查异常似乎是常用的方法,但输入 json 的解决方案失败,例如
{"outputValueSchemaFormat": "","sortByIndexInRecord": 0,"sortOrder":847874874387209"descending"}kajhfsadkjh
正如你所见,json 是无效的,因为有尾随的垃圾字符。但是,如果您尝试使用 jackson 或 gson 解析上述 json,那么您将获得有效 json 的解析映射,并且垃圾尾随字符将被忽略。当您使用解析器检查 json 有效性时,这不是必需的解决方案。
有关此问题的解决方案,请参阅here。
PS:这个问题是我提出并回答的。
【讨论】:
检查给定字符串是否是 Kotlin 中的有效 JSON。我将MByDJava 的答案转换为 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.createReader(new StringReader(text)).read(),它似乎工作正常。有没有失败的情况?
read 也应该完全正常。
在这里您可以找到可以验证 JSON 文件的tool,或者您可以使用任何 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 的 JavaEE 标准之一374。
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>
访问the JSON-P official page了解更多信息。
【讨论】:
如您所见,有很多解决方案,他们主要是解析 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的quick start section。
【讨论】:
{"a": halfQuotedString"}