
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,其核心特点是结构化和易读性。JSON结构主要由对象({})和数组([])构成,键值对中的字符串则使用双引号("")包裹。验证JSON字符串的结构有效性,通常需要检查这些括号和引号是否正确配对和嵌套。栈(Stack)数据结构非常适合解决这类配对问题,因为它遵循“后进先出”(LIFO)原则,可以方便地匹配开闭符号。
基本思路是:
以下是一个基于栈的JSON结构验证的初步尝试代码:
import java.util.Stack;
public class JsonValidator {
public static boolean isValidJSON(String jsonString) {
Stack<Character> stack = new Stack<>();
for (char c : jsonString.toCharArray()) {
switch (c) {
case '{':
stack.push(c);
break;
case '}':
if (stack.isEmpty()) {
return false;
}
Character last1 = stack.pop();
if (last1 != '{') {
return false;
}
break;
case '[':
stack.push(c);
break;
case ']':
if (stack.isEmpty()) {
return false;
}
Character last2 = stack.pop();
if (last2 != '[') {
return false;
}
break;
case '"':
// 这里的逻辑存在多处问题
if (stack.isEmpty()) {
// 错误:如果字符串以双引号开始,栈是空的,会直接返回false
return false;
}
Character last3 = stack.peek();
if (last3 == '"') {
stack.pop(); // 期望是匹配一个开引号
} else {
stack.push(c); // 期望是压入一个开引号
}
// 核心问题:无论上面if-else分支如何,这里总是会再次压入双引号
stack.push(c);
break;
}
}
return stack.isEmpty();
}
}这段代码存在以下几个关键问题:
立即学习“Java免费学习笔记(深入)”;
Easily find JSON paths within JSON objects using our intuitive Json Path Finder
30
双引号处理逻辑不当:
未处理字符串内部的结构字符: 在JSON中, {, }, [, ] 等字符如果出现在双引号内部,应被视为普通字符串内容,不应参与结构匹配。例如,"{"key":"value"}" 是一个有效的JSON字符串,其中的 { 和 } 是字符串的一部分,不应影响栈的平衡。上述代码没有这种上下文感知能力。
未处理转义字符: JSON字符串中支持转义字符,例如 " 表示一个字面量的双引号。原始代码没有识别和跳过转义序列,可能导致 " 被错误地识别为字符串的结束引号,从而破坏逻辑。
为了解决上述问题,我们需要引入一个状态变量来判断当前是否处于字符串内部,并正确处理转义字符。
import java.util.Stack;
public class JsonValidatorImproved {
/**
* 验证JSON字符串的结构有效性(仅限括号和引号的平衡与嵌套)
* 不进行完整的JSON语法验证(如键值对格式、数据类型有效性等)
*
* @param jsonString 待验证的JSON字符串
* @return 如果结构平衡且嵌套正确,则返回true;否则返回false。
*/
public static boolean isValidJSONStructure(String jsonString) {
Stack<Character> stack = new Stack<>();
boolean inString = false; // 标记当前是否在双引号字符串内部
for (int i = 0; i < jsonString.length(); i++) {
char c = jsonString.charAt(i);
// 如果当前在字符串内部
if (inString) {
// 处理转义字符:如果遇到反斜杠,跳过下一个字符
if (c == '\') {
i++; // 跳过下一个字符,因为它是转义序列的一部分
if (i >= jsonString.length()) { // 防止字符串在转义符后结束,导致越界
return false; // 非法转义序列
}
continue; // 继续处理下一个字符
}
// 遇到未转义的双引号,表示字符串结束
if (c == '"') {
inString = false;
}
// 字符串内部的其他字符(包括 { } [ ])不影响结构匹配,直接跳过
continue;
}
// 不在字符串内部时,处理结构字符
switch (c) {
case '{':
case '[':
stack.push(c); // 遇到开符号,压入栈
break;
case '}':
if (stack.isEmpty() || stack.pop() != '{') {
return false; // 栈为空或栈顶不匹配,结构无效
}
break;
case ']':
if (stack.isEmpty() || stack.pop() != '[') {
return false; // 栈为空或栈顶不匹配,结构无效
}
break;
case '"':
inString = true; // 遇到双引号,进入字符串模式
break;
// 忽略其他字符,如逗号、冒号、空格、数字、布尔值、null等。
// 这些字符在结构验证中不影响括号平衡,但完整的JSON验证需要检查它们。
case ' ':
case ' ':
case '
':
case '
':
case ',':
case ':':
break; // 忽略空白符、逗号和冒号
default:
// 对于不在字符串内部的非结构字符,如果不是合法JSON值的一部分,
// 这里可以根据需求返回false,但对于纯粹的结构平衡验证,可以忽略。
// 为了简化,我们只关注括号和引号的平衡。
// 实际的JSON解析器会在这里进行更严格的字符检查。
// 例如,如果是非数字、非布尔、非null的裸字符,可能是语法错误。
// 为了本教程的目的,我们假设这些字符要么是合法值的一部分,要么是外部的非结构字符。
break;
}
}
// 最终检查:栈必须为空,且不能停留在字符串内部
return stack.isEmpty() && !inString;
}
public static void main(String[] args)以上就是Java中基于栈验证JSON字符串结构有效性的方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号