123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
- //
- // This Source Code Form is subject to the terms of the MIT License.
- // If a copy of the MIT was not distributed with this file,
- // You can obtain one at https://github.com/gogf/gf.
- package structs
- import "reflect"
- // Tag returns the value associated with key in the tag string. If there is no
- // such key in the tag, Tag returns the empty string.
- func (f *Field) Tag(key string) string {
- return f.Field.Tag.Get(key)
- }
- // TagLookup returns the value associated with key in the tag string.
- // If the key is present in the tag the value (which may be empty)
- // is returned. Otherwise, the returned value will be the empty string.
- // The ok return value reports whether the value was explicitly set in
- // the tag string. If the tag does not have the conventional format,
- // the value returned by Lookup is unspecified.
- func (f *Field) TagLookup(key string) (value string, ok bool) {
- return f.Field.Tag.Lookup(key)
- }
- // IsEmbedded returns true if the given field is an anonymous field (embedded)
- func (f *Field) IsEmbedded() bool {
- return f.Field.Anonymous
- }
- // TagStr returns the tag string of the field.
- func (f *Field) TagStr() string {
- return string(f.Field.Tag)
- }
- // IsExported returns true if the given field is exported.
- func (f *Field) IsExported() bool {
- return f.Field.PkgPath == ""
- }
- // Name returns the name of the given field
- func (f *Field) Name() string {
- return f.Field.Name
- }
- // Type returns the type of the given field
- func (f *Field) Type() Type {
- return Type{
- Type: f.Field.Type,
- }
- }
- // Kind returns the reflect.Kind for Value of Field `f`.
- func (f *Field) Kind() reflect.Kind {
- return f.Value.Kind()
- }
- // OriginalKind retrieves and returns the original reflect.Kind for Value of Field `f`.
- func (f *Field) OriginalKind() reflect.Kind {
- var (
- kind = f.Value.Kind()
- value = f.Value
- )
- for kind == reflect.Ptr {
- value = value.Elem()
- kind = value.Kind()
- }
- return kind
- }
- const (
- RecursiveOptionNone = 0 // No recursively retrieving fields as map if the field is an embedded struct.
- RecursiveOptionEmbedded = 1 // Recursively retrieving fields as map if the field is an embedded struct.
- RecursiveOptionEmbeddedNoTag = 2 // Recursively retrieving fields as map if the field is an embedded struct and the field has no tag.
- )
- type FieldMapInput struct {
- // Pointer should be type of struct/*struct.
- Pointer interface{}
- // PriorityTagArray specifies the priority tag array for retrieving from high to low.
- // If it's given `nil`, it returns map[name]*Field, of which the `name` is attribute name.
- PriorityTagArray []string
- // RecursiveOption specifies the way retrieving the fields recursively if the attribute
- // is an embedded struct. It is RecursiveOptionNone in default.
- RecursiveOption int
- }
- // FieldMap retrieves and returns struct field as map[name/tag]*Field from `pointer`.
- //
- // The parameter `pointer` should be type of struct/*struct.
- //
- // The parameter `priority` specifies the priority tag array for retrieving from high to low.
- // If it's given `nil`, it returns map[name]*Field, of which the `name` is attribute name.
- //
- // The parameter `recursive` specifies the whether retrieving the fields recursively if the attribute
- // is an embedded struct.
- //
- // Note that it only retrieves the exported attributes with first letter up-case from struct.
- func FieldMap(input FieldMapInput) (map[string]*Field, error) {
- fields, err := getFieldValues(input.Pointer)
- if err != nil {
- return nil, err
- }
- var (
- tagValue = ""
- mapField = make(map[string]*Field)
- )
- for _, field := range fields {
- // Only retrieve exported attributes.
- if !field.IsExported() {
- continue
- }
- tagValue = ""
- for _, p := range input.PriorityTagArray {
- tagValue = field.Tag(p)
- if tagValue != "" && tagValue != "-" {
- break
- }
- }
- tempField := field
- tempField.TagValue = tagValue
- if tagValue != "" {
- mapField[tagValue] = tempField
- } else {
- if input.RecursiveOption != RecursiveOptionNone && field.IsEmbedded() {
- switch input.RecursiveOption {
- case RecursiveOptionEmbeddedNoTag:
- if field.TagStr() != "" {
- mapField[field.Name()] = tempField
- break
- }
- fallthrough
- case RecursiveOptionEmbedded:
- m, err := FieldMap(FieldMapInput{
- Pointer: field.Value,
- PriorityTagArray: input.PriorityTagArray,
- RecursiveOption: input.RecursiveOption,
- })
- if err != nil {
- return nil, err
- }
- for k, v := range m {
- if _, ok := mapField[k]; !ok {
- tempV := v
- mapField[k] = tempV
- }
- }
- }
- } else {
- mapField[field.Name()] = tempField
- }
- }
- }
- return mapField, nil
- }
|