mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
Improve compatibility with JSON in config parser
The configuration format from the server is almost already a superset of JSON with exception of two cases: 1) trailing commas from values at the top level (although they are supported inside of maps) 2) initial and final brackets on the top level section. This change relaxes the two cases above to just skip those tokens so that the config syntax can also support valid JSON objects for configuring the server which might be helpful when generating it programmatically.
This commit is contained in:
@@ -73,6 +73,9 @@ const (
|
||||
sqStringStart = '\''
|
||||
sqStringEnd = '\''
|
||||
optValTerm = ';'
|
||||
topOptStart = '{'
|
||||
topOptValTerm = ','
|
||||
topOptTerm = '}'
|
||||
blockStart = '('
|
||||
blockEnd = ')'
|
||||
)
|
||||
@@ -234,6 +237,8 @@ func lexTop(lx *lexer) stateFn {
|
||||
}
|
||||
|
||||
switch r {
|
||||
case topOptStart:
|
||||
return lexSkip(lx, lexTop)
|
||||
case commentHashStart:
|
||||
lx.push(lexTop)
|
||||
return lexCommentStart
|
||||
@@ -280,7 +285,7 @@ func lexTopValueEnd(lx *lexer) stateFn {
|
||||
fallthrough
|
||||
case isWhitespace(r):
|
||||
return lexTopValueEnd
|
||||
case isNL(r) || r == eof || r == optValTerm:
|
||||
case isNL(r) || r == eof || r == optValTerm || r == topOptValTerm || r == topOptTerm:
|
||||
lx.ignore()
|
||||
return lexTop
|
||||
}
|
||||
|
||||
149
conf/lex_test.go
149
conf/lex_test.go
@@ -1049,3 +1049,152 @@ func TestMapInclude(t *testing.T) {
|
||||
lx = lex("foo { include \"users.conf\"}")
|
||||
expect(t, lx, expectedItems)
|
||||
}
|
||||
|
||||
func TestJSONCompat(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
input string
|
||||
expected []item
|
||||
}{
|
||||
{
|
||||
name: "should omit initial and final brackets at top level with a single item",
|
||||
input: `
|
||||
{
|
||||
"http_port": 8223
|
||||
}
|
||||
`,
|
||||
expected: []item{
|
||||
{itemKey, "http_port", 3},
|
||||
{itemInteger, "8223", 3},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should omit trailing commas at top level with two items",
|
||||
input: `
|
||||
{
|
||||
"http_port": 8223,
|
||||
"port": 4223
|
||||
}
|
||||
`,
|
||||
expected: []item{
|
||||
{itemKey, "http_port", 3},
|
||||
{itemInteger, "8223", 3},
|
||||
{itemKey, "port", 4},
|
||||
{itemInteger, "4223", 4},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should omit trailing commas at top level with multiple items",
|
||||
input: `
|
||||
{
|
||||
"http_port": 8223,
|
||||
"port": 4223,
|
||||
"max_payload": "5MB",
|
||||
"debug": true,
|
||||
"max_control_line": 1024
|
||||
}
|
||||
`,
|
||||
expected: []item{
|
||||
{itemKey, "http_port", 3},
|
||||
{itemInteger, "8223", 3},
|
||||
{itemKey, "port", 4},
|
||||
{itemInteger, "4223", 4},
|
||||
{itemKey, "max_payload", 5},
|
||||
{itemString, "5MB", 5},
|
||||
{itemKey, "debug", 6},
|
||||
{itemBool, "true", 6},
|
||||
{itemKey, "max_control_line", 7},
|
||||
{itemInteger, "1024", 7},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should support JSON not prettified",
|
||||
input: `{"http_port": 8224,"port": 4224}
|
||||
`,
|
||||
expected: []item{
|
||||
{itemKey, "http_port", 1},
|
||||
{itemInteger, "8224", 1},
|
||||
{itemKey, "port", 1},
|
||||
{itemInteger, "4224", 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should support JSON not prettified with final bracket after newline",
|
||||
input: `{"http_port": 8225,"port": 4225
|
||||
}
|
||||
`,
|
||||
expected: []item{
|
||||
{itemKey, "http_port", 1},
|
||||
{itemInteger, "8225", 1},
|
||||
{itemKey, "port", 1},
|
||||
{itemInteger, "4225", 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should support uglified JSON with inner blocks",
|
||||
input: `{"http_port": 8227,"port": 4227,"write_deadline": "1h","cluster": {"port": 6222,"routes": ["nats://127.0.0.1:4222","nats://127.0.0.1:4223","nats://127.0.0.1:4224"]}}
|
||||
`,
|
||||
expected: []item{
|
||||
{itemKey, "http_port", 1},
|
||||
{itemInteger, "8227", 1},
|
||||
{itemKey, "port", 1},
|
||||
{itemInteger, "4227", 1},
|
||||
{itemKey, "write_deadline", 1},
|
||||
{itemString, "1h", 1},
|
||||
{itemKey, "cluster", 1},
|
||||
{itemMapStart, "", 1},
|
||||
{itemKey, "port", 1},
|
||||
{itemInteger, "6222", 1},
|
||||
{itemKey, "routes", 1},
|
||||
{itemArrayStart, "", 1},
|
||||
{itemString, "nats://127.0.0.1:4222", 1},
|
||||
{itemString, "nats://127.0.0.1:4223", 1},
|
||||
{itemString, "nats://127.0.0.1:4224", 1},
|
||||
{itemArrayEnd, "", 1},
|
||||
{itemMapEnd, "", 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should support prettified JSON with inner blocks",
|
||||
input: `
|
||||
{
|
||||
"http_port": 8227,
|
||||
"port": 4227,
|
||||
"write_deadline": "1h",
|
||||
"cluster": {
|
||||
"port": 6222,
|
||||
"routes": [
|
||||
"nats://127.0.0.1:4222",
|
||||
"nats://127.0.0.1:4223",
|
||||
"nats://127.0.0.1:4224"
|
||||
]
|
||||
}
|
||||
}
|
||||
`,
|
||||
expected: []item{
|
||||
{itemKey, "http_port", 3},
|
||||
{itemInteger, "8227", 3},
|
||||
{itemKey, "port", 4},
|
||||
{itemInteger, "4227", 4},
|
||||
{itemKey, "write_deadline", 5},
|
||||
{itemString, "1h", 5},
|
||||
{itemKey, "cluster", 6},
|
||||
{itemMapStart, "", 6},
|
||||
{itemKey, "port", 7},
|
||||
{itemInteger, "6222", 7},
|
||||
{itemKey, "routes", 8},
|
||||
{itemArrayStart, "", 8},
|
||||
{itemString, "nats://127.0.0.1:4222", 9},
|
||||
{itemString, "nats://127.0.0.1:4223", 10},
|
||||
{itemString, "nats://127.0.0.1:4224", 11},
|
||||
{itemArrayEnd, "", 12},
|
||||
{itemMapEnd, "", 13},
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
lx := lex(test.input)
|
||||
expect(t, lx, test.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user