github.com/blend/go-sdk@v1.20220411.3/reflectutil/decompose_strings.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package reflectutil 9 10 import ( 11 "encoding/base64" 12 "fmt" 13 "reflect" 14 "strings" 15 ) 16 17 // DecomposeStrings decomposes an object into a string map. 18 func DecomposeStrings(obj interface{}, tagName ...string) map[string]string { 19 output := map[string]string{} 20 21 objMeta := reflectType(obj) 22 objValue := reflectValue(obj) 23 24 var field reflect.StructField 25 var fieldValue reflect.Value 26 var tag, tagValue string 27 var dataField string 28 var pieces []string 29 var isCSV bool 30 var isBytes bool 31 var isBase64 bool 32 33 if len(tagName) > 0 { 34 tag = tagName[0] 35 } 36 37 for x := 0; x < objMeta.NumField(); x++ { 38 isCSV = false 39 isBytes = false 40 isBase64 = false 41 42 field = objMeta.Field(x) 43 if !IsExported(field.Name) { 44 continue 45 } 46 47 fieldValue = objValue.FieldByName(field.Name) 48 dataField = field.Name 49 50 if field.Type.Kind() == reflect.Struct { 51 childFields := DecomposeStrings(fieldValue.Interface(), tagName...) 52 for key, value := range childFields { 53 output[key] = value 54 } 55 } 56 57 if len(tag) > 0 { 58 tagValue = field.Tag.Get(tag) 59 if len(tagValue) > 0 { 60 if field.Type.Kind() == reflect.Map { 61 continue 62 } else { 63 pieces = strings.Split(tagValue, ",") 64 dataField = pieces[0] 65 66 if len(pieces) > 1 { 67 for y := 1; y < len(pieces); y++ { 68 if pieces[y] == FieldFlagCSV { 69 isCSV = true 70 } else if pieces[y] == FieldFlagBase64 { 71 isBase64 = true 72 } else if pieces[y] == FieldFlagBytes { 73 isBytes = true 74 } 75 } 76 } 77 } 78 } 79 } 80 81 if isCSV { 82 if typed, isTyped := fieldValue.Interface().([]string); isTyped { 83 output[dataField] = strings.Join(typed, ",") 84 } 85 } else if isBytes { 86 if typed, isTyped := fieldValue.Interface().([]byte); isTyped { 87 output[dataField] = string(typed) 88 } 89 } else if isBase64 { 90 if typed, isTyped := fieldValue.Interface().([]byte); isTyped { 91 output[dataField] = base64.StdEncoding.EncodeToString(typed) 92 } 93 if typed, isTyped := fieldValue.Interface().(string); isTyped { 94 output[dataField] = typed 95 } 96 } else { 97 output[dataField] = fmt.Sprintf("%v", FollowValue(fieldValue)) 98 } 99 } 100 101 return output 102 }