[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 性能优化
- 数据跨平台