【读码练习/JSON-java】(一)解析JSON的过程

什么是JSON

官网的解释是JSON (JavaScript Object Notation) is a lightweight data-interchange format 。


JSON的格式

键值对的集合 {k:v}

值得有序列表 [1,2]


什么是JSON-java

JSON官网提供的java语言处理json数据的小框架。

阅读该源码的目的

1、学习解析类工具的原理

2、锻炼读代码的能力


解析JSON的原理

1、JSON-java最重要的类有三个。

JSONObject : 包装一个map。 用来表示一个{k:v,k2:v2,k3:[1,2]}形式的json数据

JSONArray :包装一个ArrayList。用来表示一个[1,2,{k:v}]形式的json数据

JSONTokener:包装一个Reader。用来存储、读取、操作一个表示JSON数据的字符串


2、原理

1、JSONObject和JSONArray都可以用一个JSONTokener作为构造参数去实例化。

2、解析时可能会产生多个JSONObject或者JSONArray。但是他们都是操作同一个JSONTokener。

3、JSONObject和JSONArray可以分别通过JSONTokener提供的方法解析出对方。可以实现嵌套。

例子

new JSONObject("{k:v,k2:v2,k3:[1,{k4:V4}]}");

解析出{

解析出k和v存入map

解析出k2和v2存入map

解析出k3 然后发现一个数组的左标记[

new  JSONArray 开始解析[1,{k4:V4}]}

解析出[

解析出1 放入list

解析出json对象的左标记{

new JSONObject 开始解析 {k4:V4}]}

解析出k4和v4放入map

发现}一个JSONObject解析结束

解析出 {k4:V4} 放入list。

发现 ] 一个JSONArray解析结束

解析出[1,{k4:V4}] 和k3 一起放入map (第一个JSONObject)。

解析出} 

全部解析结束



3、实现

JSONTokener 重要的Field(数据)和Method(操作)

    private int     character;    // 当前行字符的index
    private boolean eof;      // 标记读到尾部
    private int     index;      // 所有行字符的index
    private int     line;       // 行数
    private char     previous;     // 缓存
    private Reader     reader;    // JSON数据
    private boolean usePrevious;   // 使用缓存标志

 public char next() throws JSONException

  从reader或者缓存(previous)里读取一个char,并且设置和统计重要的Field。

   public void back() throws JSONException

  将各种统计的field恢复到上一个的状态。并且把userPrevious设置成true(即下次使用next()时从缓存里拿一个char)

  next和back使的JSONTokener有了一个向前探测一个字符的能力。

 public char nextClean() throws JSONException

  读取一个可见字符串或者一个结束符\0。(看了人家的代码才意识到空格之前的都是不可见字符)

  public String nextString(String quote) throws JSONException

  读一个封闭的引用符内的字符串。(这里会做一个转义处理)

转义处理解读
如果碰到\ 作转义处理:转义处理:往后读一位
1、如果后面的是b t n f r  往buff里添加相应的转义字符
2、如果后面的是u 则next(4) 转成 16进制Int 转成char 添加到buff
3、如果后面的是u 则next(4) 转成 16进制Int 转成char 添加到buff
4、后面如果是‘ “ \  /  直接把该字符添加到buff
5、其他情况抛出Illegal escape.

 

public Object nextValue() throws JSONException

  这个方法很重要! 读取下一个封闭引用符号括起来的值,或者各种基本的数据类型,或者一个JSONObject和JSONArray。(嵌套的关键)

public Object nextValue() throws JSONException {
char c = nextClean(); // 探测
String string;

switch (c) {
case '"':
case '\'':
return nextString(c);
case '{':
back();
// 探测到回退
return new JSONObject(this);
case '[':
back();
return new JSONArray(this);
}


StringBuffer sb
= new StringBuffer();
while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
sb.append(c);
c
= next();
}
back();

string
= sb.toString().trim();
if (string.equals("")) {
throw syntaxError("Missing value");
}
return JSONObject.stringToValue(string);
}



JSONArray的构造器(注意JSON-java支持非正规的JSON格式可以用多种符号分隔数据)

public JSONArray(JSONTokener x) throws JSONException {
this();
if (x.nextClean() != '[') {
throw x.syntaxError("A JSONArray text must start with '['");
}
if (x.nextClean() != ']') {
x.back();
for (;;) {
if (x.nextClean() == ',') {
x.back();
this.myArrayList.add(JSONObject.NULL);
}
else {
x.back();
this.myArrayList.add(x.nextValue());
}
switch (x.nextClean()) {
case ';':
case ',':
if (x.nextClean() == ']') {
return;
}
x.back();
break;
case ']':
return;
default:
throw x.syntaxError("Expected a ',' or ']'");
}
}
}
}



JSONObject的构造器(注意JSON-java支持非正规的JSON格式可以用多种符分隔数据)

    public JSONObject(JSONTokener x) throws JSONException {
this();
char c;
String key;

if (x.nextClean() != '{') {
throw x.syntaxError("A JSONObject text must begin with '{'");
}
for (;;) {
c
= x.nextClean();
switch (c) {
case 0:
throw x.syntaxError("A JSONObject text must end with '}'");
case '}':
return;
default:
x.back();
key
= x.nextValue().toString();
}

// The key is followed by ':'. We will also tolerate '=' or '=>'.

c
= x.nextClean();
if (c == '=') {
if (x.next() != '>') {
x.back();
}
}
else if (c != ':') {
throw x.syntaxError("Expected a ':' after a key");
}
putOnce(key, x.nextValue());

// Pairs are separated by ','. We will also tolerate ';'.

switch (x.nextClean()) {
case ';':
case ',':
if (x.nextClean() == '}') {
return;
}
x.back();
break;
case '}':
return;
default:
throw x.syntaxError("Expected a ',' or '}'");
}
}
}



posted @ 2011-08-24 21:27  倚楼无语F5  阅读(3756)  评论(0编辑  收藏  举报