Skip to content

序列化

Spire序列化(Serialization)是一个基于宏的自动序列化解决方案,通过简单的注解即可为类生成序列化和反序列化功能。它采用编译时代码生成的方式,提供高性能的序列化体验。

快速启动

只需要以下 3 个步骤即可开始使用序列化框架:

cangjie
import stdx.encoding.json.*
import spire_serialization.macros.*
import stdx.serialization.serialization.*

// 1. 使用@Serialization注解标记类
@Serialization
public class Student {
    // 2. 定义以_开头的字段
    private var _id: Int64 = 0
    private var _name: ?String = None
    private var _type: ?String = None

    public static func create() {
        return Student()
    }
}

main() {    
    // 3.创建对象并使用序列化功能
    let student = Student.create();
    student.id = 123456
    student.name = "cangjie"

    // 序列化为Json
    student.serialize().toJson() |> println

    // 反序列化
    let newStudent = Student.deserialize(DataModel.fromJson(student.serialize().toJson()))
    println("姓名: ${newStudent.name}")
}

说明

@Serialization 修饰的类如果没有实现无参构造方法,框架会自动实现一个私有无参构造方法,供反序列化使用

字段定义规范

字段命名规则

所有需要序列化的字段均以 “_” 开头才会被处理,并且需要序列化的字段必须声明为 var

cangjie
@Serialization
public class User {
    
    // 不以_开头的字段会被忽略
    private var userId: Int64 = 0  // 不会生成序列化代码
    private var status: String = "" // 不会生成序列化代码
    
    // 缺少类型标注会被忽略
    private var _age = 0 // 不会生成序列化代码

    // 不可变字段会被忽略
    private let _address: String = String.empty // 不会生成序列化代码

    // 非私有字段会被忽略
    public var _gender: Int64 = 0
}

属性覆盖

符合序列化规则的字段会自动生成属性,如果不需要,我们可以主动提供属性进行覆盖。 属性和字段的类型可以不一致,可以忽略setter

cangjie
public class Order {
    private let _items: ArrayList<OrderItem> = ArrayList<OrderItem>()

    // 使用同名属性覆盖
    public prop items: ReadOnlyList<OrderItem> {
        get() {
            _items
        }
    }
}

字段类型支持

框架支持多种数据类型的序列化:

cangjie
import stdx.encoding.json.*
import std.collection.*
import spire_serialization.macros.*
import stdx.serialization.serialization.*

// public class CantSerializable {} 没有实现序列化的类型

@Serialization
public class CantSerializable {}

@Serialization
public class DataTypes {
    // 基础类型
    private var _id: Int64 = 0
    private var _name: String = ""
    private var _price: Float64 = 0.0
    private var _active: Bool = false
    
    // 可选类型
    private var _description: ?String = None
    private var _categoryId: ?Int64 = None
    
    // 集合类型(需要元素类型支持序列化)
    private var _tags: Array<String> = []
    private var _metadata: HashMap<String, String> = HashMap<String, String>()

    // 实现序列化的类型
    private var canSerializable: CantSerializable = CantSerializable()

    // private var _cantserializable: CantSerializable = CantSerializable() // 不支持不可序列化的类型
}

main() {    
    let date = DataTypes()
    date.serialize().toJson() |> println
}

反序列化

从序列化数据重建对象:

cangjie
import stdx.encoding.json.*
import spire_serialization.macros.*
import stdx.serialization.serialization.*

@Serialization
class Order {
    private var _orderId: Int64 = 0
    private var _customerName: String = ""
    private var _amount: Float64 = 0.0
}

main() {    
    let jsonData = """
    	{"orderId": 1001, "customerName": "Spire", "amount": 199.99}
    """

    // 解析JSON为DataModel
    let jsonValue = JsonValue.fromStr(jsonData)
    let dataModel = DataModel.fromJson(jsonValue)

    // 反序列化为对象
    let order = Order.deserialize(dataModel) 
    println("Order ID: ${order.orderId} | "+"Customer: ${order.customerName} | "+"Amount: ${order.amount}")
}

字段映射

如果json字段使用的是下划线,但是代码不希望它是下划线

cangjie
@Serialization
public class Order {

    @DataField["user_name"]
    private var _userName: String = String.empty
}

字段注解支持

框架支持在字段上使用其他宏注解:

cangjie
@Serialization
public class Student {
    @Column["student_id"]
    @Description["学生唯一标识"]
    private let _id: Int64 = 0
    
    @Column["full_name"] 
    @Description["学生姓名"]
    private var _name: String = ""
    
    @Column["student_age"]
    @Description["学生年龄"] 
    private var _age: ?Int64 = None
}

注解兼容性

序列化宏能够正确处理字段上的其他宏注解,保持它们的功能不受影响

最佳实践

性能优化建议

  • 避免反射:序列化代码在编译时生成,运行时无反射开销
  • 类型安全:编译期类型检查,避免运行时类型错误
  • 内联优化:生成的代码可被编译器进一步优化
  • 避免深层嵌套:过深的对象嵌套可能影响序列化性能

架构设计

  • 命名规范:所有需要序列化的类都必须使用@Serialization注解
  • 嵌套对象:嵌套对象的类型也必须支持序列化
  • 字段命名规范:统一使用_前缀命名需要序列化的字段

开发建议

  • 合理使用可选类型:只在确实需要时使用?类型
  • 注解兼容性:序列化宏能够正确处理字段上的其他宏注解
  • 类型支持:确保所有字段类型都支持序列化接口