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

sap*_*ppu 138 java validation json

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

MBy*_*ByD 249

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

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;
}
Run Code Online (Sandbox Code Playgroud)

此代码使用org.json JSON API实现,该实现可在github,maven和部分Android上使用.

  • 你没有提到有JSONObject的库,我没有在标准的java lib中看到它 (16认同)
  • 我尝试了一个json字符串,如"{'hello':'foo'}'invalid'"(在{}之外添加'invalid'),而JSONObject没有抛出ParseException.我正在使用org.json.JSONObject.这是预期的吗? (9认同)
  • 我无法理解为什么海报不能被包含在包含代码片段的import语句中.这里很重要.这里的第二个答案是**更好. (9认同)
  • 此解决方案适用于大多数情况,但在某些情况下可能会失败.例如,它允许在右大括号之前使用逗号,这实际上是语法错误.有关其他极端情况,请参阅http://www.json.org/javadoc/org/json/JSONObject.html. (5认同)
  • 它很接近,但缺少对JSONArray的验证(我用更合适的函数更新了这篇文章) (2认同)

Jea*_*ean 89

杰克逊图书馆

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

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.7.0</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

然后,您可以按如下方式实现正确的答案:

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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

谷歌GSON选项

另一种选择是使用Google Gson.导入依赖项:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.5</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

同样,您可以将提议的解决方案实现为:

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;
      }
  }
}
Run Code Online (Sandbox Code Playgroud)

这里有一个简单的测试:

//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(VALID_JSON_STRING); //true
boolean secondStringValid = JSONUtils.isJSONValid(NOT_VALID_JSON_STRING); //false
Run Code Online (Sandbox Code Playgroud)

请注意,由于尾随逗号将在发布中修复,因此可能存在"次要"问题3.0.0.

  • JACKSON 陷阱:`new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")` 解析为 IntNode(28),没有异常。真没想到... (4认同)
  • 请注意,此处的 gson 示例使用 [lenient](https://static.javadoc.io/com.google.code.gson/gson/2.8.5/com/google/gson/stream/JsonReader.html#setLenient-boolean- )解析模式仍然允许许多偏差。请参阅[测试用例的更多详细信息](/sf/ask/3026372891/#47890960)和[严格解析示例](/sf/ask/712242891/#56901432)在我的其他答案中。 (2认同)

小智 15

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

import com.google.gson.JsonParser;

JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这不会对未括号的字符串ala"asdf"产生错误 (2认同)

npi*_*nti 12

您可以使用JSONUtils库中提供的.mayBeJSON(String str).

  • 此方法字面上只检查该字符串开头,并用引号或括号结束.非常不可靠. (3认同)
  • 这就是为什么方法名称是“可能”,而不是“是”的原因:) (3认同)

Nic*_*ley 5

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

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

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

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

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