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  }