[TOC]
## 手寫Json解析(仿Gson)
### Reader
~~~
public class Reader {
private char[] buffer;
private int pos;
public Reader(String json) {
buffer = json.toCharArray();
pos = 0;
}
ublic char next() throws BufferException{
if (pos < buffer.length){
return buffer[pos];
}
throw new BufferException("no next");
}
public void skipNext() {
pos ++;
}
public void moveToLast() {
pos --;
}
public String nextName() {
//讀取下一個名稱 知道遇到下一個 '"'
return nextString();
}
//讀取下一個value 根據類型的區別 分為 nextBoolean() nextDouble() nextFloat()...
public String nextNumString() {
nextNonWhitespace();
StringBuilder stringBuilder = new StringBuilder();
char c;
while (pos < buffer.length){
c = buffer[pos ++];
if (c == '"' && stringBuilder.length() <= 0){
continue;
}else if (c > '0' && c < '9' || c == '.' || c == '-'){
stringBuilder.append(c);
}else {
pos --;
break;
}
}
return stringBuilder.toString();
}
}
~~~
### Parser
~~~
public interface Parser {
Object parse(Reader reader);
}
~~~
解析器安裝類型可以分為 ObjectParser , PrimitiveParser(基本類型) , ArrayParser , NullParser
下面以ObjectParser為例
### ObjectParser
~~~
public class ObjectParser implements Parser {
private static final int START_TAG = -1;
private static final int OBJECT = 0;
private static final int NAME = 1;
private static final int VALUE = 2;
private Stack<Integer> stack;//核心操作棧
private Stack<String> nameStack;//名稱張
private Class<?> raw;
private Map<String, Field> map; // <fieldName, typeName>
private Map<String, Object> map; // <fieldName, typeName>
public ObjectParser(Class<?> raw) {
this.raw = raw;
map = new HashMap<>();
stack = new Stack<>();
nameStack = new Stack<>();
}
public Object parse(Reader reader) {
//一次性class對象解析,存入map
Field[] fields = raw.getDeclaredFields();
for (Field f : fields){
String name = f.getName();
map.put(name, f);
}
Object instance;
try {
instance = raw.newInstance();
} catch (Exception e) {
return null;
}
stack.push(START_TAG);
while (reader.hasNext() && !stack.empty()){
//為了第一次能往下執行初始化
if (stack.peek() == START_TAG){
stack.pop();
}
char c;
try {
c = reader.next();
} catch (Reader.BufferException e) {
e.printStackTrace();
break ;
}
reader.skipNext();
Logger.d("c is " + c);
switch (c){
case '{':
if (stack != null && !stack.isEmpty() && stack.peek() == VALUE){
//如果是value
reader.moveToLast();
setValue(reader, instance);
}else {
//否則就是key
stack.push(OBJECT);
stack.push(NAME);
}
continue;
case '"':
if (stack.peek() == NAME){
//如果是name
String name = reader.nextName();
nameStack.push(name);
stack.pop();
}else if (stack.peek() == VALUE){
//如果是value
setValue(reader, instance);
}
break;
case ',':
stack.push(NAME);
break;
case ':':
stack.push(VALUE);
break;
case '}':
if (stack.peek() == OBJECT){
stack.pop();
}
break;
case ' ':
case '\n':
break;
default:
reader.moveToLast();
setNameAndValue(reader, instance);
break;
}
}
return instance;
}
private void setValue(Reader reader, Object instance) {
//根據類型的不同 初始化不同的 使用不同Parser
//通過反射Field的值調用不同的值Par
~~~
核心思想:
維護一個操作指令棧
## Gson
//todo 研究gson的源碼
## FastJson為什么快
### 序列化
1. 緩存各種序列化處理類,包括各種基本對象、集合對象、第三方對象、自定義對象,方便序列化處理類的快速查找、避免JavaBeanSerializer的反復創建
2. 使用ThreadLocal來存儲序列化過程中不斷append的字符串,減少內存分配和gc,從而提高性能。
3. 用類StringBuilder方式進行字符串操作,配合ThreadLocal實現線程安全的StringBuilder。(StringBuilder線程不安全但效率改哦)
4. 缺省啟用sort field輸出,為deserialize優化做準備。
5. 使用asm高效反射 就是使用不同的反射機制
### 反序列化
1. IdentityHashMap緩存各種反序列化處理類,包括基本對象、集合對象、第三方對象、自定義對象,方便反序列化類的快速查找、避免JavaBeanDeserializer的反復創建。代碼與序列化的處理類緩存相似
2. 讀取token基于預測。在反序列化一個json字符串時,下一個字符一般情況下是可以預估的。比如字符}之后最有可能出現的是“,”、“\]”、“}”或者結束符,有計劃、有預測地判斷token將能提升不少性能。(其實就是json字符串是有規律的, 后面結束符是可以提前只是,只要做好匹配就好)
3. 快速匹配。在Fastjson反序列化過程中,有一個非常有用的效率改進方法是有序json的快速匹配。所謂有序json就是json字符串中的key是按照字符排序好了的。上面已經說過,Fastjson的序列化默認是按照key的順序進行的,因此做反序列化時候,Fastjson采用一種優化算法,就是假設key/value的內容是有序的,讀取的時候只需要做key的匹配,而不需要把key從輸入中讀取出來。( key的順序與 field的順序一直值時,就可以不要匹配查找,直接比較賦值)
4. 使用asm高效反射(同上序列化的asm反射)
5. symbolTable算法緩存關鍵字,避免創建新的字符串對象。
6.
## 參考資料
[JsonParser](https://github.com/5A59/JsonParser)
- Android
- 四大組件
- Activity
- Fragment
- Service
- 序列化
- Handler
- Hander介紹
- MessageQueue詳細
- 啟動流程
- 系統啟動流程
- 應用啟動流程
- Activity啟動流程
- View
- view繪制
- view事件傳遞
- choreographer
- LayoutInflater
- UI渲染概念
- Binder
- Binder原理
- Binder最大數據
- Binder小結
- Android組件
- ListView原理
- RecyclerView原理
- SharePreferences
- AsyncTask
- Sqlite
- SQLCipher加密
- 遷移與修復
- Sqlite內核
- Sqlite優化v2
- sqlite索引
- sqlite之wal
- sqlite之鎖機制
- 網絡
- 基礎
- TCP
- HTTP
- HTTP1.1
- HTTP2.0
- HTTPS
- HTTP3.0
- HTTP進化圖
- HTTP小結
- 實踐
- 網絡優化
- Json
- ProtoBuffer
- 斷點續傳
- 性能
- 卡頓
- 卡頓監控
- ANR
- ANR監控
- 內存
- 內存問題與優化
- 圖片內存優化
- 線下內存監控
- 線上內存監控
- 啟動優化
- 死鎖監控
- 崩潰監控
- 包體積優化
- UI渲染優化
- UI常規優化
- I/O監控
- 電量監控
- 第三方框架
- 網絡框架
- Volley
- Okhttp
- 網絡框架n問
- OkHttp原理N問
- 設計模式
- EventBus
- Rxjava
- 圖片
- ImageWoker
- Gilde的優化
- APT
- 依賴注入
- APT
- ARouter
- ButterKnife
- MMKV
- Jetpack
- 協程
- MVI
- Startup
- DataBinder
- 黑科技
- hook
- 運行期Java-hook技術
- 編譯期hook
- ASM
- Transform增量編譯
- 運行期Native-hook技術
- 熱修復
- 插件化
- AAB
- Shadow
- 虛擬機
- 其他
- UI自動化
- JavaParser
- Android Line
- 編譯
- 疑難雜癥
- Android11滑動異常
- 方案
- 工業化
- 模塊化
- 隱私合規
- 動態化
- 項目管理
- 業務啟動優化
- 業務架構設計
- 性能優化case
- 性能優化-排查思路
- 性能優化-現有方案
- 登錄
- 搜索
- C++
- NDK入門
- 跨平臺
- H5
- Flutter
- Flutter 性能優化
- 數據跨平臺