# Toon-Java **Repository Path**: wuahhh/toon-java ## Basic Information - **Project Name**: Toon-Java - **Description**: TOON (Text-Oriented Object Notation) 是专为大型语言模型(LLM)交互设计的轻量级数据序列化格式,兼顾人类可读性与Token优化,比JSON节省30-60%的API调用成本。本库是TOON规范在Java 8环境下的生产级实现。 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2025-11-08 - **Last Updated**: 2025-11-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: toon, toon-java, toon-java8, toon-llm ## README # TOON-Java: 面向LLM的高效数据序列化库(JDK 1.8+) ![TOON Logo](doc/imges/toon-java-icon.png) > **TOON (Text-Oriented Object Notation)** 是专为大型语言模型(LLM)交互设计的轻量级数据序列化格式,兼顾人类可读性与Token优化,比JSON节省30-60%的API调用成本。本库是TOON规范在Java 8环境下的生产级实现。 ## 项目目标 1. 为Java开发者提供**低Token消耗**的LLM交互数据格式,降低API调用成本; 2. 保持**高可读性**,让开发者与LLM都能快速理解数据结构; 3. 支持复杂业务场景(嵌套对象、集合、自定义类型),兼容JDK 1.8及以上; 4. 提供灵活扩展能力,满足不同业务的类型转换、字段注释等个性化需求。 ## 核心优势 | 特性 | 说明 | |---------------------|---------------------------------------------------| | 🚀 **Token优化** | 表格化数据存储+元数据前置压缩,比JSON平均节省30-60% Token,大幅降低LLM调用成本 | | 🧠 **LLM友好** | 支持字段注释,元数据显式约束,减少模型解析幻觉,提升交互准确率 | | 📦 **全面兼容** | 支持基础类型、集合、嵌套对象、枚举、LocalDateTime等常用类型 | | 🔌 **灵活扩展** | 自定义类型转换器、字段注释、序列化策略,适配复杂业务场景 | | ⚡ **性能高效** | 反射字段缓存,避免重复解析类结构,高频场景性能提升50%以上 | | 🛡️ **健壮可靠** | 精细化异常体系+特殊字符处理,生产环境稳定可用 | ## 功能特性 ### 1. 基础功能 - ✅ 支持所有Java基础类型及包装类(int/Integer、long/Long等) - ✅ 支持String、枚举、LocalDateTime等常用类型 - ✅ 支持List/Set集合类型,自动校验数据长度 - ✅ 支持嵌套对象(无限层级),通过缩进标识层级关系 ### 2. 高级功能 - ✅ 字段注释:通过`@ToonField(comment="")`为字段添加说明,LLM可直接理解 - ✅ 自定义类型转换器:扩展支持Date、BigDecimal等业务类型 - ✅ 特殊字符处理:自动转义逗号、分号等分隔符,避免格式破坏 - ✅ 反射缓存:缓存类字段结构,提升高频序列化/反序列化性能 - ✅ 精细化异常:区分格式错误、类型转换失败、反射异常等场景,便于调试 ### 3. 兼容性 - 兼容JDK 1.8及以上版本 - 与TOON规范v1.3完全兼容 - 支持与JSON格式双向转换(需自行集成Jackson等JSON库) ## 快速开始 ### 1. 引入依赖(Maven) ```xml com.github toon-java 1.0-SNAPSHOT ``` ### 2. 定义实体类(带注释) ```java static class Address { @com.github.toon.anno.ToonField(order = 1, comment = "街道地址,含门牌号和单元号") private String street; @com.github.toon.anno.ToonField(order = 2, comment = "城市名称") private String city; public Address() {} // 反序列化需要默认构造函数 public Address(String street, String city) { this.street = street; this.city = city; } // getter和setter(序列化需要访问字段值) public String getStreet() { return street; } public String getCity() { return city; } } enum UserStatus { ACTIVE, INACTIVE } static class User { @com.github.toon.anno.ToonField(order = 1, comment = "用户唯一标识,自增ID") private int id; @com.github.toon.anno.ToonField(order = 2, comment = "用户姓名,最长32字符") private String name; @com.github.toon.anno.ToonField(order = 3, comment = "注册时间,ISO格式") private LocalDateTime registerTime; @com.github.toon.anno.ToonField(order = 4, comment = "用户状态(ACTIVE/INACTIVE)") private UserStatus status; @com.github.toon.anno.ToonField(order = 5, comment = "用户地址信息") private Address address; public User() {} // 反序列化需要默认构造函数 public User(int id, String name, LocalDateTime registerTime, UserStatus status, Address address) { this.id = id; this.name = name; this.registerTime = registerTime; this.status = status; this.address = address; } // getter和setter public int getId() { return id; } public String getName() { return name; } public LocalDateTime getRegisterTime() { return registerTime; } public UserStatus getStatus() { return status; } public Address getAddress() { return address; } } ``` ### 3. 序列化示例 ```java import com.github.toon.Toons; import com.github.toon.exception.ToonException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; public class QuickStartDemo { public static void main(String[] args) throws ToonException { // 1. 构建测试数据(含特殊字符、嵌套对象、枚举类型) Address homeAddr = new Address("123 Main St, Apt 4B", "New York"); // 包含逗号的字符串 Address workAddr = new Address("456 Business Ave", "San Francisco"); User user1 = new User( 1, "Alice", LocalDateTime.of(2024, 1, 1, 10, 30), UserStatus.ACTIVE, homeAddr ); User user2 = new User( 2, "Bob", LocalDateTime.of(2024, 2, 15, 14, 20), UserStatus.INACTIVE, workAddr ); List userList = new ArrayList<>(); userList.add(user1); userList.add(user2); // 2. 执行序列化(使用全局工具类) String toonStr = Toons.serialize("users", userList); System.out.println("集合序列化结果:\n" + toonStr); } } ``` ### 4. 输出结果 ```text TOON序列化结果: users(2){id#用户唯一标识,自增ID,name#用户姓名,最长32字符,registerTime#注册时间,ISO格式,status#用户状态(ACTIVE/INACTIVE),address#用户地址信息[$object],address.street#街道地址,含门牌号和单元号,address.city#城市名称}: 1,Alice,2024-01-01T10:30:00,ACTIVE,(123 Main St\, Apt 4B,New York); 2,Bob,2024-02-15T14:20:00,INACTIVE,(456 Business Ave,San Francisco); ``` ## 进阶用法 ### 1. 自定义类型转换器(以 BigDecimal 为例) ```java import com.github.toon.converter.TypeConverter; import com.github.toon.exception.ToonTypeConvertException; import java.math.BigDecimal; // 自定义BigDecimal转换器 public class BigDecimalConverter implements TypeConverter { @Override public boolean support(Class type) { return BigDecimal.class.equals(type); } @Override public Object convert(String value, Class type) throws ToonTypeConvertException { if (value == null || value.trim().isEmpty()) { return null; } try { return new BigDecimal(value.trim()); } catch (NumberFormatException e) { throw new ToonTypeConvertException("", type, value); } } @Override public String serialize(Object value) { return value == null ? "" : value.toString(); } } // 注册转换器 public class ConverterDemo { public static void main(String[] args) throws ToonException { DefaultToonSerializer serializer = new DefaultToonSerializer(); serializer.addConverter(new BigDecimalConverter()); DefaultToonDeserializer deserializer = new DefaultToonDeserializer(); deserializer.addConverter(new BigDecimalConverter()); // 后续序列化/反序列化可自动处理BigDecimal类型 } } ``` ### 2. 混合格式策略(JSON 存储 + TOON 入模) ```java import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.toon.exception.ToonException; import java.util.List; public class MixedFormatDemo { public static void main(String[] args) throws Exception { // 1. 构建数据 Address addr = new Address("123 Main St", "New York"); List users = List.of(new User(1, "Alice", LocalDateTime.now(), addr)); // 2. JSON序列化(存储/持久化) ObjectMapper objectMapper = new ObjectMapper(); String jsonStr = objectMapper.writeValueAsString(users); // 4. 转换为TOON(与LLM交互) String toonStr = Toons.serialize("users", jsonData); System.out.println("TOON格式(入模用):"); System.out.println(toonStr); } } ``` ## 适用场景 1. LLM API 调用:按 Token 计费的场景(如 OpenAI、Anthropic),大幅降低调用成本; 2. RAG 系统:知识库数据传输,兼顾可读性与传输效率; 3. AI Agent 交互:结构化指令传输,字段注释帮助 Agent 理解数据含义; 4. 成本敏感型 AI 项目:需要控制 API 开销的大规模 LLM 应用。 ## 不适用场景 1. 需跨语言极致兼容性(优先 JSON); 2. 深度嵌套的非表格化数据(JSON 更高效); 3. 对序列化速度要求极高且数据结构简单(可考虑 Protobuf)。 ## 贡献指南 ### 如何贡献 - Fork 本仓库; - 创建特性分支(git checkout -b feature/xxx); - 提交代码(git commit -m "feat: 新增xxx功能"); - 推送分支(git push origin feature/xxx); - 提交 Pull Request。 ### 代码规范 - 遵循 Google Java Code Style; - 新增功能需配套单元测试(覆盖率≥80%); - 不破坏原有 API 兼容性(除非重大版本迭代)。 ## 许可证 本项目基于 Apache License 2.0 开源,可自由用于商业和非商业项目。