我有一个场景,我需要验证部分输入(见下文(是否是有效的JSON?我已经参考了这个答案来确定给定的字符串是否是有效的 JSON。
示例输入:
{
"JSON": [{
"foo":"bar",
"details": {
"name":"bar",
"id":"bar",
到目前为止我尝试过:
/ (?(DEFINE)
(?<number> -? (?= [1-9]|0(?!d) ) d+ (.d+)? ([eE] [+-]? d+)? )
(?<boolean> true | false | null )
(?<string> " ([^"nrt\\]* | \\ ["\\bfnrt/] | \\ u [0-9a-f]{4} )* " )
(?<array> [ (?: (?&json) (?: , (?&json) )* )? s* ]{0,1} )
(?<pair> s* (?&string) s* : (?&json) )
(?<object> { (?: (?&pair) (?: , (?&pair) )* )? s* }{0,1} )
(?<json> s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) s* )
) A (?&json),{0,1} Z /six
我使数组和对象的关闭是可选的(允许零或一次(。但是在某些情况下,这将失败,例如,当您打开一个对象而不关闭另一个对象(如下所示(时,正则表达式仍然会找到匹配项。
无效,但仍匹配:
{
"JSON": [{
"foo":"bar",
"details": {
"name":"bar",
"id":"bar",{
如何验证部分 JSON 输入?
编辑:
正如@ntahdh
在评论中提到的,此正则表达式无法使用java.util.regex
。所以现在我需要一个正则表达式,它应该在没有递归的情况下工作
这不是对您的问题的回答,如果允许的字符数足够,则注释的形式将是这样。
JSON 不是一种常规语言,因此不能仅由正则表达式引擎识别(如果您使用 Python 编程,regex
包提供的扩展可能会使您的任务成为可能,但我所说的通常是正确的(。
如果解析器生成器不适用于您的首选语言,您可以考虑创建一个简单的递归下降分析器。您已经定义的正则表达式将很好地帮助您创建将成为该解析器输入的令牌。当然,您预计会发生解析错误 - 但它应该发生在作为文件结束令牌的输入令牌上。在扫描文件结束令牌之前发生的分析错误表明您没有有效JSON 的前缀。如果您使用的是自下而上的移位-减少解析器,例如使用 YACC 生成的解析器,那么这将是文件结束标记以外的其他内容的移位错误。
为什么不让像 Gson 这样的解析器为您完成,您基本上是在令牌级别处理流。
import java.io.IOException;
import java.io.StringReader;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
public class Main
{
public static void main(String[] args) throws Exception
{
String json = "{'id': 1001,'firstName': 'Lokesh','lastName': 'Gupta','email': null}";
JsonReader jsonReader = new JsonReader(new StringReader(json));
jsonReader.setLenient(true);
try
{
while (jsonReader.hasNext())
{
JsonToken nextToken = jsonReader.peek();
if (JsonToken.BEGIN_OBJECT.equals(nextToken)) {
jsonReader.beginObject();
} else if (JsonToken.NAME.equals(nextToken)) {
String name = jsonReader.nextName();
System.out.println("Token KEY >>>> " + name);
} else if (JsonToken.STRING.equals(nextToken)) {
String value = jsonReader.nextString();
System.out.println("Token Value >>>> " + value);
} else if (JsonToken.NUMBER.equals(nextToken)) {
long value = jsonReader.nextLong();
System.out.println("Token Value >>>> " + value);
} else if (JsonToken.NULL.equals(nextToken)) {
jsonReader.nextNull();
System.out.println("Token Value >>>> null");
} else if (JsonToken.END_OBJECT.equals(nextToken)) {
jsonReader.endObject();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
jsonReader.close();
}
}
}
来源: https://howtodoinjava.com/gson/jsonreader-streaming-json-parser/
我知道使用正则表达式来验证一些具有嵌套结构的字符串并不容易,如果不是根本不可行的话。 使用现有的 JSON 解析器可能会有更多机会。
使用堆栈跟踪仍打开的对象和数组。 添加所需的右大括号和方括号。 询问 JSON 解析器您的新字符串是否为有效的 JSON。
您可能还需要做一些工作来处理逗号和引号,但您明白了。
使用代码示例:
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
String valid = "{n" +
""JSON": [{n" +
" "foo":"bar",n" +
" "details": {n" +
" "name":"bar",n" +
" "id":"bar"";
System.out.println("Is valid?:n" + valid + "n" + validate(valid));
String invalid = "{ n" +
" "JSON": [{n" +
" "foo":"bar",n" +
" "details": {n" +
" "name":"bar",n" +
" "id":"bar",{";
System.out.println("Is valid?:n" + invalid + "n" + validate(invalid));
}
public static boolean validate(String input) {
Stack<String> closings = new Stack<>();
for (char ch: input.toCharArray()) {
switch(ch) {
case '{':
closings.push("}");
break;
case '[':
closings.push("]");
break;
case '}':
case ']':
closings.pop();
}
}
StringBuilder closingBuilder = new StringBuilder();
while (! closings.empty()) {
closingBuilder.append(closings.pop());
}
String fullInput = input + closingBuilder.toString();
JsonParser parser = new JsonParser();
try{
parser.parse(fullInput);
}
catch(JsonSyntaxException jse){
return false;
}
return true;
}
}
这导致:
Is valid?:
{
"JSON": [{
"foo":"bar",
"details": {
"name":"bar",
"id":"bar"
true
Is valid?:
{
"JSON": [{
"foo":"bar",
"details": {
"name":"bar",
"id":"bar",{
false
请注意,在有效示例中的"bar"
行后添加逗号会使其无效(因为"bar",}]}}
是无效的 JSON(。