github.com/lingyao2333/mo-zero@v1.4.1/core/mapping/yamlunmarshaler.go (about) 1 package mapping 2 3 import ( 4 "encoding/json" 5 "errors" 6 "io" 7 8 "gopkg.in/yaml.v2" 9 ) 10 11 // To make .json & .yaml consistent, we just use json as the tag key. 12 const yamlTagKey = "json" 13 14 var ( 15 // ErrUnsupportedType is an error that indicates the config format is not supported. 16 ErrUnsupportedType = errors.New("only map-like configs are supported") 17 18 yamlUnmarshaler = NewUnmarshaler(yamlTagKey) 19 ) 20 21 // UnmarshalYamlBytes unmarshals content into v. 22 func UnmarshalYamlBytes(content []byte, v interface{}) error { 23 return unmarshalYamlBytes(content, v, yamlUnmarshaler) 24 } 25 26 // UnmarshalYamlReader unmarshals content from reader into v. 27 func UnmarshalYamlReader(reader io.Reader, v interface{}) error { 28 return unmarshalYamlReader(reader, v, yamlUnmarshaler) 29 } 30 31 func cleanupInterfaceMap(in map[interface{}]interface{}) map[string]interface{} { 32 res := make(map[string]interface{}) 33 for k, v := range in { 34 res[Repr(k)] = cleanupMapValue(v) 35 } 36 return res 37 } 38 39 func cleanupInterfaceNumber(in interface{}) json.Number { 40 return json.Number(Repr(in)) 41 } 42 43 func cleanupInterfaceSlice(in []interface{}) []interface{} { 44 res := make([]interface{}, len(in)) 45 for i, v := range in { 46 res[i] = cleanupMapValue(v) 47 } 48 return res 49 } 50 51 func cleanupMapValue(v interface{}) interface{} { 52 switch v := v.(type) { 53 case []interface{}: 54 return cleanupInterfaceSlice(v) 55 case map[interface{}]interface{}: 56 return cleanupInterfaceMap(v) 57 case bool, string: 58 return v 59 case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64: 60 return cleanupInterfaceNumber(v) 61 default: 62 return Repr(v) 63 } 64 } 65 66 func unmarshal(unmarshaler *Unmarshaler, o, v interface{}) error { 67 if m, ok := o.(map[string]interface{}); ok { 68 return unmarshaler.Unmarshal(m, v) 69 } 70 71 return ErrUnsupportedType 72 } 73 74 func unmarshalYamlBytes(content []byte, v interface{}, unmarshaler *Unmarshaler) error { 75 var o interface{} 76 if err := yamlUnmarshal(content, &o); err != nil { 77 return err 78 } 79 80 return unmarshal(unmarshaler, o, v) 81 } 82 83 func unmarshalYamlReader(reader io.Reader, v interface{}, unmarshaler *Unmarshaler) error { 84 var res interface{} 85 if err := yaml.NewDecoder(reader).Decode(&res); err != nil { 86 return err 87 } 88 89 return unmarshal(unmarshaler, cleanupMapValue(res), v) 90 } 91 92 // yamlUnmarshal YAML to map[string]interface{} instead of map[interface{}]interface{}. 93 func yamlUnmarshal(in []byte, out interface{}) error { 94 var res interface{} 95 if err := yaml.Unmarshal(in, &res); err != nil { 96 return err 97 } 98 99 *out.(*interface{}) = cleanupMapValue(res) 100 return nil 101 }