Tomjson 是一個「短小精悍」的 Java JSON 序列化庫,GitHub:https://github.com/luoxn28/tomjson
public class Person {
private String name; private int age; private double money;
private Dog dog; private List<Dog> dogs = new ArrayList<>();
// 構造器、getter/setter、toString 省略
}
public class Dog {
private String name;
// 構造器、getter/setter、toString 省略
}
Person person = new Person("luxon28", 23);
person.setMoney(13.14);
person.setDog(new Dog("gay"));
person.setDogs(Arrays.asList(new Dog("gay1"), new Dog("gar2")));
// 序列化
String json = TomJson.toJsonString(person);
System.out.println(json);
// 反序列化(無類型信息)
JsonObject jsonObj = TomJson.parseObject(json);
// 反序列化(指定類型)
Person person2 = TomJson.parseObject(json, Person.class);
tomjson ├── serializer # 序列化:各類型 Serializer + SerializerContext 配置 ├── deserializer # 反序列化:JsonObject、各類型 Deserializer + DeserializerContext ├── util # TinyUtil 工具類 └── test # 測試用例
入口:TomJson.toJsonString() → SerializerContext 獲取對應 JsonSerializer → 遞歸寫入 SerializerBuffer
// ObjectSerializer 核心邏輯
@Override
public void write(String name, Object object, SerializerBuffer buffer) {
Class clazz = object.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String key = field.getName();
PropertyDescriptor pd = new PropertyDescriptor(key, clazz);
Method readMethod = pd.getReadMethod();
Object value = readMethod.invoke(object); // 反射調用 getter
JsonSerializer writer = config.getObject(value.getClass());
writer.write(key, value, buffer); // 委派給具體類型 Serializer
}
}
關鍵點:反射獲取字段 → 讀方法調用取值 → 按類型分發序列化器 → 寫入緩衝區
核心難點:無類型信息的 JSON 如何還原對象圖
// 獲取同層級所有 key-value token,如 "name":"luxon28","age":23
private static List<String> getTokens(String text) {
List<String> tokens = new ArrayList<>();
Stack<Character> stack = new Stack<>();
text = TinyUtil.trimBrace(text.trim()); // 去除外層 {}
for (int i = 0, tokenStart = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c == '{' || c == '[') stack.push(c);
else if (c == '}' || c == ']') {
char pop = stack.pop();
if (!TinyUtil.flagOk(pop, c)) return Collections.emptyList(); // 格式錯誤
}
if (c == ',' && stack.isEmpty()) {
tokens.add(text.substring(tokenStart, i));
tokenStart = i + 1;
} else if (i == text.length() - 1 && stack.isEmpty()) {
tokens.add(text.substring(tokenStart));
}
}
return tokens;
}
public static <T> T parseObject(String text, Class<T> clazz) {
List<String> tokens = getTokens(text);
JsonObject jsonObj = new JsonObject();
for (String token : tokens) {
if (TinyUtil.isBeanKeyValue(token)) { // 普通鍵值對
parse(token, jsonObj.keyValue);
} else if (TinyUtil.isJsonBean(token)) { // 嵌套對象
String key = TinyUtil.getJsonKey(token);
String valueStr = TinyUtil.getJsonValue(token);
// 反射獲取字段泛型類型,遞歸解析
Field field = findField(clazz, key);
Class subClazz = extractGenericType(field);
Object subObj = parseObject(valueStr, subClazz);
jsonObj.keyValue.put(key, subObj);
} else if (TinyUtil.isJsonCollectionBean(token)) { // 集合
// 解析數組元素類型,逐個遞歸解析加入 List
}
}
// 反射實例化目標對象,逐字段賦值
T obj = clazz.newInstance();
for (Field field : clazz.getDeclaredFields()) {
if (jsonObj.keyValue.containsKey(field.getName())) {
new PropertyDescriptor(field.getName(), clazz).getWriteMethod()
.invoke(obj, jsonObj.keyValue.get(field.getName()));
}
}
return obj;
}
// 序列化類型映射表
public class SerializerContext {
private static Map<Class, JsonSerializer> config = new HashMap<>();
static {
config.put(String.class, new StringSerializer());
config.put(Integer.class, new IntegerSerializer());
config.put(Long.class, new LongSerializer());
config.put(Double.class, new DoubleSerializer());
config.put(Boolean.class, new BooleanSerializer());
// 集合、對象等通用處理器...
}
}
// 反序列化類型映射表
public class DeserializerContext {
private static Map<Class, JsonDeserializer> config = new HashMap<>();
static { /* 類似註冊各類型 Deserializer */ }
}
| 優點 | 缺點/局限 |
|---|---|
| 源碼極簡(<1000 行),極適合學習 JSON 庫原理 | 無 ASM 加速,大對象/高並發性能遜於 Fastjson/Jackson |
| 「專人專事」設計,邏輯清晰,易擴展自定義類型 | 反序列化依賴反射+泛型擷取,複雜泛型(Map<String, List<Foo>>)支撐弱 |
| 零依賴,引入即用 | 未嚴格遵循 JSON 標準(如日期格式、轉義字符處理) |
推薦場景:教學演示、輕量項目、嵌入式環境、需要深度定制序列化邏輯的場景。生產環境高性能場景請用 Fastjson/Jackson/Gson。