Joe Topjian | 1e9551c | 2017-06-03 10:35:33 -0600 | [diff] [blame] | 1 | package internal |
| 2 | |
| 3 | import ( |
| 4 | "reflect" |
Joe Topjian | fb5c0e8 | 2017-06-10 20:52:58 -0600 | [diff] [blame] | 5 | "strings" |
Joe Topjian | 1e9551c | 2017-06-03 10:35:33 -0600 | [diff] [blame] | 6 | ) |
| 7 | |
Joe Topjian | fb5c0e8 | 2017-06-10 20:52:58 -0600 | [diff] [blame] | 8 | // RemainingKeys will inspect a struct and compare it to a map. Any struct |
| 9 | // field that does not have a JSON tag that matches a key in the map or |
| 10 | // a matching lower-case field in the map will be returned as an extra. |
Joe Topjian | 1e9551c | 2017-06-03 10:35:33 -0600 | [diff] [blame] | 11 | // |
| 12 | // This is useful for determining the extra fields returned in response bodies |
| 13 | // for resources that can contain an arbitrary or dynamic number of fields. |
| 14 | func RemainingKeys(s interface{}, m map[string]interface{}) (extras map[string]interface{}) { |
| 15 | extras = make(map[string]interface{}) |
Joe Topjian | fb5c0e8 | 2017-06-10 20:52:58 -0600 | [diff] [blame] | 16 | for k, v := range m { |
| 17 | extras[k] = v |
| 18 | } |
| 19 | |
Joe Topjian | 1e9551c | 2017-06-03 10:35:33 -0600 | [diff] [blame] | 20 | valueOf := reflect.ValueOf(s) |
| 21 | typeOf := reflect.TypeOf(s) |
| 22 | for i := 0; i < valueOf.NumField(); i++ { |
| 23 | field := typeOf.Field(i) |
Joe Topjian | fb5c0e8 | 2017-06-10 20:52:58 -0600 | [diff] [blame] | 24 | |
| 25 | lowerField := strings.ToLower(field.Name) |
| 26 | delete(extras, lowerField) |
| 27 | |
| 28 | if tagValue := field.Tag.Get("json"); tagValue != "" && tagValue != "-" { |
| 29 | delete(extras, tagValue) |
Joe Topjian | 1e9551c | 2017-06-03 10:35:33 -0600 | [diff] [blame] | 30 | } |
| 31 | } |
| 32 | |
| 33 | return |
| 34 | } |