EncodeStruct encodes struct from viper `tag` represent the fields when setting config, and the fields with `tag` shall prevail. `object` must be a pointer
(input *viper.Viper, output interface{}, tag string)
| 96 | // `tag` represent the fields when setting config, and the fields with `tag` shall prevail. |
| 97 | // `object` must be a pointer |
| 98 | func EncodeStruct(input *viper.Viper, output interface{}, tag string) errors.Error { |
| 99 | vf := reflect.ValueOf(output) |
| 100 | if vf.Kind() != reflect.Ptr { |
| 101 | return errors.Default.New(fmt.Sprintf("output %v is not a pointer", output)) |
| 102 | } |
| 103 | |
| 104 | for _, f := range utils.WalkFields(reflect.Indirect(vf).Type(), nil) { |
| 105 | fieldName := f.Name |
| 106 | fieldType := f.Type |
| 107 | fieldTag := f.Tag.Get(tag) |
| 108 | |
| 109 | // Check if the first letter is uppercase (indicates a public element, accessible) |
| 110 | ascii := rune(fieldName[0]) |
| 111 | if int(ascii) < int('A') || int(ascii) > int('Z') { |
| 112 | continue |
| 113 | } |
| 114 | |
| 115 | // View their tags in order to filter out members who don't have a valid tag set |
| 116 | if fieldTag == "" { |
| 117 | continue |
| 118 | } |
| 119 | vfField := vf.Elem().FieldByName(fieldName) |
| 120 | switch fieldType.Kind() { |
| 121 | case reflect.String: |
| 122 | vfField.SetString(input.GetString(fieldTag)) |
| 123 | case reflect.Int, reflect.Int64: |
| 124 | vfField.SetInt(input.GetInt64(fieldTag)) |
| 125 | case reflect.Float64: |
| 126 | vfField.SetFloat(input.GetFloat64(fieldTag)) |
| 127 | case reflect.Bool: |
| 128 | vfField.SetBool(input.GetBool(fieldTag)) |
| 129 | case reflect.Slice: |
| 130 | elem := vfField.Type().Elem() |
| 131 | switch elem.Kind() { |
| 132 | case reflect.String: |
| 133 | value := input.GetStringSlice(fieldTag) |
| 134 | stringSlice := reflect.MakeSlice(reflect.SliceOf(elem), 0, len(value)) |
| 135 | for _, item := range value { |
| 136 | stringSlice = reflect.Append(stringSlice, reflect.ValueOf(item)) |
| 137 | } |
| 138 | vfField.Set(stringSlice) |
| 139 | case reflect.Int: |
| 140 | value := input.GetIntSlice(fieldTag) |
| 141 | intSlice := reflect.MakeSlice(reflect.SliceOf(elem), 0, len(value)) |
| 142 | for _, item := range value { |
| 143 | intSlice = reflect.Append(intSlice, reflect.ValueOf(item)) |
| 144 | } |
| 145 | vfField.Set(intSlice) |
| 146 | } |
| 147 | case reflect.Map: |
| 148 | key := vfField.Type().Key() |
| 149 | elem := vfField.Type().Elem() |
| 150 | if key.Kind() == reflect.String { |
| 151 | mapType := reflect.MapOf(key, elem) |
| 152 | data := reflect.MakeMap(mapType) |
| 153 | switch elem.Kind() { |
| 154 | case reflect.String: |
| 155 | for k, value := range input.GetStringMapString(fieldTag) { |