reflux/rfx_json_test.go
what f5f261e541 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通信、配置持久化、数据传输、缓存、消息队列等
2025-12-08 17:22:05 +08:00

214 lines
4.7 KiB
Go

package reflux
import (
"encoding/json"
"testing"
)
// TestJSONMarshal 测试 JSON 序列化
func TestJSONMarshal(t *testing.T) {
t.Run("Marshal struct", func(t *testing.T) {
type Person struct {
Name string
Age int
}
person := Person{Name: "Alice", Age: 30}
r := New(&person)
data, err := json.Marshal(r)
if err != nil {
t.Fatalf("Marshal failed: %v", err)
}
expected := `{"Name":"Alice","Age":30}`
if string(data) != expected {
t.Errorf("Expected %s, got %s", expected, string(data))
}
})
t.Run("Marshal map", func(t *testing.T) {
m := map[string]any{
"name": "Bob",
"age": 25,
}
r := New(&m)
data, err := json.Marshal(r)
if err != nil {
t.Fatalf("Marshal failed: %v", err)
}
// 反序列化回来验证
var result map[string]any
if err := json.Unmarshal(data, &result); err != nil {
t.Fatalf("Unmarshal verification failed: %v", err)
}
if result["name"] != "Bob" || result["age"].(float64) != 25 {
t.Errorf("Unexpected result: %v", result)
}
})
t.Run("Marshal slice", func(t *testing.T) {
slice := []int{1, 2, 3, 4, 5}
r := New(&slice)
data, err := json.Marshal(r)
if err != nil {
t.Fatalf("Marshal failed: %v", err)
}
expected := `[1,2,3,4,5]`
if string(data) != expected {
t.Errorf("Expected %s, got %s", expected, string(data))
}
})
t.Run("Marshal nested structure", func(t *testing.T) {
type Address struct {
City string
Country string
}
type Person struct {
Name string
Age int
Address Address
}
person := Person{
Name: "Charlie",
Age: 35,
Address: Address{
City: "Beijing",
Country: "China",
},
}
r := New(&person)
data, err := json.Marshal(r)
if err != nil {
t.Fatalf("Marshal failed: %v", err)
}
// 验证可以正确反序列化
var result Person
if err := json.Unmarshal(data, &result); err != nil {
t.Fatalf("Unmarshal verification failed: %v", err)
}
if result.Name != "Charlie" || result.Age != 35 ||
result.Address.City != "Beijing" || result.Address.Country != "China" {
t.Errorf("Unexpected result: %v", result)
}
})
}
// TestJSONUnmarshal 测试 JSON 反序列化
func TestJSONUnmarshal(t *testing.T) {
t.Run("Unmarshal to struct", func(t *testing.T) {
type Person struct {
Name string
Age int
}
person := Person{}
r := New(&person)
jsonData := `{"Name":"David","Age":40}`
if err := json.Unmarshal([]byte(jsonData), r); err != nil {
t.Fatalf("Unmarshal failed: %v", err)
}
if r.Get("Name").String() != "David" || r.Get("Age").Int() != 40 {
t.Errorf("Unexpected values after unmarshal: Name=%s, Age=%d",
r.Get("Name").String(), r.Get("Age").Int())
}
})
t.Run("Unmarshal to map", func(t *testing.T) {
m := make(map[string]any)
r := New(&m)
jsonData := `{"name":"Eve","age":28,"active":true}`
if err := json.Unmarshal([]byte(jsonData), r); err != nil {
t.Fatalf("Unmarshal failed: %v", err)
}
if r.Get("name").String() != "Eve" {
t.Errorf("Expected name=Eve, got %s", r.Get("name").String())
}
if r.Get("age").Float64() != 28 {
t.Errorf("Expected age=28, got %v", r.Get("age").Float64())
}
if !r.Get("active").Bool() {
t.Error("Expected active=true")
}
})
t.Run("Unmarshal to slice", func(t *testing.T) {
slice := []int{}
r := New(&slice)
jsonData := `[10,20,30,40,50]`
if err := json.Unmarshal([]byte(jsonData), r); err != nil {
t.Fatalf("Unmarshal failed: %v", err)
}
arr := r.Array()
if len(arr) != 5 {
t.Fatalf("Expected 5 elements, got %d", len(arr))
}
for i, expected := range []int{10, 20, 30, 40, 50} {
if arr[i].Int() != expected {
t.Errorf("arr[%d]: expected %d, got %d", i, expected, arr[i].Int())
}
}
})
}
// TestJSONRoundTrip 测试序列化和反序列化往返
func TestJSONRoundTrip(t *testing.T) {
type TestCase struct {
Name string
Age int
Tags []string
}
original := TestCase{
Name: "Test",
Age: 99,
Tags: []string{"tag1", "tag2", "tag3"},
}
// 序列化
r1 := New(&original)
data, err := json.Marshal(r1)
if err != nil {
t.Fatalf("Marshal failed: %v", err)
}
// 反序列化
result := TestCase{}
r2 := New(&result)
if err := json.Unmarshal(data, r2); err != nil {
t.Fatalf("Unmarshal failed: %v", err)
}
// 验证
if r2.Get("Name").String() != "Test" {
t.Errorf("Name mismatch: got %s", r2.Get("Name").String())
}
if r2.Get("Age").Int() != 99 {
t.Errorf("Age mismatch: got %d", r2.Get("Age").Int())
}
tags := r2.Get("Tags").Array()
if len(tags) != 3 {
t.Fatalf("Tags length mismatch: got %d", len(tags))
}
for i, expected := range []string{"tag1", "tag2", "tag3"} {
if tags[i].String() != expected {
t.Errorf("Tags[%d] mismatch: expected %s, got %s", i, expected, tags[i].String())
}
}
}