整理代码结构, 增加普通结构体单元测试
This commit is contained in:
119
builder.go
119
builder.go
@ -7,73 +7,22 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
// Builder 运行时动态生成结构体的接口约束
|
||||
Builder interface {
|
||||
// AddField 添加结构体字段
|
||||
AddField(name string, pkg string, typ any, tag string, anonymous bool) Builder
|
||||
// RemoveField 移除指定名称的结构体字段
|
||||
RemoveField(name string) Builder
|
||||
// HasField 检测指定名称的结构体字段是否存在
|
||||
HasField(name string) bool
|
||||
// GetField 根据名称获取结构体字段定义
|
||||
GetField(name string) FieldConfig
|
||||
// Build 返回动态定义的结构体.
|
||||
Build() DynamicStruct
|
||||
}
|
||||
type nestedStruct struct {
|
||||
Field string
|
||||
Builder IBuilder
|
||||
Tag string
|
||||
}
|
||||
|
||||
// FieldConfig 结构体字段的定义.
|
||||
FieldConfig interface {
|
||||
// SetType 设置字段类型.
|
||||
SetType(typ any) FieldConfig
|
||||
// SetTag 设置字段 tag.
|
||||
SetTag(tag string) FieldConfig
|
||||
}
|
||||
|
||||
// DynamicStruct contains defined dynamic struct.
|
||||
// This definition can't be changed anymore, once is built.
|
||||
// It provides a method for creating new instances of same defintion.
|
||||
DynamicStruct interface {
|
||||
// New 获取结构体实例, 所有字段值均为对应类型的初始零值
|
||||
New() any
|
||||
|
||||
// NewSliceOfStructs slice实例化
|
||||
NewSliceOfStructs() any
|
||||
|
||||
// NewMapOfStructs map 或者 struct实例化
|
||||
NewMapOfStructs(key any) any
|
||||
}
|
||||
|
||||
nestedStruct struct {
|
||||
Field string
|
||||
Builder Builder
|
||||
Tag string
|
||||
}
|
||||
|
||||
builderImpl struct {
|
||||
fields []*fieldConfigImpl
|
||||
nestedStructTable map[string]nestedStruct // 嵌套结构体的定义, 父级路径 => 父级路径下挂接的子路径
|
||||
maxFieldDeep int // 字段嵌套最大深度
|
||||
structTagTable map[string]string // 字段路径 => json tag,最高优先级, 没传的时候会使用AddField的tag, 也为空使用手搓json tag
|
||||
}
|
||||
|
||||
fieldConfigImpl struct {
|
||||
name string
|
||||
pkg string
|
||||
typ any
|
||||
tag string
|
||||
anonymous bool
|
||||
}
|
||||
|
||||
dynamicStructImpl struct {
|
||||
structFields []reflect.StructField
|
||||
definition reflect.Type
|
||||
}
|
||||
)
|
||||
type builderImpl struct {
|
||||
fields []*fieldConfigImpl
|
||||
nestedStructTable map[string]nestedStruct // 嵌套结构体的定义, 父级路径 => 父级路径下挂接的子路径
|
||||
maxFieldDeep int // 字段嵌套最大深度
|
||||
structTagTable map[string]string // 字段路径 => json tag,最高优先级, 没传的时候会使用AddField的tag, 也为空使用手搓json tag
|
||||
}
|
||||
|
||||
// NewStruct 获取builder实例
|
||||
// 传入的tag映射表: 字段路径 => json tag,最高优先级, 没传的时候会使用AddField的tag, 也为空使用手搓json tag
|
||||
func NewStruct(structTagTable map[string]string) Builder {
|
||||
func NewStruct(structTagTable map[string]string) IBuilder {
|
||||
return &builderImpl{
|
||||
fields: []*fieldConfigImpl{},
|
||||
nestedStructTable: make(map[string]nestedStruct),
|
||||
@ -82,12 +31,12 @@ func NewStruct(structTagTable map[string]string) Builder {
|
||||
}
|
||||
|
||||
// ExtendStruct 基于已有结构体, 生成动态结构体(相当于继承指定的结构体属性)
|
||||
func ExtendStruct(value ...any) Builder {
|
||||
func ExtendStruct(value ...any) IBuilder {
|
||||
return MergeStructs(value...)
|
||||
}
|
||||
|
||||
// MergeStructs 多个结构体合并成一个动态结构体
|
||||
func MergeStructs(values ...any) Builder {
|
||||
func MergeStructs(values ...any) IBuilder {
|
||||
builder := NewStruct(map[string]string{})
|
||||
|
||||
for _, value := range values {
|
||||
@ -111,8 +60,8 @@ func (b *builderImpl) parseNestedField(fieldName string) ([]string, bool) {
|
||||
}
|
||||
|
||||
// AddField 添加结构体字段
|
||||
func (b *builderImpl) AddField(name string, pkg string, typ any, tag string, anonymous bool) Builder {
|
||||
// 瞎话线转驼峰, 传入的name实际对应序列化时的json tag
|
||||
func (b *builderImpl) AddField(name string, pkg string, typ any, tag string, anonymous bool) IBuilder {
|
||||
// 下划线转驼峰, 传入的name实际对应序列化时的json tag
|
||||
// name = wrapper.String(name).SnakeCaseToCamel()
|
||||
if cfgTag, exist := b.structTagTable[name]; exist && len(cfgTag) > 0 {
|
||||
tag = cfgTag
|
||||
@ -191,7 +140,7 @@ func (b *builderImpl) addNestedField(nameArr []string, pkg string, typ any, tag
|
||||
}
|
||||
|
||||
// RemoveField 根据名称移除结构体字段
|
||||
func (b *builderImpl) RemoveField(name string) Builder {
|
||||
func (b *builderImpl) RemoveField(name string) IBuilder {
|
||||
newFieldList := make([]*fieldConfigImpl, 0)
|
||||
for i := range b.fields {
|
||||
if b.fields[i].name == name {
|
||||
@ -214,7 +163,7 @@ func (b *builderImpl) HasField(name string) bool {
|
||||
}
|
||||
|
||||
// GetField 根据名称获取字段配置, 不存在, 返回nil
|
||||
func (b *builderImpl) GetField(name string) FieldConfig {
|
||||
func (b *builderImpl) GetField(name string) IFieldConfig {
|
||||
for i := range b.fields {
|
||||
if b.fields[i].name == name {
|
||||
return b.fields[i]
|
||||
@ -224,7 +173,7 @@ func (b *builderImpl) GetField(name string) FieldConfig {
|
||||
}
|
||||
|
||||
// Build 构建动态结构体
|
||||
func (b *builderImpl) Build() DynamicStruct {
|
||||
func (b *builderImpl) Build() IDynamicStruct {
|
||||
// 按照嵌套深度, 进行一次回溯处理
|
||||
for deep := b.maxFieldDeep - 1; deep > 0; deep-- {
|
||||
// 嵌套数据结构
|
||||
@ -281,7 +230,7 @@ func (b *builderImpl) Build() DynamicStruct {
|
||||
var structFields []reflect.StructField
|
||||
for _, field := range b.fields {
|
||||
if strings.Contains(field.name, ArraySplit) {
|
||||
// TODO : 临时过滤, 后续需要在正确逻辑处正确移除
|
||||
// 去除数组路径
|
||||
continue
|
||||
}
|
||||
structFields = append(structFields, reflect.StructField{
|
||||
@ -297,31 +246,3 @@ func (b *builderImpl) Build() DynamicStruct {
|
||||
definition: reflect.StructOf(structFields),
|
||||
}
|
||||
}
|
||||
|
||||
// SetType 设置字段类型
|
||||
func (f *fieldConfigImpl) SetType(typ any) FieldConfig {
|
||||
f.typ = typ
|
||||
return f
|
||||
}
|
||||
|
||||
// SetTag 设置字段标签
|
||||
func (f *fieldConfigImpl) SetTag(tag string) FieldConfig {
|
||||
f.tag = tag
|
||||
return f
|
||||
}
|
||||
|
||||
// New 创建动态结构体实例
|
||||
func (ds *dynamicStructImpl) New() any {
|
||||
// 不要指针,全部解引用
|
||||
return reflect.New(ds.definition).Interface()
|
||||
}
|
||||
|
||||
// NewSliceOfStructs 创建动态结构体切片实例
|
||||
func (ds *dynamicStructImpl) NewSliceOfStructs() any {
|
||||
return reflect.New(reflect.SliceOf(ds.definition)).Interface()
|
||||
}
|
||||
|
||||
// NewMapOfStructs 创建动态结构体map实例
|
||||
func (ds *dynamicStructImpl) NewMapOfStructs(key any) any {
|
||||
return reflect.New(reflect.MapOf(reflect.Indirect(reflect.ValueOf(key)).Type(), ds.definition)).Interface()
|
||||
}
|
||||
|
Reference in New Issue
Block a user