github.com/3JoB/go-json@v0.10.4/internal/runtime/struct_field.go (about)

     1  package runtime
     2  
     3  import (
     4  	"strings"
     5  	"unicode"
     6  
     7  	"reflect"
     8  )
     9  
    10  func getTag(field reflect.StructField) string {
    11  	return field.Tag.Get("json")
    12  }
    13  
    14  func IsIgnoredStructField(field reflect.StructField) bool {
    15  	if field.PkgPath != "" {
    16  		if field.Anonymous {
    17  			t := field.Type
    18  			if t.Kind() == reflect.Ptr {
    19  				t = t.Elem()
    20  			}
    21  			if t.Kind() != reflect.Struct {
    22  				return true
    23  			}
    24  		} else {
    25  			// private field
    26  			return true
    27  		}
    28  	}
    29  	tag := getTag(field)
    30  	return tag == "-"
    31  }
    32  
    33  type StructTag struct {
    34  	Key         string
    35  	IsTaggedKey bool
    36  	IsOmitEmpty bool
    37  	IsString    bool
    38  	Field       reflect.StructField
    39  }
    40  
    41  type StructTags []*StructTag
    42  
    43  func (t StructTags) ExistsKey(key string) bool {
    44  	for _, tt := range t {
    45  		if tt.Key == key {
    46  			return true
    47  		}
    48  	}
    49  	return false
    50  }
    51  
    52  func isValidTag(s string) bool {
    53  	if s == "" {
    54  		return false
    55  	}
    56  	for _, c := range s {
    57  		switch {
    58  		case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
    59  			// Backslash and quote chars are reserved, but
    60  			// otherwise any punctuation chars are allowed
    61  			// in a tag name.
    62  		case !unicode.IsLetter(c) && !unicode.IsDigit(c):
    63  			return false
    64  		}
    65  	}
    66  	return true
    67  }
    68  
    69  func StructTagFromField(field reflect.StructField) *StructTag {
    70  	keyName := field.Name
    71  	tag := getTag(field)
    72  	st := &StructTag{Field: field}
    73  	opts := strings.Split(tag, ",")
    74  	if len(opts) > 0 {
    75  		if opts[0] != "" && isValidTag(opts[0]) {
    76  			keyName = opts[0]
    77  			st.IsTaggedKey = true
    78  		}
    79  	}
    80  	st.Key = keyName
    81  	if len(opts) > 1 {
    82  		for _, opt := range opts[1:] {
    83  			switch opt {
    84  			case "omitempty":
    85  				st.IsOmitEmpty = true
    86  			case "string":
    87  				st.IsString = true
    88  			}
    89  		}
    90  	}
    91  	return st
    92  }