【讀碼練習/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 '}'");
}
}
}




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM