实现一个简单地json解析器。

两部分组成,词法分析、语法分析

词法分析

package com.mahuan.json;import java.util.LinkedList;
import java.util.List;/*** 词法分析*/
public class Tokenizer {// 待分析的字符串private String json;// 读取字符时的索引位置private int index = 0;// 词法分析结果列表private List<Token> tokens = new LinkedList<Token>();// 获取词法分析结果时的索引位置private int tokenIndex = 0;/*** 构造函数,触发词法分析* @param json* @throws Exception*/public Tokenizer(String json) throws Exception {this.json = json;this.init();}/*** 读取字符串中的字符,索引位置加1* @return*/private Character read() {if (index < json.length())return json.charAt(index++);elsereturn null;}/*** 读取字符串中的字符,索引位置减1*/private void unread() {index--;}/*** 进行词法分析* @throws Exception*/private void init() throws Exception {Token token = null;while ((token = token()) != null) {tokens.add(token);}}/*** 按顺序读取字符串,获取词法分析结果* @return* @throws Exception*/private Token token() throws Exception {Character c = read();if (c == null)return null;// 忽略空白字符、换行符等while (isSpace(c)) {c = read();}if (isNull(c))return new Token(TokenType.Null, null);if (c == '{')return new Token(TokenType.ObjectStart, "{");if (c == '}')return new Token(TokenType.ObjectEnd, "}");if (c == '[')return new Token(TokenType.ArrayStart, "[");if (c == ']')return new Token(TokenType.ArrayEnd, "]");if (c == ',')return new Token(TokenType.Comma, ",");if (c == ':')return new Token(TokenType.Colon, ":");if (isTrue(c))return new Token(TokenType.Boolean, "true");if (isFalse(c))return new Token(TokenType.Boolean, "false");if (c == '"')return new Token(TokenType.String, readString());if (isNum(c)) {unread();return new Token(TokenType.Number, readNum());}throw new Exception("");}/*** 读取字符串* @return*/private String readString() {char c = read();StringBuffer sb = new StringBuffer();while (c != '"') {sb.append(c);if (isEscape(c)) {c = read();sb.append(c);}c = read();}return sb.toString();}/*** 读取数字,还未考虑所有数字表达形式* @return*/private String readNum() {char c = read();StringBuffer sb = new StringBuffer();while (c != '"' && c != ':' && c != ',' && c != ']' && c != '}') {sb.append(c);c = read();}unread();return sb.toString();}/*** 判断是否为数字开头的特征* @param c* @return*/private boolean isNum(char c) {if (c == '-' || ('0' <= c && c <= '9'))return true;return false;}/*** 判断是否为转义字符* @param c* @return*/private boolean isEscape(char c) {if (c == '\\')return true;return false;}/*** 是否为true字符串* @param c* @return* @throws Exception*/private boolean isTrue(char c) throws Exception {if (c == 't') {c = read();if (c == 'r') {c = read();if (c == 'u') {c = read();if (c == 'e') {return true;} else {throw new Exception("Invalid JSON input.");}} else {throw new Exception("Invalid JSON input.");}} else {throw new Exception("Invalid JSON input.");}} else {return false;}}/*** 是否为false字符串* @param c* @return* @throws Exception*/private boolean isFalse(char c) throws Exception {if (c == 'f') {c = read();if (c == 'a') {c = read();if (c == 'l') {c = read();if (c == 's') {c = read();if (c == 'e') {return true;} else {throw new Exception("Invalid JSON input.");}} else {throw new Exception("Invalid JSON input.");}} else {throw new Exception("Invalid JSON input.");}} else {throw new Exception("Invalid JSON input.");}} else {return false;}}/*** 是否为null字符串* @param c* @return* @throws Exception*/private boolean isNull(char c) throws Exception {if (c == 'n') {c = read();if (c == 'u') {c = read();if (c == 'l') {c = read();if (c == 'l') {return true;} else {throw new Exception("Invalid JSON input.");}} else {throw new Exception("Invalid JSON input.");}} else {throw new Exception("Invalid JSON input.");}} else {return false;}}/*** 是否为空字符* @param c* @return*/private boolean isSpace(char c) {if (c == '\t')return true;if (c == '\n')return true;if (c == '\r')return true;if (c == '\0')return true;if (c == ' ')return true;return false;}/*** 获取词法分析的下一个结果* @return*/public Token next() {if (tokenIndex + 1 < tokens.size())return tokens.get(++tokenIndex);return null;}/*** 获取当前位置的词法分析结果* @return*/public Token get() {if (tokenIndex < tokens.size())return tokens.get(tokenIndex);return null;}
}/*** 词法分析类型*/
enum TokenType {// object开始
    ObjectStart,// object结束
    ObjectEnd,// 数组开始
    ArrayStart,// 数组结束
    ArrayEnd,// 字符串
    String,// 数字
    Number,// boolean
    Boolean,// 空
    Null,// ,
    Comma,// :
    Colon
}/*** 词法分析单元* @author mahuan* @version 2017年12月13日*/
class Token {public TokenType type;public String value;public Token(TokenType type, String value) {this.type = type;this.value = value;}
}

语法分析

package com.mahuan.json;import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;/*** 语法分析*/
public class Parser {/*** 分析Object,使用map数据结构标识* @param tokenizer* @return* @throws Exception*/public static Map<String, Object> parserObject(Tokenizer tokenizer) throws Exception {Map<String, Object> map = new HashMap<>();Token token = null;while (true) {token = tokenizer.get();if (token.type == TokenType.ObjectEnd)break;if (token.type == TokenType.ObjectStart) {tokenizer.next();continue;}if (token.type == TokenType.Comma) {tokenizer.next();continue;// 跳过,
            }String key = token.value;token = tokenizer.next();if (token.type != TokenType.Colon)throw new Exception();tokenizer.next();map.put(key, parserValue(tokenizer));}return map;}/*** 分析Array,使用list数据结构标识* @param tokenizer* @return* @throws Exception*/public static List<Object> parserArray(Tokenizer tokenizer) throws Exception {List<Object> list = new LinkedList<>();Token token = null;while (true) {token = tokenizer.get();if (token.type == TokenType.ArrayEnd)break;if (token.type == TokenType.ArrayStart) {tokenizer.next();continue;}if (token.type == TokenType.Comma) {tokenizer.next();continue;}list.add(parserValue(tokenizer));}return list;}/*** 分析值,根据token再判断值的具体类型* @param tokenizer* @return* @throws Exception*/public static Object parserValue(Tokenizer tokenizer) throws Exception {Token token = tokenizer.get();try {if (token.type == TokenType.ObjectStart)return parserObject(tokenizer);else if (token.type == TokenType.ArrayStart)return parserArray(tokenizer);else if (token.type == TokenType.Boolean)return Boolean.valueOf(token.value);else if (token.type == TokenType.String)return token.value;else if (token.type == TokenType.Number)return token.value;else if (token.type == TokenType.Null)return null;throw new Exception("");} finally {// object和array分析完后,要跳过其end的token// 其他类型分析完后,要跳过自身
            tokenizer.next();}}}

测试代码

package com.mahuan.json;public class Test {public static void main(String[] args) throws Exception {String json = "{  \"success\": true,  \"message\": \"123\",  \"result\": [    -2146464718]}";Tokenizer tokenizer = new Tokenizer(json);Object map = Parser.parserValue(tokenizer);System.out.println(map);}
}

转载于:https://www.cnblogs.com/mahuan2/p/8034392.html

一个简单的json解析器相关推荐

  1. 自己动手实现一个简单的JSON解析器

    1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着诸多优点.比如易读性更好,占用空间更少等.在 ...

  2. json string 格式_自己动手实现一个简单的JSON解析器

    作者:田小波 原文:http://cnblogs.com/nullllun/p/8358146.html 1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数 ...

  3. 手写了一个简单的JSON解析器,网友直乎:牛!

    作者 | 田小波 来源 | http://r3m2u.cn/4455O 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 X ...

  4. 一个简单的公式解析器

    为了理解算法中的文法分析,用一个简单的公式解析器来说明. 公式计算是电子表格中的常用功能.主要是实现了些简单的公式计算:    比如:=Sum(A1,A2) 假设我们要实现简单的公式解析,我们从头开始 ...

  5. 高手教您编写简单的JSON解析器

    编写JSON解析器是熟悉解析技术的最简单方法之一.格式非常简单.它是递归定义的,所以与解析Brainfuck相比,你会遇到轻微的挑战 ; 你可能已经使用JSON.除了最后一点之外,解析 Scheme的 ...

  6. csv文件示例_自己动手? -一个简单的CSV解析器示例

    csv文件示例 Download source code - 2.7 MB 下载源代码2.7 MB 目录 (Table of Contents) Introduction 介绍 The Dataset ...

  7. IT民工——发一个万能的JSON解析器吧!

    前言 之前一直在用Newtonsoft的json解析,但是实在烂的可以!!! 首先,对于unicode无法解析,竟然跟我删除了\u,返回一堆码(\u6211-> 6211),我都火了! 还有,如 ...

  8. python 简历解析_pyresparser 一个简单的简历解析器,用于从简历中提取信息

    pyresparser A simple resume parser used for extracting information from resumes Built with ❤︎ and ☕ ...

  9. 手把手教你实现一个 JSON 解析器!

    1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着诸多优点.比如易读性更好,占用空间更少等. 在 ...

最新文章

  1. JDBC学习DayTwo
  2. rhel6用centos163 yum源
  3. count(1)、count(*) 与 count (列名) 的执行区别
  4. 通用存储过程分页---(测试能用的请放心试用)
  5. (整理)用户空间_内核空间以及内存映射
  6. 3 魔改_魔改启动!《战地3》非官方MOD工具即将发布
  7. redis windows下的环境搭建
  8. Go 函数特性和网络爬虫示例
  9. strict=False 但还是size mismatch for []: copying a param with shape [] from checkpoint,the shape in cur
  10. windows签名证书流程
  11. [转]正则表达式中re.match、re.search、re.findall的用法和区别
  12. 【Spring Cloud】网关 - Zuul(1.x)
  13. linux svn备份,SVN完全备份svnadmin hotcopy
  14. LaTeX详细教程+技巧总结
  15. 手机CPU处理器大解析
  16. 《今雨》孙溟㠭书画艺术
  17. 微信小程序识别图片并提取文字_这款微信小程序可以批量图片转文字?识别准确率超高!...
  18. 一种基于属性加密技术(ABE)的轻量级数据共享方案
  19. vue 日期时间选择器_Vue日期时间选择器
  20. Error: Flash Download failed - “Cortex-M3“的解决方法

热门文章

  1. 主键和索引哪个快_字节一面,被连问 MySQL 索引,脸都问绿了。。。
  2. python 项目发布会_发布会直播技术及业务实践
  3. android怎么看错误日志,android运行错误日志帮看下 不懂啊
  4. csh sum算总和_如何在R中使用sum()–在R中查找元素的总和
  5. python字符串反向输出_Python反向字符串– 5种方法和最佳方法
  6. fadein和fadeto_jQuery fadeIn,fadeOut,fadeTo
  7. C语言基础教程之可变的参数
  8. C语言基础教程之常量
  9. Java基础笔记(一)
  10. OpenCV(二)OpenCV的介绍和发展