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


Answers:


261

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

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实现,该实现在githubmaven和部分Android上可用。


2
它很接近,但是缺少对JSONArray的验证(我已使用更合适的功能更新了该帖子)
Arthur

9
我已经尝试过像“ {'hello':'foo'}'invalid'”这样的json字符串(在{}之外添加了'invalid'),并且JSONObject不会引发ParseException。我正在使用org.json.JSONObject。这是预期的吗?
林一千(Soichi Hayashi)2014年

16
您没有提到具有JSONObject的库,我没有在标准Java库中看到它
KrzysztofKrasoń15年

6
该解决方案适用于大多数情况,但在某些情况下可能会失败。例如,它允许逗号在右花括号前,这实际上是语法错误。有关其他特殊情况,请参考json.org/javadoc/org/json/JSONObject.html
Hua2308

9
我不明白为什么海报不能麻烦地包含带有代码片段的导入语句。在这里很重要。这里的第二个答案好得多。
seansand '17

100

杰克逊图书馆

一种选择是使用Jackson库。首先导入最新版本(现在是):

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

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

请注意,由于尾随逗号会在release中修复,因此可能存在“次要”问题3.0.0


虽然这适用于不匹配的引号或缺少括号的大事,但Gson会很乐意用尾随逗号来解析json数组,这不符合RFC-4627
eurythmia 2014年

@eurythmia真的!在3.0版中,他们应该解决此问题
JeanValjean 2016年

1
这也可以验证{key:value},但是它不是有效的json
Pratapi Hemant Patel 2016年

2
杰克逊陷阱:new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")无异常地解析为IntNode(28)。没料到……
mgaert

1
据我了解,此解决方案不仅可以验证,而且可以解析(并存储)整个json。它将数字转换为Integer / Long / Double等。这不仅是语法检查,它还将整个json存储在内存中。这对于密集负载可能很重要。是否存在更好的语法检查解决方案?
javapowered

15

使用Google Gson,您可以使用JsonParser:

import com.google.gson.JsonParser;

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

3
请注意,这并不对加括号的字符串抛出一个错误ALA“ASDF”
安德鲁

1
它也不拒绝JSON数组中的结尾逗号。
Sotirios Delimanolis

我对此实在不敢相信……它说字符串“ Save”是可解析的。
Dherik '17

请注意,这里的gson示例使用宽大的解析模式,该模式仍然允许许多偏差。在我的其他答案中,请参见有关测试用例严格解析示例的更多详细信息
Vadzim

14

您可以使用.mayBeJSON(字符串str)可供JSONUtils库。


是的...这正在工作。感谢npinti。我正在尝试使用gson,但没有看到这样的方法。
sappu 2012年

@sappu:如果此答案解决了您的问题,请标记为。大多数库都倾向于使用String并尝试对其进行解析,如果解析失败,即该字符串不是有效的JSON字符串,它将抛出异常。
npinti 2012年

@npinti:未能获得额外的}。对于带多余括号的无效字符串,返回true =>}
Vivek 2014年

3
此方法从字面上仅检查字符串是否以引号或括号开头和结尾。非常不可靠。
Michael Munsey

2
这就是方法名称为“也许”而不是“是”的原因:)
Khoa

5

这取决于您要通过验证证明的内容。当然,按照其他人的建议解析json比使用正则表达式更好,因为json的语法比仅用正则表达式所代表的语法更复杂。

如果只能通过Java代码解析json,请使用相同的解析器进行验证。

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

  • 许多解析器会忽略对象或数组中的尾部逗号,但是旧版本的IE遇到尾部逗号时可能会失败。
  • 其他解析器可以接受结尾的逗号,但在其后添加未定义/空条目。
  • 某些解析器可能允许使用不带引号的属性名称。
  • 某些解析器对字符串中的非ASCII字符可能会有不同的反应。

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


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

请下载stringtree-json


是否可以像上面那样定义一个String?或仅用于创意。
Santron Manibharathi 2014年

不可能,那是由于我的错误。现在已纠正
谢谢

1
JSONValidatingReader不是Java API的一部分
IgorGanapolsky

请使用上述图书馆,谢谢
Jamsheer '17

2

关于解析的一点:

Json,实际上是所有语言,都使用语法,该语法是可以用作替代的一组规则。为了解析json,您需要从根本上解决这些替换问题

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

如果您愿意编写自己的解析器
,则可以在编制语法后制作递归下降解析器


2

检查给定的字符串在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;
}

1

在这里,您可以找到可以验证JSON文件的工具,也可以使用任何JSON库反序列化JSON文件,如果操作成功,则该文件应有效(例如google-json,如果输入内容会抛出异常解析无效的JSON)。


1

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

1

恕我直言,最优雅的方法是使用Java API进行JSON处理(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官方页面以获取更多信息。



1

如您所见,有很多解决方案,它们主要解析JSON以对其进行检查,最后您必须对其进行解析才能确定。

但是,根据具体情况,您可以通过预检查来提高性能。

当我调用API时,我所做的只是检查第一个字符为'{',最后一个字符为'}'。如果不是这种情况,我就不用创建解析器了。


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
    }

做完了 请享用


0

答案部分正确。我也面临同样的问题。解析json并检查异常似乎是通常的方法,但是对于输入的json解决方案失败,例如

{“ outputValueSchemaFormat”:“”,“ sortByIndexInRecord”:0,“ sortOrder”:847874874387209“降序”} kajhfsadkjh

如您所见,由于存在尾随垃圾字符,因此json无效。但是,如果您尝试使用jackson或gson解析上述json,那么您将获得有效json的已解析映射,垃圾尾部字符将被忽略。当您使用解析器检查json有效性时,这不是必需的解决方案。

有关此问题的解决方案,请参见此处

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


0
import static net.minidev.json.JSONValue.isValidJson;

然后调用此函数,并传入您的JSON String :)


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

以上解决方案涵盖了两种情况:

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

0

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

0

您可以使用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()
    );

对于这样一个简单的任务来说,这似乎有些矫kill过正,但是当您必须验证一个复杂的请求时,它就显得闪闪发光。请查看Validol的快速入门部分

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.