feat: R 接口支持 JSON 序列化和反序列化
实现功能:
- R 接口继承 json.Marshaler 和 json.Unmarshaler 接口
- MarshalJSON(): 将 R 实例序列化为 JSON 字节数组
- UnmarshalJSON(): 从 JSON 字节数组反序列化到 R 实例
核心特性:
- 支持 struct、map、slice 等所有类型的 JSON 序列化
- 支持嵌套结构的序列化和反序列化
- 自动智能类型转换(如 JSON 数字 float64 -> int/int64)
- 可以对嵌套字段单独序列化(如 rfx.Get("Address"))
测试覆盖:
- TestJSONMarshal: 测试各种类型的序列化
- TestJSONUnmarshal: 测试各种类型的反序列化
- TestJSONRoundTrip: 测试序列化和反序列化的往返一致性
文档更新:
- 在 README 特性列表中添加 JSON 序列化说明
- 新增"JSON 序列化和反序列化"章节
- 包含完整的使用示例和最佳实践
- 说明使用场景:API通信、配置持久化、数据传输、缓存、消息队列等
This commit is contained in:
169
README.md
169
README.md
@@ -15,6 +15,7 @@ Reflux 是一个 Go 语言包,提供了统一的接口用于访问和操作嵌
|
||||
- 🔤 **大小写不敏感**: 支持使用小写字段名访问和修改结构体字段(包括 Map 键名)
|
||||
- 🔑 **键名提取**: Keys 方法可获取结构体或 Map 的所有键名
|
||||
- 📝 **JSON 集成**: Ptr() 方法返回的指针可直接用于 json.Unmarshal(),实现动态 JSON 反序列化
|
||||
- 🎯 **JSON 序列化**: 实现 json.Marshaler 和 json.Unmarshaler 接口,支持直接序列化和反序列化 R 实例
|
||||
- 🎯 **类型安全**: 使用反射但保证类型安全
|
||||
- 🔥 **增强类型转换**: 支持切片和结构体之间的智能转换(如 []any -> []T, map -> struct)
|
||||
- 🌀 **R 接口集成**: 支持直接传入 R 接口或 []R 切片,无缝集成反射值
|
||||
@@ -672,6 +673,174 @@ func main() {
|
||||
- 插件系统: 动态加载和更新插件配置
|
||||
- 热更新: 在运行时更新应用配置而无需重启
|
||||
|
||||
### 11. JSON 序列化和反序列化
|
||||
|
||||
R 接口实现了 `json.Marshaler` 和 `json.Unmarshaler` 接口,支持直接对 R 实例进行 JSON 序列化和反序列化:
|
||||
|
||||
#### JSON 序列化 (MarshalJSON)
|
||||
|
||||
```go
|
||||
import (
|
||||
"encoding/json"
|
||||
"git.fsdpf.net/go/reflux"
|
||||
)
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
Tags []string
|
||||
}
|
||||
|
||||
func main() {
|
||||
person := Person{
|
||||
Name: "Alice",
|
||||
Age: 30,
|
||||
Tags: []string{"developer", "golang"},
|
||||
}
|
||||
|
||||
rfx := reflux.New(&person)
|
||||
|
||||
// 直接序列化 R 实例
|
||||
data, err := json.Marshal(rfx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(string(data))
|
||||
// 输出: {"Name":"Alice","Age":30,"Tags":["developer","golang"]}
|
||||
}
|
||||
```
|
||||
|
||||
#### JSON 反序列化 (UnmarshalJSON)
|
||||
|
||||
```go
|
||||
func main() {
|
||||
person := Person{}
|
||||
rfx := reflux.New(&person)
|
||||
|
||||
jsonData := []byte(`{"Name":"Bob","Age":35,"Tags":["manager","python"]}`)
|
||||
|
||||
// 直接反序列化到 R 实例
|
||||
err := json.Unmarshal(jsonData, rfx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 数据已更新到原始对象
|
||||
fmt.Printf("%+v\n", person)
|
||||
// 输出: {Name:Bob Age:35 Tags:[manager python]}
|
||||
|
||||
// 也可以通过 R 接口访问
|
||||
fmt.Println(rfx.Get("Name").String()) // 输出: Bob
|
||||
fmt.Println(rfx.Get("Age").Int()) // 输出: 35
|
||||
}
|
||||
```
|
||||
|
||||
#### JSON 往返转换
|
||||
|
||||
```go
|
||||
func main() {
|
||||
// 原始数据
|
||||
original := map[string]any{
|
||||
"name": "Charlie",
|
||||
"age": 40,
|
||||
"active": true,
|
||||
}
|
||||
|
||||
rfx1 := reflux.New(&original)
|
||||
|
||||
// 序列化
|
||||
data, _ := json.Marshal(rfx1)
|
||||
|
||||
// 反序列化到新对象
|
||||
result := make(map[string]any)
|
||||
rfx2 := reflux.New(&result)
|
||||
json.Unmarshal(data, rfx2)
|
||||
|
||||
// 验证数据一致性
|
||||
fmt.Println(rfx2.Get("name").String()) // Charlie
|
||||
fmt.Println(rfx2.Get("age").Float64()) // 40 (JSON 数字默认 float64)
|
||||
fmt.Println(rfx2.Get("active").Bool()) // true
|
||||
}
|
||||
```
|
||||
|
||||
#### 嵌套结构序列化
|
||||
|
||||
```go
|
||||
type Address struct {
|
||||
City string
|
||||
Country string
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Age int
|
||||
Address Address
|
||||
}
|
||||
|
||||
func main() {
|
||||
user := User{
|
||||
Name: "David",
|
||||
Age: 45,
|
||||
Address: Address{
|
||||
City: "Beijing",
|
||||
Country: "China",
|
||||
},
|
||||
}
|
||||
|
||||
rfx := reflux.New(&user)
|
||||
|
||||
// 序列化整个嵌套结构
|
||||
data, _ := json.Marshal(rfx)
|
||||
fmt.Println(string(data))
|
||||
// 输出: {"Name":"David","Age":45,"Address":{"City":"Beijing","Country":"China"}}
|
||||
|
||||
// 只序列化某个嵌套字段
|
||||
addressData, _ := json.Marshal(rfx.Get("Address"))
|
||||
fmt.Println(string(addressData))
|
||||
// 输出: {"City":"Beijing","Country":"China"}
|
||||
}
|
||||
```
|
||||
|
||||
#### 智能类型转换
|
||||
|
||||
反序列化时,R 接口会自动进行类型转换:
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
Port int
|
||||
Timeout int64
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
config := Config{}
|
||||
rfx := reflux.New(&config)
|
||||
|
||||
// JSON 中的数字默认是 float64
|
||||
jsonData := []byte(`{"Port":8080,"Timeout":30,"Enabled":true}`)
|
||||
json.Unmarshal(jsonData, rfx)
|
||||
|
||||
// 自动转换为目标类型
|
||||
fmt.Printf("Port: %d (type: int)\n", config.Port) // 8080
|
||||
fmt.Printf("Timeout: %d (type: int64)\n", config.Timeout) // 30
|
||||
fmt.Printf("Enabled: %v (type: bool)\n", config.Enabled) // true
|
||||
}
|
||||
```
|
||||
|
||||
**使用场景**:
|
||||
- **API 通信**: 直接序列化 R 实例发送到 HTTP API
|
||||
- **配置持久化**: 将配置对象保存为 JSON 文件
|
||||
- **数据传输**: 在不同系统间传输复杂数据结构
|
||||
- **缓存系统**: 将对象序列化后存储到 Redis 等缓存
|
||||
- **消息队列**: 序列化后通过消息队列传输
|
||||
|
||||
**注意事项**:
|
||||
- 序列化会调用底层 `Any()` 方法获取实际值
|
||||
- 反序列化支持智能类型转换,使用 `setValue` 方法
|
||||
- 对于 struct 类型,会按字段名匹配反序列化
|
||||
- JSON 数字默认解析为 `float64`,会自动转换为目标类型
|
||||
|
||||
## 使用场景
|
||||
|
||||
### 1. 配置文件处理
|
||||
|
||||
Reference in New Issue
Block a user