如何编写基本的 JSON 解析类
有人可以指导如何编写一个类,该类将获取JSON数据并尝试将其解析为一个简单的缓冲列表,我们可以从中读回数据?
例如,JSON
{ name: 'John', age: 56 }
..将被解析为键值对表
name John
age 56
如何编写一个解析方法,这将有助于创建一个更快,更简单的方法?
请不要建议任何现有的图书馆。提供解析 JSON 的概念。
有人可以指导如何编写一个类,该类将获取JSON数据并尝试将其解析为一个简单的缓冲列表,我们可以从中读回数据?
例如,JSON
{ name: 'John', age: 56 }
..将被解析为键值对表
name John
age 56
如何编写一个解析方法,这将有助于创建一个更快,更简单的方法?
请不要建议任何现有的图书馆。提供解析 JSON 的概念。
这个答案假设你真的想写一个解析器,并准备投入所需的努力。
您必须从 JSON 的正式规范开始。我找到了 http://www.ietf.org/rfc/rfc4627.txt。这精确地定义了语言。您必须实现规范中的所有内容并为其编写测试。您的解析器必须满足不正确的JSON(就像您的一样)并抛出异常。
如果你想写一个解析器,停下来,思考,然后不要。要使其正常工作需要做很多工作。无论你做什么,都要做好它 - 不完整的解析器是一个威胁,永远不应该被分发。
您必须编写符合要求的代码。以下是规范中的一些短语。如果你不理解它们,你将不得不仔细研究并确保你理解:
“JSON文本应以Unicode编码。默认编码为 UTF-8。
“JSON解析器必须接受所有符合JSON语法的文本。
“编码注意事项:如果 UTF-8 为 8 位;二进制,如果 UTF-16 或 UTF-32
JSON may be represented using UTF-8, UTF-16, or UTF-32. When JSON
is written in UTF-8, JSON is 8bit compatible. When JSON is
written in UTF-16 or UTF-32, the binary content-transfer-encoding
must be used.
"
“任何字符都可以转义。如果字符位于基本
多语言平面(U+0000 到 U+FFFF)中,则它可以
表示为六个字符序列:反向 solidus,后跟
小写字母 u,后跟编码字符码位的四个十六进制数字
。十六进制字母 A 到
F 可以是大写或小写。因此,例如,仅包含单个反向实体字符的
字符串可以表示为
“\u005C”。"
如果您了解这些内容,并且仍然想编写解析器,请查看其他一些解析器,并查看其中是否有任何解析器具有一致性测试。借用这些用于您自己的应用程序。
如果您仍然热衷于,则应强烈建议您考虑使用解析器生成器。例如JAVACC,CUP和我最喜欢的工具ANTLR。ANTLR非常强大,但可能很难开始。另见Parboiled的建议,我现在推荐它。JSON相对简单,这将是一个有用的练习。大多数解析器生成器都会生成一个完整的解析器,该解析器可以创建可执行代码或生成 JSON 的解析树。
有一个使用ANTLR的JSON解析器生成器,http://www.antlr.org/wiki/display/ANTLR3/JSON+Interpreter 是否允许您偷看它。我还刚刚发现了一个用于JSON的Parboiled解析器生成器。如果你编写解析器的主要原因是学习如何做到这一点,这可能是一个很好的起点。
如果您不允许(或不想)使用解析器生成器,那么您必须创建自己的解析器。这通常分为两部分:
词法分析器/分词器。这识别语言规范中定义的基本基元。在这种情况下,它必须识别大括号,引号等。它可能还会建立数字的表示。
一个抽象语法树(http://en.wikipedia.org/wiki/Abstract_syntax_tree,AST)生成器。在这里,您编写代码来组装一个表示JSON抽象的树(例如,空格和卷曲已被丢弃)。
当您拥有AST时,应该很容易循环访问节点并创建所需的输出。
但是编写解析器生成器,即使对于像JSON这样的简单语言,也是一项繁重的工作。
如果你的“JSON”真的是这样的,你应该先拿一根棒球棒,然后去敲掉它的生产者的头。认真地。
如果你真的坚持编写自己的类(为什么?),你可以使用这样的接口:
public interface MyParser
{
boolean parse()
throws MyParsingException;
MyParser next();
}
然后,实现将 a 作为参数和地图生成器类;要解析,你可以做:CharBuffer
final CharBuffer buf = CharBuffer.wrap(yourSource);
final MyMapBuilder builder = new MyMapBuilder();
MyParser parser = new OpenBracketParser(buf, builder);
while (parser.parse())
parser = parser.next();
// result is builer.build()
这只是一个例子...
第二种解决方案,您希望使用现有的解析工具;在这种情况下,看看Parboiled。比antlr,jflex或其他更容易使用,因为你用纯Java编写语法。
最后,如果您认为足够了,并决定使用JSON库(您确实应该这样做),请使用Jackson,它甚至可以读取这种格式错误的JSON:
public static void main(final String... args)
throws IOException
{
final ObjectMapper mapper = new ObjectMapper()
.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true)
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
final JsonNode node = mapper.readTree("{name: 'John'}");
System.out.println(node); // {"name":"John"}
}