github.com/Jeffail/benthos/v3@v3.65.0/lib/util/config/sanitised.go (about) 1 package config 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "sort" 7 8 "gopkg.in/yaml.v3" 9 ) 10 11 //------------------------------------------------------------------------------ 12 13 // SanitizeComponent performs a generic sanitation on a component config, where 14 // a type field describes the type of the component, and the only other fields 15 // returned in the sanitized result are under the namespace of the type. 16 func SanitizeComponent(conf interface{}) (Sanitised, error) { 17 cBytes, err := yaml.Marshal(conf) 18 if err != nil { 19 return nil, err 20 } 21 22 hashMap := map[string]interface{}{} 23 if err := yaml.Unmarshal(cBytes, &hashMap); err != nil { 24 return nil, err 25 } 26 27 return Sanitised(hashMap), nil 28 } 29 30 //------------------------------------------------------------------------------ 31 32 // Sanitised is a general map[string]interface{} type that tries to marshal into 33 // both YAML and JSON in a way that ensure the 'type' field is always first. 34 type Sanitised map[string]interface{} 35 36 // SanitForYAML a map to be embedded within a parent object for YAML 37 // marshalling. 38 type SanitForYAML map[string]interface{} 39 40 // MarshalYAML return the config as YAML with the 'type' field first. 41 func (s Sanitised) MarshalYAML() (interface{}, error) { 42 dynObj := SanitForYAML{} 43 44 var typeVal interface{} 45 for k, v := range s { 46 if k == "type" { 47 typeVal = v 48 } else { 49 dynObj[k] = v 50 } 51 } 52 53 return struct { 54 Type interface{} `yaml:"type"` 55 SanitForYAML `yaml:",inline"` 56 }{ 57 Type: typeVal, 58 SanitForYAML: dynObj, 59 }, nil 60 } 61 62 // MarshalJSON return the config as a JSON blob with the 'type' field first. 63 func (s Sanitised) MarshalJSON() ([]byte, error) { 64 var keys []string 65 var typeVal interface{} 66 67 for k, v := range s { 68 if k == "type" { 69 typeVal = v 70 } else { 71 keys = append(keys, k) 72 } 73 } 74 75 sort.Strings(keys) 76 77 var buf bytes.Buffer 78 buf.WriteByte('{') 79 80 if typeVal != nil { 81 typeBytes, err := json.Marshal(typeVal) 82 if err != nil { 83 return nil, err 84 } 85 86 buf.WriteString(`"type":`) 87 buf.Write(typeBytes) 88 89 if len(keys) > 0 { 90 buf.WriteByte(',') 91 } 92 } 93 94 for i, k := range keys { 95 valBytes, err := json.Marshal(s[k]) 96 if err != nil { 97 return nil, err 98 } 99 100 buf.WriteByte('"') 101 buf.WriteString(k) 102 buf.WriteString(`":`) 103 buf.Write(valBytes) 104 105 if i < len(keys)-1 { 106 buf.WriteByte(',') 107 } 108 } 109 110 buf.WriteByte('}') 111 return buf.Bytes(), nil 112 } 113 114 //------------------------------------------------------------------------------