如何检查是否一个给定的字符串是有效的JSON在Java

如何在Java中验证JSON字符串?或者我可以用正则表达式解析它吗?

319897 次浏览

你可以使用JSONUtils库中可用的.mayBeJSON (String str)

一个疯狂的想法,尝试解析它并捕获异常:

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上

在这里你可以找到一个可以验证JSON文件的工具,或者你可以用任何JSON库反序列化JSON文件,如果操作成功,那么它应该是有效的(例如google-json,如果它正在解析的输入不是有效的JSON,它将抛出异常)。

String jsonInput = "{\"mob no\":\"9846716175\"}";//Read input Here
JSONReader reader = new JSONValidatingReader();
Object result = reader.read(jsonInput);
System.out.println("Validation Success !!");

请下载stringtree-json

杰克逊图书馆

一种选择是使用杰克逊图书馆。首先导入最新版本(现在是):

<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选项

另一个选项是使用谷歌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中修复。

我找到了一个非常简单的解决办法。

请先为它安装这个库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
}

完成了。享受

这取决于你想通过验证证明什么。 当然,像其他人建议的那样解析json比使用正则表达式更好,因为json的语法比仅用正则表达式表示要复杂得多

如果json只由java代码解析,那么使用相同的解析器来验证它。

但是仅仅解析并不一定能告诉您在其他环境中是否可以接受它。如。

  • 许多解析器会忽略对象或数组中的尾随逗号,但旧版本的IE会在遇到尾随逗号时失败。
  • 其他解析器可能接受尾随逗号,但在后面添加一个未定义的/null条目。
  • 一些解析器可能允许不带引号的属性名。
  • 有些解析器对字符串中的非ascii字符可能有不同的反应。

如果你的验证需要非常彻底,你可以:

谷歌Gson中,你可以使用JsonParser:

import com.google.gson.JsonParser;


JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException

答案部分正确。我也面临着同样的问题。解析json和检查异常似乎是常见的方法,但解决方案失败的输入json之类的

{"outputValueSchemaFormat": "","sortByIndexInRecord": 0,"sortOrder":847874874387209" descent "}kajhfsadkjh .

正如你所看到的,json是无效的,因为后面有垃圾字符。但是如果你尝试使用jackson或gson解析上面的json,那么你将得到有效json的解析映射,并且垃圾尾随字符被忽略。当您使用解析器检查json有效性时,这不是必需的解决方案。

这个问题的解决方法见在这里

PS:这个问题是我问过并回答过的。

关于解析:

Json,实际上所有语言都使用语法,这是一组可用于替换的规则。为了解析json,基本上需要反向计算这些替换

Json是上下文无关语法,这意味着你可以有无限嵌套的对象/数组,而Json仍然有效。regex只处理常规的语法(因此名称中的'reg'),它是上下文无关语法的子集,不允许无限嵌套,因此不可能仅使用regex来解析所有有效的json。你可以使用一组复杂的正则表达式和循环,假设没有人会嵌套超过100层,但这仍然非常困难。

< p > 如果你准备编写自己的解析器
在解决语法

之后,您可以创建一个递归下降解析器

使用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;
}
}
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.");
}
}
}

上述方案包括两种场景:

  • 复制键
  • 不匹配的引号或缺少括号等。

恕我直言,最优雅的方法是使用 JSON处理的Java API (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。我将MByD Java的答案转换为Kotlin

fun isJSONValid(test: String): Boolean {
try {
JSONObject(test);
} catch (ex: JSONException) {
try {
JSONArray(test);
} catch (ex1: JSONException) {
return false;
}
}
return true;
}

下面是一个使用gson库严格解析json的工作示例:

public static JsonElement parseStrict(String json) {
// throws on almost any non-valid json
return new Gson().getAdapter(JsonElement.class).fromJson(json);
}

也请参阅我在如何检查JSON是否在Java中使用GSON有效中的其他详细答案,其中包含更多信息和扩展的测试用例,以及各种无效的示例。

使用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;
}

你可以使用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的快速入门部分

正如你所看到的,有很多解决方案,他们主要是解析JSON来检查它,最后你必须解析它来确定。

但是,根据上下文,您可以通过预先检查来提高性能。

当我调用api时,我所做的只是检查第一个字符是“{”,最后一个字符是“}”。如果不是这样,我就不会费心创建解析器。

你可以试试下面的代码,为我工作:

 import org.json.JSONObject;
import org.json.JSONTokener;


public static JSONObject parseJsonObject(String substring)
{
return new JSONObject(new JSONTokener(substring));
}

Gson版本

try {
String errorBody = response.errorBody().string();
MyErrorResponse errorResponse = new Gson().fromJson(errorBody, MyErrorResponse.class);
} catch (JsonSyntaxException e) {
e.printStackTrace();
}