Quote YAML 1.1 bools at encoding time for compatibility with other legacy parsers (#354)

This commit is contained in:
Yusuke Kuoka 2023-03-14 15:24:34 +09:00 committed by GitHub
parent 11ad39b5c5
commit f3319d6c80
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 6 deletions

View file

@ -440,7 +440,7 @@ func TestEncoder(t *testing.T) {
}, },
{ {
"a:\n y: \"\"\n", "a:\n \"y\": \"\"\n",
struct { struct {
A *struct { A *struct {
X string `yaml:"x,omitempty"` X string `yaml:"x,omitempty"`
@ -702,7 +702,7 @@ func TestEncodeStructIncludeMap(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
expect := "a:\n m:\n x: y\n" expect := "a:\n m:\n x: \"y\"\n"
actual := string(bytes) actual := string(bytes)
if actual != expect { if actual != expect {
t.Fatalf("unexpected output. expect:[%s] actual:[%s]", expect, actual) t.Fatalf("unexpected output. expect:[%s] actual:[%s]", expect, actual)
@ -720,7 +720,7 @@ func TestEncodeDefinedTypeKeyMap(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("%+v", err) t.Fatalf("%+v", err)
} }
expect := "m:\n x: y\n" expect := "m:\n x: \"y\"\n"
actual := string(bytes) actual := string(bytes)
if actual != expect { if actual != expect {
t.Fatalf("unexpected output. expect:[%s] actual:[%s]", expect, actual) t.Fatalf("unexpected output. expect:[%s] actual:[%s]", expect, actual)

View file

@ -283,6 +283,28 @@ var (
"False", "False",
"FALSE", "FALSE",
} }
// For compatibility with other YAML 1.1 parsers
// Note that we use these solely for encoding the bool value with quotes.
// go-yaml should not treat these as reserved keywords at parsing time.
// as go-yaml is supposed to be compliant only with YAML 1.2.
reservedLegacyBoolKeywords = []string{
"y",
"Y",
"yes",
"Yes",
"YES",
"n",
"N",
"no",
"No",
"NO",
"on",
"On",
"ON",
"off",
"Off",
"OFF",
}
reservedInfKeywords = []string{ reservedInfKeywords = []string{
".inf", ".inf",
".Inf", ".Inf",
@ -297,6 +319,11 @@ var (
".NAN", ".NAN",
} }
reservedKeywordMap = map[string]func(string, string, *Position) *Token{} reservedKeywordMap = map[string]func(string, string, *Position) *Token{}
// reservedEncKeywordMap contains is the keyword map used at encoding time.
// This is supposed to be a superset of reservedKeywordMap,
// and used to quote legacy keywords present in YAML 1.1 or lesser for compatibility reasons,
// even though this library is supposed to be YAML 1.2-compliant.
reservedEncKeywordMap = map[string]func(string, string, *Position) *Token{}
) )
func reservedKeywordToken(typ Type, value, org string, pos *Position) *Token { func reservedKeywordToken(typ Type, value, org string, pos *Position) *Token {
@ -317,7 +344,14 @@ func init() {
} }
} }
for _, keyword := range reservedBoolKeywords { for _, keyword := range reservedBoolKeywords {
reservedKeywordMap[keyword] = func(value, org string, pos *Position) *Token { f := func(value, org string, pos *Position) *Token {
return reservedKeywordToken(BoolType, value, org, pos)
}
reservedKeywordMap[keyword] = f
reservedEncKeywordMap[keyword] = f
}
for _, keyword := range reservedLegacyBoolKeywords {
reservedEncKeywordMap[keyword] = func(value, org string, pos *Position) *Token {
return reservedKeywordToken(BoolType, value, org, pos) return reservedKeywordToken(BoolType, value, org, pos)
} }
} }
@ -581,7 +615,7 @@ func IsNeedQuoted(value string) bool {
if value == "" { if value == "" {
return true return true
} }
if _, exists := reservedKeywordMap[value]; exists { if _, exists := reservedEncKeywordMap[value]; exists {
return true return true
} }
if stat := getNumberStat(value); stat.isNum { if stat := getNumberStat(value); stat.isNum {

View file

@ -101,6 +101,22 @@ func TestIsNeedQuoted(t *testing.T) {
`"a b`, `"a b`,
"a:", "a:",
"a: b", "a: b",
"y",
"Y",
"yes",
"Yes",
"YES",
"n",
"N",
"no",
"No",
"NO",
"on",
"On",
"ON",
"off",
"Off",
"OFF",
} }
for i, test := range needQuotedTests { for i, test := range needQuotedTests {
if !token.IsNeedQuoted(test) { if !token.IsNeedQuoted(test) {

View file

@ -95,7 +95,7 @@ a:
b: hello b: hello
c: true c: true
d: d:
x: y x: "y"
b: b:
a: 2 a: 2
b: world b: world