reflect.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package jsonpointer
  2. import (
  3. "reflect"
  4. "strconv"
  5. "strings"
  6. )
  7. // Reflect gets the value at the specified path from a struct.
  8. func Reflect(o interface{}, path string) interface{} {
  9. if path == "" {
  10. return o
  11. }
  12. parts := parsePointer(path)
  13. var rv interface{} = o
  14. OUTER:
  15. for _, p := range parts {
  16. val := reflect.ValueOf(rv)
  17. if val.Kind() == reflect.Ptr {
  18. val = val.Elem()
  19. }
  20. if val.Kind() == reflect.Struct {
  21. typ := val.Type()
  22. for i := 0; i < typ.NumField(); i++ {
  23. sf := typ.Field(i)
  24. tag := sf.Tag.Get("json")
  25. name := parseJSONTagName(tag)
  26. if (name != "" && name == p) || sf.Name == p {
  27. rv = val.Field(i).Interface()
  28. continue OUTER
  29. }
  30. }
  31. // Found no matching field.
  32. return nil
  33. } else if val.Kind() == reflect.Map {
  34. // our pointer always gives us a string key
  35. // here we try to convert it into the correct type
  36. mapKey, canConvert := makeMapKeyFromString(val.Type().Key(), p)
  37. if canConvert {
  38. field := val.MapIndex(mapKey)
  39. if field.IsValid() {
  40. rv = field.Interface()
  41. } else {
  42. return nil
  43. }
  44. } else {
  45. return nil
  46. }
  47. } else if val.Kind() == reflect.Slice || val.Kind() == reflect.Array {
  48. i, err := strconv.Atoi(p)
  49. if err == nil && i < val.Len() {
  50. rv = val.Index(i).Interface()
  51. } else {
  52. return nil
  53. }
  54. } else {
  55. return nil
  56. }
  57. }
  58. return rv
  59. }
  60. // ReflectListPointers lists all possible pointers from the given struct.
  61. func ReflectListPointers(o interface{}) ([]string, error) {
  62. return reflectListPointersRecursive(o, ""), nil
  63. }
  64. func reflectListPointersRecursive(o interface{}, prefix string) []string {
  65. rv := []string{prefix + ""}
  66. val := reflect.ValueOf(o)
  67. if val.Kind() == reflect.Ptr {
  68. val = val.Elem()
  69. }
  70. if val.Kind() == reflect.Struct {
  71. typ := val.Type()
  72. for i := 0; i < typ.NumField(); i++ {
  73. child := val.Field(i).Interface()
  74. sf := typ.Field(i)
  75. tag := sf.Tag.Get("json")
  76. name := parseJSONTagName(tag)
  77. if name != "" {
  78. // use the tag name
  79. childReults := reflectListPointersRecursive(child, prefix+encodePointer([]string{name}))
  80. rv = append(rv, childReults...)
  81. } else {
  82. // use the original field name
  83. childResults := reflectListPointersRecursive(child, prefix+encodePointer([]string{sf.Name}))
  84. rv = append(rv, childResults...)
  85. }
  86. }
  87. } else if val.Kind() == reflect.Map {
  88. for _, k := range val.MapKeys() {
  89. child := val.MapIndex(k).Interface()
  90. mapKeyName := makeMapKeyName(k)
  91. childReults := reflectListPointersRecursive(child, prefix+encodePointer([]string{mapKeyName}))
  92. rv = append(rv, childReults...)
  93. }
  94. } else if val.Kind() == reflect.Slice || val.Kind() == reflect.Array {
  95. for i := 0; i < val.Len(); i++ {
  96. child := val.Index(i).Interface()
  97. childResults := reflectListPointersRecursive(child, prefix+encodePointer([]string{strconv.Itoa(i)}))
  98. rv = append(rv, childResults...)
  99. }
  100. }
  101. return rv
  102. }
  103. // makeMapKeyName takes a map key value and creates a string representation
  104. func makeMapKeyName(v reflect.Value) string {
  105. switch v.Kind() {
  106. case reflect.Float32, reflect.Float64:
  107. fv := v.Float()
  108. return strconv.FormatFloat(fv, 'f', -1, v.Type().Bits())
  109. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  110. iv := v.Int()
  111. return strconv.FormatInt(iv, 10)
  112. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  113. iv := v.Uint()
  114. return strconv.FormatUint(iv, 10)
  115. default:
  116. return v.String()
  117. }
  118. }
  119. // makeMapKeyFromString takes the key type for a map, and a string
  120. // representing the key, it then tries to convert the string
  121. // representation into a value of the correct type.
  122. func makeMapKeyFromString(mapKeyType reflect.Type, pointer string) (reflect.Value, bool) {
  123. valp := reflect.New(mapKeyType)
  124. val := reflect.Indirect(valp)
  125. switch mapKeyType.Kind() {
  126. case reflect.String:
  127. return reflect.ValueOf(pointer), true
  128. case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
  129. iv, err := strconv.ParseInt(pointer, 10, mapKeyType.Bits())
  130. if err == nil {
  131. val.SetInt(iv)
  132. return val, true
  133. }
  134. case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
  135. iv, err := strconv.ParseUint(pointer, 10, mapKeyType.Bits())
  136. if err == nil {
  137. val.SetUint(iv)
  138. return val, true
  139. }
  140. case reflect.Float32, reflect.Float64:
  141. fv, err := strconv.ParseFloat(pointer, mapKeyType.Bits())
  142. if err == nil {
  143. val.SetFloat(fv)
  144. return val, true
  145. }
  146. }
  147. return reflect.ValueOf(nil), false
  148. }
  149. // parseJSONTagName extracts the JSON field name from a struct tag
  150. func parseJSONTagName(tag string) string {
  151. if idx := strings.Index(tag, ","); idx != -1 {
  152. return tag[:idx]
  153. }
  154. return tag
  155. }