编辑
2023-12-13
后端
00
请注意,本文编写于 513 天前,最后修改于 513 天前,其中某些信息可能已经过时。

目录

主要概念和类型
主要方法和功能
使用示例

这个库是一个把结构体转换为map的库,不支持标签

go
// KeyCase 表示输出键的大小写规范 type KeyCase int const ( NotSet KeyCase = iota // 不设置规范 CamelCase // 驼峰命名法 PascalCase // 帕斯卡命名法 SnakeCase // 蛇形命名法 ) var defaultCase = NotSet // 默认规范为不设置 // SetDefaultCase 用于设置默认的键规范 func SetDefaultCase(caseType KeyCase) { defaultCase = caseType } type mapModifier func(jsonMap) jsonMap type jsonMap map[string]interface{} // Predicate 是 func(interface{}) bool 的别名,用于测试是否包含某个字段 type Predicate func(interface{}) bool // KeyConverter 是 func(string) string 的别名,用于转换键的名称 type KeyConverter func(string) string // ValueConverter 是 func(interface{}) interface{} 的别名,用于转换值 type ValueConverter func(interface{}) interface{} // Serializer 是所有序列化方法的基础接口 type Serializer interface { Transform(entity interface{}) map[string]interface{} TransformArray(entities interface{}) ([]map[string]interface{}, error) MustTransformArray(entities interface{}) []map[string]interface{} ConvertKeys(keyConverter KeyConverter) Serializer UseSnakeCase() Serializer UseCamelCase() Serializer UsePascalCase() Serializer PickAll() Serializer Pick(keys ...string) Serializer PickIf(predicate Predicate, keys ...string) Serializer PickFunc(converter ValueConverter, keys ...string) Serializer PickFuncIf(predicate Predicate, converter ValueConverter, keys ...string) Serializer Omit(keys ...string) Serializer OmitIf(predicate Predicate, keys ...string) Serializer Add(key string, value interface{}) Serializer AddIf(predicate Predicate, key string, value interface{}) Serializer AddFunc(key string, converter ValueConverter) Serializer AddFuncIf(predicate Predicate, key string, converter ValueConverter) Serializer }

这里定义了一系列类型,包括 KeyCase 枚举类型、mapModifier 函数类型和别名类型 jsonMapPredicateKeyConverterValueConverter 以及 Serializer 接口。

go
func alwaysTrue(u interface{}) bool { return true } func alwaysFalse(u interface{}) bool { return false } func identity(u interface{}) interface{} { return u }

这里定义了三个用于作为默认参数的函数,alwaysTrue 总是返回 truealwaysFalse 总是返回 falseidentity 返回输入参数本身。

go
type Base struct { raw interface{} modifiers []mapModifier reflected reflect.Value keyConverter KeyConverter } func New() *Base { b := &Base{} b.addDefaultKeyConverter() return b }

Base 结构体是 Serializer 接口的基础实现,包含了原始数据 raw、一系列修改器函数 modifiers、反射得到的值 reflected 和键转换函数 keyConverter

New 函数返回一个新的 Base 实例,并调用 addDefaultKeyConverter 设置默认键转换函数。

go
func (b *Base) Transform(entity interface{}) map[string]interface{} { b.raw = entity b.reflected = reflect.Indirect(reflect.ValueOf(entity)) return b.result() }

Transform 方法将实体转换为 map[string]interface{},并设置 rawreflected 属性。

go
func (b *Base) TransformArray(entities interface{}) ([]map[string]interface{}, error) { s := reflect.ValueOf(entities) if s.Kind() != reflect.Slice && s.Kind() != reflect.Array { return nil, fmt.Errorf("TransformArray() given a non-slice type") } result := []map[string]interface{}{} for i := 0; i < s.Len(); i++ { result = append(result, b.Transform(s.Index(i).Interface())) } return result, nil } func (b *Base) MustTransformArray(entities interface{}) []map[string]interface{} { res, err := b.TransformArray(entities) if err != nil { panic(err) } return res }

TransformArray 方法将实体数组转换为 []map[string]interface{},并对输入类型进行检查。MustTransformArray 方法在 TransformArray 的基础上增加了 panic 处理。

go
func ( b *Base) addDefaultKeyConverter() { switch defaultCase { case PascalCase: b.UsePascalCase() case SnakeCase: b.UseSnakeCase() case CamelCase: b.UseCamelCase() default: break } } func (b *Base) transformedResult(result jsonMap) jsonMap { newResult := make(map[string]interface{}) for key, value := range result { newResult[b.keyConverter(key)] = value } return newResult } func (b *Base) result() map[string]interface{} { result := make(map[string]interface{}) for _, modifier := range b.modifiers { result = modifier(result) } if b.keyConverter != nil { return b.transformedResult(result) } return result }

addDefaultKeyConverter 方法根据默认键规范设置键转换函数。

transformedResult 方法使用键转换函数对结果进行转换。

result 方法应用所有修改器函数,并根据键转换函数进行最终结果的转换。

go
func (b *Base) ConvertKeys(keyConverter KeyConverter) Serializer { b.keyConverter = keyConverter return b } func (b *Base) UsePascalCase() Serializer { return b.ConvertKeys(func(k string) string { return xstrings.ToCamelCase(xstrings.ToSnakeCase(k)) }) } func (b *Base) UseCamelCase() Serializer { return b.ConvertKeys(func(k string) string { return xstrings.FirstRuneToLower(xstrings.ToCamelCase(xstrings.ToSnakeCase(k))) }) } func (b *Base) UseSnakeCase() Serializer { return b.ConvertKeys(xstrings.ToSnakeCase) }

ConvertKeys 方法用于设置键转换函数,UsePascalCaseUseCamelCaseUseSnakeCase 方法分别设置不同的键规范。

go
func (b *Base) PickAll() Serializer { b.modifiers = append(b.modifiers, func(m jsonMap) jsonMap { return structs.Map(b.raw) }) return b } func (b *Base) Pick(keys ...string) Serializer { return b.PickFunc(identity, keys...) } func (b *Base) PickIf(p Predicate, keys ...string) Serializer { return b.PickFuncIf(p, identity, keys...) } func (b *Base) PickFunc(converter ValueConverter, keys ...string) Serializer { return b.PickFuncIf(alwaysTrue, converter, keys...) } func (b *Base) PickFuncIf(p Predicate, converter ValueConverter, keys ...string) Serializer { b.modifiers = append(b.modifiers, func(m jsonMap) jsonMap { if p(b.raw) { for _, key := range keys { m[key] = converter(b.reflected.FieldByName(key).Interface()) } } return m }) return b }

PickAll 方法将所有公开字段添加到结果中。

Pick 方法添加指定字段到结果。

PickIf 方法添加指定字段到结果,仅当 Predicate 返回 true 时。

PickFunc 方法添加通过 ValueConverter 转换后的指定字段到结果。

PickFuncIf 方法添加通过 ValueConverter 转换后的指定字段到结果,仅当 Predicate 返回 true 时。

go
func (b *Base) Omit(keys ...string) Serializer { return b.OmitIf(alwaysTrue, keys...) } func (b *Base) OmitIf(p Predicate, keys ...string) Serializer { b.modifiers = append(b.modifiers, func(m jsonMap) jsonMap { if p(b.raw) { for _, key := range keys { delete(m, key) } } return m }) return b }

Omit 方法从结果中排除指定字段。

OmitIf 方法从结果中排除指定字段,仅当 Predicate 返回 true 时。

go
func (b *Base) Add(key string, value interface{}) Serializer { return b.AddIf(alwaysTrue, key, value) } func (b *Base) AddIf(p Predicate, key string, value interface{}) Serializer { return b.AddFuncIf(p, key, func(m interface{}) interface{} { return value }) } func (b *Base) AddFunc(key string, f ValueConverter) Serializer { return b.AddFuncIf(alwaysTrue, key, f) } func (b *Base) AddFuncIf(p Predicate, key string, f ValueConverter) Serializer { b.modifiers = append(b.modifiers, func(m jsonMap) jsonMap { if p(b.raw) { m[key] = f(b.raw) } return m }) return b }

Add 方法向结果中添加指定的自定义字段。

AddIf 方法向结果中添加指定的自定义字段,仅当 Predicate 返回 true 时。

AddFunc 方法向结果中添加通过 ValueConverter 转换后的自定义字段。

AddFuncIf 方法向结果中添加通过 ValueConverter 转换后的自定义字段,仅当 Predicate 返回 true 时。

这些方法允许用户添加自定义字段到结果中。

主要概念和类型

  1. KeyCase 枚举类型: 定义了表示键的命名规则的枚举类型,包括 NotSet(未设置)、CamelCase(驼峰命名法)、PascalCase(帕斯卡命名法)、SnakeCase(蛇形命名法)。

  2. mapModifier 函数类型: 用于修改输出的 map 的函数类型。

  3. jsonMap 类型: map[string]interface{} 的别名,用于表示 JSON 对象。

  4. Predicate、KeyConverter、ValueConverter 函数类型: 分别用于测试字段是否包含、转换键的名称、转换字段的值。

  5. Serializer 接口: 定义了所有序列化方法的接口。

  6. Base 结构体: 实现了 Serializer 接口的基础结构,包括对键的默认转换和一些常见的转换操作。

主要方法和功能

  1. New 函数: 创建一个新的 Serializer 实例。

  2. Transform 方法: 将实体(结构体)转换为 map[string]interface{}

  3. TransformArray 方法: 将实体数组(切片)转换为 []map[string]interface{}

  4. MustTransformArray 方法: 与 TransformArray 相同,但如果发生错误则引发 panic。

  5. ConvertKeys 方法: 设置键的命名规则。

  6. UsePascalCase、UseCamelCase、UseSnakeCase 方法: 设置键的命名规则为帕斯卡命名法、驼峰命名法、蛇形命名法。

  7. PickAll 方法: 添加所有导出字段到结果。

  8. Pick 方法: 添加指定的字段到结果。

  9. PickIf 方法: 如果满足条件,则添加指定的字段到结果。

  10. PickFunc 方法: 使用转换函数,添加指定的字段到结果。

  11. PickFuncIf 方法: 如果满足条件,则使用转换函数,添加指定的字段到结果。

  12. Omit 方法: 从结果中省略指定的字段。

  13. OmitIf 方法: 如果满足条件,则从结果中省略指定的字段。

  14. Add 方法: 添加自定义字段到结果。

  15. AddIf 方法: 如果满足条件,则添加自定义字段到结果。

  16. AddFunc 方法: 使用转换函数,添加计算的自定义字段到结果。

  17. AddFuncIf 方法: 如果满足条件,则使用转换函数,添加计算的自定义字段到结果。

使用示例

go
serializer := structomap.New().UseSnakeCase().Pick("FieldName").Add("CustomField", "some value") result := serializer.Transform(someStruct)

在上述示例中,创建了一个新的 structomap 实例,设置了键的命名规则为蛇形命名法,然后选择了结构体中名为 "FieldName" 的字段,添加了一个自定义字段 "CustomField" 到结果中,最后进行了转换。

这个库的设计允许用户根据需要选择转换的方式,非常适用于将结构体数据转换为 JSON 对象的场景。

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!