|
@@ -1,14 +1,4 @@
|
|
|
-// Package yaml provides a wrapper around go-yaml designed to enable a better
|
|
|
|
|
-// way of handling YAML when marshaling to and from structs.
|
|
|
|
|
-//
|
|
|
|
|
-// In short, this package first converts YAML to JSON using go-yaml and then
|
|
|
|
|
-// uses json.Marshal and json.Unmarshal to convert to or from the struct. This
|
|
|
|
|
-// means that it effectively reuses the JSON struct tags as well as the custom
|
|
|
|
|
-// JSON methods MarshalJSON and UnmarshalJSON unlike go-yaml.
|
|
|
|
|
-//
|
|
|
|
|
-// See also http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang
|
|
|
|
|
-//
|
|
|
|
|
-package yaml // import "github.com/ghodss/yaml"
|
|
|
|
|
|
|
+package yaml
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
"bytes"
|
|
"bytes"
|
|
@@ -21,7 +11,7 @@ import (
|
|
|
"gopkg.in/yaml.v2"
|
|
"gopkg.in/yaml.v2"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-// Marshals the object into JSON then converts JSON to YAML and returns the
|
|
|
|
|
|
|
+// Marshal marshals the object into JSON then converts JSON to YAML and returns the
|
|
|
// YAML.
|
|
// YAML.
|
|
|
func Marshal(o interface{}) ([]byte, error) {
|
|
func Marshal(o interface{}) ([]byte, error) {
|
|
|
j, err := json.Marshal(o)
|
|
j, err := json.Marshal(o)
|
|
@@ -43,19 +33,24 @@ type JSONOpt func(*json.Decoder) *json.Decoder
|
|
|
// Unmarshal converts YAML to JSON then uses JSON to unmarshal into an object,
|
|
// Unmarshal converts YAML to JSON then uses JSON to unmarshal into an object,
|
|
|
// optionally configuring the behavior of the JSON unmarshal.
|
|
// optionally configuring the behavior of the JSON unmarshal.
|
|
|
func Unmarshal(y []byte, o interface{}, opts ...JSONOpt) error {
|
|
func Unmarshal(y []byte, o interface{}, opts ...JSONOpt) error {
|
|
|
- return unmarshal(yaml.Unmarshal, y, o, opts)
|
|
|
|
|
|
|
+ return yamlUnmarshal(y, o, false, opts...)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// UnmarshalStrict is like Unmarshal except that any mapping keys that are
|
|
|
|
|
-// duplicates will result in an error.
|
|
|
|
|
-// To also be strict about unknown fields, add the DisallowUnknownFields option.
|
|
|
|
|
|
|
+// UnmarshalStrict strictly converts YAML to JSON then uses JSON to unmarshal
|
|
|
|
|
+// into an object, optionally configuring the behavior of the JSON unmarshal.
|
|
|
func UnmarshalStrict(y []byte, o interface{}, opts ...JSONOpt) error {
|
|
func UnmarshalStrict(y []byte, o interface{}, opts ...JSONOpt) error {
|
|
|
- return unmarshal(yaml.UnmarshalStrict, y, o, opts)
|
|
|
|
|
|
|
+ return yamlUnmarshal(y, o, true, append(opts, DisallowUnknownFields)...)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func unmarshal(f func(in []byte, out interface{}) (err error), y []byte, o interface{}, opts []JSONOpt) error {
|
|
|
|
|
|
|
+// yamlUnmarshal unmarshals the given YAML byte stream into the given interface,
|
|
|
|
|
+// optionally performing the unmarshalling strictly
|
|
|
|
|
+func yamlUnmarshal(y []byte, o interface{}, strict bool, opts ...JSONOpt) error {
|
|
|
vo := reflect.ValueOf(o)
|
|
vo := reflect.ValueOf(o)
|
|
|
- j, err := yamlToJSON(y, &vo, f)
|
|
|
|
|
|
|
+ unmarshalFn := yaml.Unmarshal
|
|
|
|
|
+ if strict {
|
|
|
|
|
+ unmarshalFn = yaml.UnmarshalStrict
|
|
|
|
|
+ }
|
|
|
|
|
+ j, err := yamlToJSON(y, &vo, unmarshalFn)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return fmt.Errorf("error converting YAML to JSON: %v", err)
|
|
return fmt.Errorf("error converting YAML to JSON: %v", err)
|
|
|
}
|
|
}
|
|
@@ -83,7 +78,7 @@ func jsonUnmarshal(r io.Reader, o interface{}, opts ...JSONOpt) error {
|
|
|
return nil
|
|
return nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Convert JSON to YAML.
|
|
|
|
|
|
|
+// JSONToYAML Converts JSON to YAML.
|
|
|
func JSONToYAML(j []byte) ([]byte, error) {
|
|
func JSONToYAML(j []byte) ([]byte, error) {
|
|
|
// Convert the JSON to an object.
|
|
// Convert the JSON to an object.
|
|
|
var jsonObj interface{}
|
|
var jsonObj interface{}
|
|
@@ -134,7 +129,7 @@ func yamlToJSON(y []byte, jsonTarget *reflect.Value, yamlUnmarshal func([]byte,
|
|
|
// YAML objects are not completely compatible with JSON objects (e.g. you
|
|
// YAML objects are not completely compatible with JSON objects (e.g. you
|
|
|
// can have non-string keys in YAML). So, convert the YAML-compatible object
|
|
// can have non-string keys in YAML). So, convert the YAML-compatible object
|
|
|
// to a JSON-compatible object, failing with an error if irrecoverable
|
|
// to a JSON-compatible object, failing with an error if irrecoverable
|
|
|
- // incompatibilities happen along the way.
|
|
|
|
|
|
|
+ // incompatibilties happen along the way.
|
|
|
jsonObj, err := convertToJSONableObject(yamlObj, jsonTarget)
|
|
jsonObj, err := convertToJSONableObject(yamlObj, jsonTarget)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, err
|
|
return nil, err
|
|
@@ -321,6 +316,4 @@ func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (in
|
|
|
}
|
|
}
|
|
|
return yamlObj, nil
|
|
return yamlObj, nil
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- return nil, nil
|
|
|
|
|
}
|
|
}
|