開源Json解析器的淺述
之前在做專案中,Json 這種資料轉換格式經常用,為什麼呢?我認為是
1、它的易用性,跨平臺性,它是JS(JavaScript)的子集,是一種物件字面量。
2、它與XML都是樹結構的語法樹;
同樣的XML,JSON表示,Json則相對簡潔,XML相對冗餘,當然也是互相不可替代的,根據具體需求選擇合適才是完美的。
做個原生的Json解析器是掌閱科技的大佬提出的一個問題,在之前沒有相對的深入瞭解這個Json解析器,專案裡用到的都是org.Json開源包\Gson包。這周就主要對Json解析器包括與塌相關的知識做個梳理,形成網路結構。想做Json解析器,必須對Json本身有了解,在這裡主要點出幾個下面需要用的點:
JSON結構:
"string":Java的String;
number:Java的Long或Double;
true/false:Java的Boolean;
null:Java的null;
[array]:Java的List<Object>或Object[];
{"key":"value"}:Java的Map<String, Object>。
JSON文法:
Jsonobject = {} | { members }
members = pair | pair , members
pair = string : value
array = [] | [ elements ]
elements = value | value , elements
value = string | number | object | array | true | false | null
string = “” | ” chars ”
chars = char | char chars
char = any-Unicode-character-except-“-or–or- control-character | \” | \ | \/ | \b | \f | \n | \r | \t | \u four-hex-digits
number = int | int frac | int exp | int frac exp
int = digit | digit1-9 digits | - digit | - digit1-9 digits
frac = . digits
exp = e digits
digits = digit | digit digits
e = e | e+ | e- | E | E+ | E-
細節可以參看《Json必知必會》http://download.csdn.net/download/qq_34417408/10122524;
同時也要了解編譯原理的一些知識:
編譯過程:詞法分析,語法分析,語義分析,當然其中還有程式碼優化,目的碼;
其中,
詞法分析作用:找出單詞 。如int a=b+c; 結果為: int,a,=,b,+,c和;
語法分析作用:找出表示式,程式段,語句等。如int a=b=c;的語法分析結果為int a=b+c這條語句。
語義分析作用:檢視型別是否匹配等。
還有中間程式碼的優化:http://blog.csdn.net/qq_34417408/article/details/78126087(我之前總結的部落格)
同時要了解解析器的功能,原理;
Json解析器是把輸入字串重新變成熟悉型別的物件,像一個函式,它的輸入是一個表示JSON的字串,輸出是結構化的對應到語言本身的資料結構。
在解析過程中,主要有兩部分一個是,詞法分析,將原始碼解析為詞法單元token;另一個是語法分析,構造語法樹parser;當然都是基於Json 詞法和文法。
在第一部分,形成詞法分析時,即是構造自動機(DFA);在寫Json之前,我先手寫了幾個簡單的自動機,很久沒寫過,熱了下身,其實只要邏輯分析沒問題,是很簡單的,就是程式碼實現。
(a|bb)一個可以有’a’和’b’的字串,’b’出現時必為偶數個;
public class ABB {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
// TODO code application logic here
Scanner in =new Scanner(System.in);
String string=in.nextLine();
char[] ch=string.toCharArray();
if(ch.length==0){
throw new Exception("不合法字元!");
}
int i=0;
while(i<ch.length){
if(ch[i]=='a'){
++i;
}else if(i<ch.length-1&&ch[i]=='b'){
++i;
if(i<ch.length&&ch[i]=='b'){
++i;
}else{
throw new Exception("不合法字元!");
}
}else{
throw new Exception("不合法字元!");
}
}
System.out.println("合法字元!");
}
}
由於Json 的結構特殊,在輸入第一字元的時候就可以判斷是哪個物件,{}/[]/string/true/false/number/null;我們可以加工構造並對應列舉型別即token流,進行詞法分析:
STRING(字串字面量)
NUMBER(數字字面量)
NULL(null)
START_ARRAY([)
END_ARRAY(])
START_OBJ({)
END_OBJ(})
COMMA(,)
COLON(:)
BOOLEAN(true或者false)
END_DOC(表示JSON資料的結束)
列舉型別:
public enum TokenType {
START_OBJ, END_OBJ, START_ARRAY, END_ARRAY, NULL, NUMBER, STRING, BOOLEAN, COLON, COMMA, END_DOC
}
同時構造token類:
public class Token {
private TokenType type;
private String value;
public Token(TokenType type, String value) {
this.type = type;
this.value = value;
}
public TokenType getType() {
return type;
}
public void setType(TokenType type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String toString() {
return getValue();
}
}
在進行Json解析的詞法分析時,首先需要將字串轉為字元陣列,我們可以用BufferReader(new StringReader(String str));
關於BufferReader()可以見:https://www.cnblogs.com/meilidelaohuhua/p/6638545.html ;
轉化之後進行字元逐一分析,此時用到的是Json的結構的自動機,將其轉化為token流。此時第一部分詞法分析完成。
在第二部分語法樹parser構造中,主要分兩部分;
一塊是物件Object文法,一塊是陣列Array文法,其他文法是基本型別;
其中物件可以用Map實現(Key:Value),陣列用List集合
public class JObject implements Json {
private Map<String, Value> map = new HashMap<>();
public JObject(Map<String, Value> map) {
this.map = map;
}
public int getInt(String key) {
return Integer.parseInt((String) map.get(key).value());
}
public String getString(String key) {
return (String) map.get(key).value();
}
public boolean getBoolean(String key) {
return Boolean.parseBoolean((String) map.get(key).value());
}
public JArray getJArray(String key) {
return (JArray) map.get(key).value();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{ ");
int size = map.size();
for (String key : map.keySet()) {
sb.append(key + " : " + map.get(key));
if (--size != 0) {
sb.append(", ");
}
}
sb.append(" }");
return sb.toString();
}
}
public class JArray implements Json, Value {
private List<Json> list = new ArrayList<>();
public JArray(List<Json> list) {
this.list = list;
}
public int length() {
return list.size();
}
public void add(Json element) {
list.add(element);
}
public Json get(int i) {
return list.get(i);
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[ ");
for (int i =0; i < list.size(); i++) {
sb.append(list.get(i).toString());
if (i != list.size() - 1) {
sb.append(", ");
}
}
sb.append(" ]");
return sb.toString();
}
@Override
public Object value() {
return this;
}
}
其中重要的是Json,和Value抽象類的建立得以使JObject和JArray相互轉化,動態的完成物件和陣列相互巢狀的轉化。
另外,在構造token 類的時候把列舉型別和Value為屬性,在後面新增list的時候,省了許多麻煩。
原始碼:https://github.com/weiyanyanyan/Json
資料查詢:https://www.cnblogs.com/meilidelaohuhua/p/6638545.html
https://www.zhihu.com/question/24640264/answer/80500016
http://blog.csdn.net/yuanzhou314/article/details/43032067
https://www.liaoxuefeng.com/article/0014211269349633dda29ee3f29413c91fa65c372585f23000
相關文章
- json 解析器哪家強?JSON
- 手寫javascript json解析器JavaScriptJSON
- 分享開源表示式解析器IK-Expression2.0Express
- 手寫Json解析器學習心得JSON
- iOS開發-XML&JSON淺析iOSXMLJSON
- Java JSON解析器效能基準測試JavaJSON
- 開源BI系統簡述(轉載)
- JSON解析器之Gson、FastJson、JacksonJSONAST
- 開源新聞綜述:五角大樓、好萊塢和 Sandboxie 的開源
- 淺述容器和容器映象的區別
- Google 開源了世界上最準確的語言解析器 Parsey McParsefaceGo
- [原創]淺談從“述職”向“述能”轉變
- Lotus 複製技術淺述
- Json序列化之.NET開源類庫Newtonsoft.Json的研究JSON
- 淺析 package.jsonPackageJSON
- 【JSON解析】淺談JSONObject的使用JSONObject
- 淺述Oracle分散式事務概念Oracle分散式
- 自己動手寫json解析器0x01-分詞JSON分詞
- 幾百行程式碼實現一個 JSON 解析器行程JSON
- 教你如何用Swift寫個json轉模型的開源庫SwiftJSON模型
- 淺談KPI與開源的可持續發展KPI
- 如何學習開源專案及Ceph的淺析
- 深入淺出 JSON Web TokenJSONWeb
- 作者親述:開源軟體給作者帶來什麼?
- 【Python】淺談python中的jsonPythonJSON
- .NET6 開源之JSON 2 SQL (JORM框架)JSONSQLORM框架
- MySQL核心原始碼解讀-SQL解析之解析器淺析MySql原始碼
- 【淺度渣文】JVM——簡述垃圾回收JVM
- 無線上網基礎知識淺述
- 優秀開源庫SDWebImage原始碼淺析Web原始碼
- 開源新聞綜述:有史以來最快的開源 CPU、Facebook 分享對抗有害內容的 AI 演算法AI演算法
- 淺析package.json中的devdependencies 和 dependenciesPackageJSONdev
- 二、淺談 JSON 處理技巧JSON
- 如何關閉一個開放的DNS解析器DNS
- 淺述代理對 TikTok運營的重要性——IPIPGOGo
- 基於RISC-V架構的開源處理器及SoC研究綜述(一)架構
- 基於RISC-V架構的開源處理器及SoC研究綜述(二)架構
- 基於RISC-V架構的開源處理器及SoC研究綜述(三)架構