如何在 Java 中使用字符堆栈验证 JSON 语法?
How to Validate JSON Syntax Using a Character Stack in Java?
我有一个输入文件 ("student.json"),它包含几行 JSON 代码,例如:
{"name":"Josh","age":22,"gender":"M"}
将在 Java 程序中使用。程序应该输入文件,抓取一个 JSON 字符串,然后使用字符堆栈来验证语法(程序应该忽略具体的 属性 [name] 和值 [Josh] 是什么,但是知道每组大括号必须至少有 2 个值,中间有一个冒号)。如果语法正确,控制台会告诉用户 JSON 字符串有效,如果无效,控制台会告诉用户。
对于字符堆栈,我将遍历 JSON 字符串的每个字符。当遇到左大括号或方括号时,程序应将其压入堆栈。当遇到右大括号或括号时,程序应从堆栈中弹出一个值并查看它是否匹配。我还应该使用 isEmpty 方法来查看是否有不匹配的符号。
我以前从未使用过字符堆栈。我知道如何完成 Java 程序的其余部分,这只是我卡在的堆栈。
问题:如何使用此字符堆栈和要求验证 JSON 字符串?
是否绝对需要通过手动解析 JSON 来验证?如果不是,我建议使用 Jackson 的 ObjectMapper:http://fasterxml.github.io/jackson-databind/javadoc/2.2.0/com/fasterxml/jackson/databind/ObjectMapper.html#readTree(java.lang.String)
如果您尝试手动执行此操作,您将不得不担心嵌套对象和数组。
编辑:
堆栈
我假设您了解什么是堆栈 (LIFO) 的基础知识,但您有兴趣了解堆栈的底层实现方式。如果可以,请使用 Java LinkedList 作为底层数据结构。如果你必须使用一个简单的数组会更难,因为你将不得不处理调整大小并因此移动数组的所有元素。
使用 LinkedList,您只需为每次推送到堆栈添加 (E)/addFirst(E),然后为每次弹出添加 getLast()/getFirst()。
您可以在此 post 中找到示例:Stack array using pop() and push()
一个栈基本上就是这个接口:
public interface Stack<T> {
void push(T item); // adds an item to the stack
T peek(); // looks what is the last item in the stack
T pop(); // removes and returns the last item of the stack
boolean isEmpty(); // are there items in the stack?
}
这不是漂亮的代码,但这里有一个示例可以解决您的问题(使用内置 java.util.Stack
class):
public static boolean isValid(String str) {
Stack<Character> stack = new Stack<>();
for (char c : str.toCharArray()) {
switch (c) {
case '{':
stack.push(c);
break;
case '}':
if (stack.isEmpty()) {
return false;
}
Character last1 = stack.pop();
if (last1 != '{') {
return false;
}
break;
case '\"':
if (stack.isEmpty()) {
return false;
}
Character last2 = stack.peek();
if (last2 == '\"') {
// It's a closing quote
stack.pop();
} else {
// It's an opening quote
stack.push(c);
}
break;
}
}
return stack.isEmpty();
}
有测试:
@Test public void isValid_if_true() {
String jsonString = "{\"name\": \"John\"}";
assertTrue(JsonValidator.isValid(jsonString));
}
@Test public void isValid_if_too_many_opened_brackets() {
String jsonString = "{\"name\": \"John\", {}";
assertFalse(JsonValidator.isValid(jsonString));
}
@Test public void isValid_if_too_many_closed_brackets() {
String jsonString = "{\"name\": \"John\", }}";
assertFalse(JsonValidator.isValid(jsonString));
}
@Test public void isValid_if_too_many_quotes() {
String jsonString = "{\"name\": \"\"John\"}";
assertFalse(JsonValidator.isValid(jsonString));
}
您仍然需要检查您的 JSON 对象中是否至少有 2 个属性,并验证 ,
.
的位置
试着在纸上玩一下算法,看看它是如何工作的。
基本上我们忽略除括号和引号之外的所有字符。当我们得到其中一个特殊字符时,我们检查它们是否正在打开一个新的 "token"(压入堆栈)、关闭一个(从堆栈弹出)或者是否存在问题。
希望对您有所帮助。
我有一个输入文件 ("student.json"),它包含几行 JSON 代码,例如:
{"name":"Josh","age":22,"gender":"M"}
将在 Java 程序中使用。程序应该输入文件,抓取一个 JSON 字符串,然后使用字符堆栈来验证语法(程序应该忽略具体的 属性 [name] 和值 [Josh] 是什么,但是知道每组大括号必须至少有 2 个值,中间有一个冒号)。如果语法正确,控制台会告诉用户 JSON 字符串有效,如果无效,控制台会告诉用户。
对于字符堆栈,我将遍历 JSON 字符串的每个字符。当遇到左大括号或方括号时,程序应将其压入堆栈。当遇到右大括号或括号时,程序应从堆栈中弹出一个值并查看它是否匹配。我还应该使用 isEmpty 方法来查看是否有不匹配的符号。
我以前从未使用过字符堆栈。我知道如何完成 Java 程序的其余部分,这只是我卡在的堆栈。
问题:如何使用此字符堆栈和要求验证 JSON 字符串?
是否绝对需要通过手动解析 JSON 来验证?如果不是,我建议使用 Jackson 的 ObjectMapper:http://fasterxml.github.io/jackson-databind/javadoc/2.2.0/com/fasterxml/jackson/databind/ObjectMapper.html#readTree(java.lang.String)
如果您尝试手动执行此操作,您将不得不担心嵌套对象和数组。
编辑:
堆栈
我假设您了解什么是堆栈 (LIFO) 的基础知识,但您有兴趣了解堆栈的底层实现方式。如果可以,请使用 Java LinkedList 作为底层数据结构。如果你必须使用一个简单的数组会更难,因为你将不得不处理调整大小并因此移动数组的所有元素。
使用 LinkedList,您只需为每次推送到堆栈添加 (E)/addFirst(E),然后为每次弹出添加 getLast()/getFirst()。
您可以在此 post 中找到示例:Stack array using pop() and push()
一个栈基本上就是这个接口:
public interface Stack<T> {
void push(T item); // adds an item to the stack
T peek(); // looks what is the last item in the stack
T pop(); // removes and returns the last item of the stack
boolean isEmpty(); // are there items in the stack?
}
这不是漂亮的代码,但这里有一个示例可以解决您的问题(使用内置 java.util.Stack
class):
public static boolean isValid(String str) {
Stack<Character> stack = new Stack<>();
for (char c : str.toCharArray()) {
switch (c) {
case '{':
stack.push(c);
break;
case '}':
if (stack.isEmpty()) {
return false;
}
Character last1 = stack.pop();
if (last1 != '{') {
return false;
}
break;
case '\"':
if (stack.isEmpty()) {
return false;
}
Character last2 = stack.peek();
if (last2 == '\"') {
// It's a closing quote
stack.pop();
} else {
// It's an opening quote
stack.push(c);
}
break;
}
}
return stack.isEmpty();
}
有测试:
@Test public void isValid_if_true() {
String jsonString = "{\"name\": \"John\"}";
assertTrue(JsonValidator.isValid(jsonString));
}
@Test public void isValid_if_too_many_opened_brackets() {
String jsonString = "{\"name\": \"John\", {}";
assertFalse(JsonValidator.isValid(jsonString));
}
@Test public void isValid_if_too_many_closed_brackets() {
String jsonString = "{\"name\": \"John\", }}";
assertFalse(JsonValidator.isValid(jsonString));
}
@Test public void isValid_if_too_many_quotes() {
String jsonString = "{\"name\": \"\"John\"}";
assertFalse(JsonValidator.isValid(jsonString));
}
您仍然需要检查您的 JSON 对象中是否至少有 2 个属性,并验证 ,
.
试着在纸上玩一下算法,看看它是如何工作的。
基本上我们忽略除括号和引号之外的所有字符。当我们得到其中一个特殊字符时,我们检查它们是否正在打开一个新的 "token"(压入堆栈)、关闭一个(从堆栈弹出)或者是否存在问题。
希望对您有所帮助。