首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Tomjson:輕量級 Java JSON 庫核心原理與源碼深度解析

     編輯:Java 綜合教學

一、項目簡介

Tomjson 是一個「短小精悍」的 Java JSON 序列化庫,GitHub:https://github.com/luoxn28/tomjson

  • 功能:JavaBean ↔ JSON 字符串雙向轉換
  • 特點:基於反射、架構簡單(4 個包)、易理解、小型對象序列化快
  • 對比:不像 Fastjson 使用 ASM 生成專用類,Tomjson 採用「專人專事」策略,每類型對應專屬 Serializer/Deserializer

二、快速上手

實體類定義

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           # 測試用例

四、核心原理深度解析

1. 序列化流程(Object → JSON)

入口: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
    }
}

關鍵點:反射獲取字段 → 讀方法調用取值 → 按類型分發序列化器 → 寫入緩衝區

2. 反序列化流程(JSON → Object)

核心難點:無類型信息的 JSON 如何還原對象圖

Step 1:Token 化(按層級分割)

// 獲取同層級所有 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;
}

Step 2:Token 類型判斷與遞歸解析

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;
}

3. 核心配置類

// 序列化類型映射表
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。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved