Files
condition/condition_json_test.go
what a14d0f2c72 feat: Condition/ConditionExpr 支持 JSON 序列化/反序列化
给 Condition/ConditionExpr 加 MarshalJSON/UnmarshalJSON,中间过一层 DTO
(conditionDTO/exprDTO)避免 UnmarshalJSON 递归。FromMap(m map[string]any)
方便从已经解析好的 map(比如请求参数)直接构造 Condition,不用先序列化
成 JSON 字符串再解析一遍。
2026-08-21 08:57:07 +08:00

127 lines
2.9 KiB
Go

package condition_test
import (
"encoding/json"
"testing"
"git.fsdpf.net/go/condition"
"github.com/stretchr/testify/suite"
)
type conditionJSONTest struct {
suite.Suite
}
func TestConditionJSONSuite(t *testing.T) {
suite.Run(t, new(conditionJSONTest))
}
// 构造一个有代表性的多层条件
func buildTestCondition() *condition.Condition {
cond := condition.New(condition.Describe("测试"))
cond.SetExpr(condition.NewExpr("User", "name",
condition.Operator(condition.LIKE),
condition.Token("张三", condition.STRING),
))
cond.SetExpr(condition.NewExpr("User", "age",
condition.Operator(condition.GE),
condition.Token("18", condition.STRING),
))
sub := condition.New(condition.Type(condition.OR))
sub.SetExpr(condition.NewExpr("User", "status",
condition.Operator(condition.IN),
condition.Token("active", condition.STRING),
))
sub.SetExpr(condition.NewExpr("User", "roles",
condition.FieldSqlFn("json_contains", ""),
condition.Token("admin", condition.STRING),
))
cond.SetCondition(sub)
return cond
}
func (t *conditionJSONTest) TestMarshalUnmarshal() {
orig := buildTestCondition()
data, err := json.Marshal(orig)
t.Require().NoError(err)
t.T().Log("JSON:", string(data))
got := condition.New()
t.Require().NoError(json.Unmarshal(data, got))
// 二次序列化结果应一致
data2, err := json.Marshal(got)
t.Require().NoError(err)
t.Equal(string(data), string(data2))
}
func (t *conditionJSONTest) TestFromMap() {
m := map[string]any{
"type": "AND",
"describe": "来自Map",
"exprs": []any{
map[string]any{
"operator": "=",
"field": "name",
"fieldResource": "User",
"tokenType": "string",
"token": "张三",
},
map[string]any{
"operator": ">=",
"field": "age",
"fieldResource": "User",
"tokenType": "string",
"token": "18",
},
},
"childrens": []any{
map[string]any{
"type": "OR",
"exprs": []any{
map[string]any{
"operator": "IS NULL",
"field": "deleted_at",
"fieldResource": "User",
"tokenType": "string",
"token": "",
},
},
},
},
}
cond, err := condition.FromMap(m)
t.Require().NoError(err)
t.False(cond.IsEmpty())
data, err := json.Marshal(cond)
t.Require().NoError(err)
t.T().Log("FromMap JSON:", string(data))
}
func (t *conditionJSONTest) TestRoundTrip() {
orig := buildTestCondition()
// Condition → JSON → Condition → JSON,两次 JSON 应一致
data1, err := json.Marshal(orig)
t.Require().NoError(err)
cond2 := condition.New()
t.Require().NoError(json.Unmarshal(data1, cond2))
data2, err := json.Marshal(cond2)
t.Require().NoError(err)
t.JSONEq(string(data1), string(data2))
}
func (t *conditionJSONTest) TestFromMapEmpty() {
cond, err := condition.FromMap(map[string]any{})
t.Require().NoError(err)
t.True(cond.IsEmpty())
}