Skip to content

Commit 1a577c7

Browse files
committed
fix(scanner): treat colon as plain scalar content in flow mapping keys
In flow mapping context, a ':' not followed by whitespace, a flow indicator, or a quote should be part of the plain scalar key, not a mapping value indicator. This fixes parsing of inputs like {hello:world: [a,b,c]} where the key is the plain scalar 'hello:world'. Fixes #832
1 parent edee2f9 commit 1a577c7

2 files changed

Lines changed: 31 additions & 2 deletions

File tree

decode_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,26 @@ c:
12881288
source: "42: 100",
12891289
value: map[int]any{42: 100},
12901290
},
1291+
{
1292+
source: "{hello:world: [a,b,c]}",
1293+
value: map[string]any{"hello:world": []any{"a", "b", "c"}},
1294+
},
1295+
{
1296+
source: "{a:b:c: value}",
1297+
value: map[string]any{"a:b:c": "value"},
1298+
},
1299+
{
1300+
source: "{host:port: 8080, name: test}",
1301+
value: map[string]any{"host:port": uint64(8080), "name": "test"},
1302+
},
1303+
{
1304+
source: "{a:b: {c: d}}",
1305+
value: map[string]any{"a:b": map[string]any{"c": "d"}},
1306+
},
1307+
{
1308+
source: "{a:b: [1,2]}",
1309+
value: map[string]any{"a:b": []any{uint64(1), uint64(2)}},
1310+
},
12911311
}
12921312
for _, test := range tests {
12931313
t.Run(test.source, func(t *testing.T) {

scanner/scanner.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -983,8 +983,17 @@ func (s *Scanner) scanMapDelim(ctx *Context) (bool, error) {
983983
if s.startedFlowMapNum <= 0 && nc != ' ' && nc != '\t' && !s.isNewLineChar(nc) && !ctx.isNextEOS() {
984984
return false, nil
985985
}
986-
if s.startedFlowMapNum > 0 && nc == '/' {
987-
// like http://
986+
if s.startedFlowMapNum > 0 && len(ctx.buf) > 0 &&
987+
nc != ' ' && nc != '\t' && !s.isNewLineChar(nc) &&
988+
nc != ',' && nc != '}' && nc != ']' && nc != '[' && nc != '{' &&
989+
nc != '"' && nc != '\'' && !ctx.isNextEOS() {
990+
// In flow mapping context, when scanning a plain scalar key (buf is non-empty),
991+
// ':' is only a mapping value indicator when followed by whitespace,
992+
// a flow indicator (',', '}', ']'), a flow collection start ('[', '{'),
993+
// a quote ('"', '\''), or end of input.
994+
// This allows unquoted keys like 'hello:world' and URLs like 'http://example.com'.
995+
// When buf is empty the key was already tokenized (e.g. as a quoted string),
996+
// so ':' is unambiguously a mapping value indicator.
988997
return false, nil
989998
}
990999
if s.startedFlowMapNum > 0 {

0 commit comments

Comments
 (0)