Files
go-sip/internal/config/json_keys.go
T

55 lines
1.2 KiB
Go

package config
import (
"encoding/json"
"errors"
"fmt"
)
// encoding/json accepts repeated object keys. Inspect the token stream before
// typed decoding so deployment settings cannot silently override earlier values.
func uniqueJSONKeys(decoder *json.Decoder, depth int) error {
if depth > 16 {
return errors.New("configuration nesting is too deep")
}
token, err := decoder.Token()
if err != nil {
return err
}
delimiter, compound := token.(json.Delim)
if !compound {
return nil
}
switch delimiter {
case '{':
seen := make(map[string]bool)
for decoder.More() {
keyToken, err := decoder.Token()
if err != nil {
return err
}
key, ok := keyToken.(string)
if !ok {
return errors.New("configuration object key must be a string")
}
if seen[key] {
return fmt.Errorf("duplicate configuration field %q", key)
}
seen[key] = true
if err := uniqueJSONKeys(decoder, depth+1); err != nil {
return err
}
}
case '[':
for decoder.More() {
if err := uniqueJSONKeys(decoder, depth+1); err != nil {
return err
}
}
default:
return errors.New("unexpected configuration JSON delimiter")
}
_, err = decoder.Token()
return err
}