瀏覽代碼

Some 1.1 backward compatibility for bool values.

The boolean strings defined in the 1.1 spec (yes, on, etc) will now
work properly if they are unmarshaled into a typed bool value.
Gustavo Niemeyer 7 年之前
父節點
當前提交
01167db92b
共有 2 個文件被更改,包括 34 次插入2 次删除
  1. 11 0
      decode.go
  2. 23 2
      decode_test.go

+ 11 - 0
decode.go

@@ -627,6 +627,17 @@ func (d *decoder) scalar(n *Node, out reflect.Value) bool {
 		case bool:
 			out.SetBool(resolved)
 			return true
+		case string:
+			// This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
+			// It only works if explicitly attempting to unmarshal into a typed bool value.
+			switch resolved {
+			case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
+				out.SetBool(true)
+				return true
+			case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+				out.SetBool(false)
+				return true
+			}
 		}
 	case reflect.Float32, reflect.Float64:
 		switch resolved := resolved.(type) {

+ 23 - 2
decode_test.go

@@ -94,11 +94,28 @@ var unmarshalTests = []struct {
 	//{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported
 	//{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails.
 
-	// Bools from spec
+	// Bools are per 1.2 spec.
 	{
 		"canonical: true",
 		map[string]interface{}{"canonical": true},
 	},
+	// For backwards compatibility with 1.1, decoding old strings into typed values still works.
+	{
+		"option: on",
+		map[string]bool{"option": true},
+	}, {
+		"option: y",
+		map[string]bool{"option": true},
+	}, {
+		"option: Off",
+		map[string]bool{"option": false},
+	}, {
+		"option: No",
+		map[string]bool{"option": false},
+	}, {
+		"option: other",
+		map[string]bool{},
+	},
 	// Ints from spec
 	{
 		"canonical: 685230",
@@ -249,6 +266,10 @@ var unmarshalTests = []struct {
 		&struct {
 			B int "a"
 		}{1},
+	}, {
+		// Some limited backwards compatibility with the 1.1 spec.
+		"a: YES",
+		&struct{ A bool }{true},
 	},
 
 	// Some cross type conversions
@@ -1216,7 +1237,7 @@ var unmarshalStrictTests = []struct {
 	unique: true,
 	data:   "a: 1\nb: 2\na: 3\n",
 	value:  struct{ A, B int }{A: 3, B: 2},
-	error: `yaml: unmarshal errors:\n  line 3: mapping key "a" already defined at line 1`,
+	error:  `yaml: unmarshal errors:\n  line 3: mapping key "a" already defined at line 1`,
 }, {
 	unique: true,
 	data:   "c: 3\na: 1\nb: 2\nc: 4\n",