如何编写基本的JSON解析类

Sam*_*ish 12 java parsing json

有人可以指导如何编写一个可以获取JSON数据的类,并尝试将其解析为一个简单的缓冲列表,我们可以从中读取数据吗?

防爆.JSON

{ name: 'John', age: 56 } 
Run Code Online (Sandbox Code Playgroud)

..将被解析为一个关键值对表

name John
age  56
Run Code Online (Sandbox Code Playgroud)

如何编写一个有助于创建更快更简单的解析方法?

请不要建议任何现有的图书馆.提供解析JSON的概念.

pet*_*ust 27

这个答案假设您真的想要编写解析器并准备投入所需的工作.

您必须从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.
Run Code Online (Sandbox Code Playgroud)

"

"任何角色都可以被转义.如果角色在基本
多语言平面(U + 0000到U + FFFF)中,那么它可以
表示为六个字符的序列:反向固定,后跟
小写字母u,然后由四个十六进制数字来
编码字符的代码点.十六进制字母A到
F可以是大写或小写.因此,例如,
只包含一个反向固相字符的字符串可以表示为
"\ u005C".

如果您理解这些并且仍想编写解析器,那么请查看其他解析器,并查看其中是否有任何解析器.借用这些为您自己的应用程序.

如果您仍然热衷于强烈考虑使用解析器生成器.例如JAVACC,CUP和我首选的工具ANTLR.ANTLR非常强大,但很难开始.另请参阅Parboiled的建议,我现在推荐.JSON相对简单,它将是一个有用的练习.大多数解析器生成器生成一个完整的解析器,可以创建可执行代码或生成JSON的解析树.

如果允许您查看它,可以在http://www.antlr.org/wiki/display/ANTLR3/JSON+Interpreter上使用ANTLR的JSON解析器生成器.我刚刚发现了一个用于JSONParboiled解析器生成器.如果编写解析器的主要原因是学习如何操作,这可能是一个很好的起点.

如果您不允许(或不想)使用解析器生成器,那么您将不得不创建自己的解析器.这通常分为两部分:

词法分析器/标记器.这可以识别语言规范中定义的基本原语.在这种情况下,它必须识别大括号,引号等.它可能还会构建数字的表示.

一个AbstractSyntaxTree(http://en.wikipedia.org/wiki/Abstract_syntax_tree,AST)生成器.在这里编写代码来汇编表示JSON抽象的树(例如,空格和curlies已被丢弃).

当你有AST时,应该很容易迭代节点并创建你想要的输出.

但编写解析器生成器,即使是像JSON这样的简单语言,也是很多工作.


fge*_*fge 7

如果你的"JSON"真的是这样,你应该首先拿一根棒球棒然后敲击它的制作人.认真.

如果你真的坚持写自己的类(为什么?),你可以使用如下界面:

public interface MyParser
{
    boolean parse()
        throws MyParsingException;
    MyParser next();
}
Run Code Online (Sandbox Code Playgroud)

然后,实现将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()
Run Code Online (Sandbox Code Playgroud)

这只是一个例子......

第二种解决方案,您希望使用现有的解析工具; 在这种情况下看看Parboiled.因为用纯Java编写语法,所以比antlr,jflex或其他人更容易使用.

最后,如果你认为足够了,并且决定使用JSON库(你真的应该这样做),那就去杰克逊,它甚至可以阅读这种格式错误的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"}
}
Run Code Online (Sandbox Code Playgroud)


J.M*_*SON 6

我之前写过一篇.脚步:

  1. 获取表示JSON文本的字符串.

  2. 创建一个JsonToken类.我叫我的JToken.

  3. 翻阅步骤#1中的整个文本并解析出JToken(s).

  4. 递归地分组和嵌套您的JToken.

  5. 尝试保持简单和统一.所有JToken节点都有一个子数组,可以有0个或更多子节点.如果node是数组,则标记为数组.如果是OBJECT或ARRAY,子数组用于节点的子节点.唯一改变的是它被标记为的东西.还要将所有值保留为字符串类型.这样,您只需要一个名为"value"的节点上的单个成员,在完成所有艰苦工作后,可以将其解释为正确的数据类型.

  6. 使用防御性编码和单元测试.编写解析器的所有组件的测试.最好再花3个小时以偏执的方式编写代码,假设你每秒都犯错,而不是花3个小时追捕错误.代码偏执不够,在调试时你很少花时间沮丧.

示例代码:当我在code-eval.com上进行简单(具有讽刺意味)的挑战时.有一个json菜单解析挑战.我认为使用任何内置函数都会让人作弊,因为对我而言,代码挑战的全部意义在于测试你的算法问题解决能力.挑战在于:https://www.codeeval.com/open_challenges/102/

我的代码,使用javascript中从头开始构建的解析器来传递此挑战:

CODE: https://pastebin.com/BReK9iij
Was not able to post it on stack-overflow because it is too much code.
Put it in a non-expiring paste-bin post.
Run Code Online (Sandbox Code Playgroud)

注意:此代码可以使用一些改进.其中一些效率非常低,并且不适用于Unicode.

除非您以某种非标准方式解释JSON,否则我不建议您编写自己的JSON解析器.

例如:我目前正在使用JSONedit来组织基于文本的冒险分支.我只使用JSON文件格式,因为它是紧凑的,查看器允许我扩展和收缩项目.GOLang附带的标准解析器不会按照我想要的方式解释信息,因此我正在编写自己的解析器.