Add strict mode to JSON parser (#6536)
This commit is contained in:
parent
41d6a1a787
commit
a9a0d4048a
|
@ -18,6 +18,10 @@ ignored unless specified in the `tag_key` or `json_string_fields` options.
|
|||
## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
|
||||
data_format = "json"
|
||||
|
||||
## When strict is true and a JSON array is being parsed, all objects within the
|
||||
## array must be valid
|
||||
strict = false
|
||||
|
||||
## Query is a GJSON path that specifies a specific chunk of JSON to be
|
||||
## parsed, if not specified the whole document will be parsed.
|
||||
##
|
||||
|
|
|
@ -32,6 +32,7 @@ type Config struct {
|
|||
TimeFormat string
|
||||
Timezone string
|
||||
DefaultTags map[string]string
|
||||
Strict bool
|
||||
}
|
||||
|
||||
type Parser struct {
|
||||
|
@ -44,6 +45,7 @@ type Parser struct {
|
|||
timeFormat string
|
||||
timezone string
|
||||
defaultTags map[string]string
|
||||
strict bool
|
||||
}
|
||||
|
||||
func New(config *Config) (*Parser, error) {
|
||||
|
@ -62,6 +64,7 @@ func New(config *Config) (*Parser, error) {
|
|||
timeFormat: config.TimeFormat,
|
||||
timezone: config.Timezone,
|
||||
defaultTags: config.DefaultTags,
|
||||
strict: config.Strict,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -73,7 +76,10 @@ func (p *Parser) parseArray(data []interface{}) ([]telegraf.Metric, error) {
|
|||
case map[string]interface{}:
|
||||
metrics, err := p.parseObject(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if p.strict {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
results = append(results, metrics...)
|
||||
default:
|
||||
|
|
|
@ -17,6 +17,7 @@ const (
|
|||
validJSONArrayMultiple = "[{\"a\": 5, \"b\": {\"c\": 6}}, {\"a\": 7, \"b\": {\"c\": 8}}]"
|
||||
invalidJSON = "I don't think this is JSON"
|
||||
invalidJSON2 = "{\"a\": 5, \"b\": \"c\": 6}}"
|
||||
mixedValidityJSON = "[{\"a\": 5, \"time\": \"2006-01-02T15:04:05\"}, {\"a\": 2}]"
|
||||
)
|
||||
|
||||
const validJSONTags = `
|
||||
|
@ -152,6 +153,41 @@ func TestParseInvalidJSON(t *testing.T) {
|
|||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestParseJSONImplicitStrictness(t *testing.T) {
|
||||
parserImplicitNoStrict, err := New(&Config{
|
||||
MetricName: "json_test",
|
||||
TimeKey: "time",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = parserImplicitNoStrict.Parse([]byte(mixedValidityJSON))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestParseJSONExplicitStrictnessFalse(t *testing.T) {
|
||||
parserNoStrict, err := New(&Config{
|
||||
MetricName: "json_test",
|
||||
TimeKey: "time",
|
||||
Strict: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = parserNoStrict.Parse([]byte(mixedValidityJSON))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestParseJSONExplicitStrictnessTrue(t *testing.T) {
|
||||
parserStrict, err := New(&Config{
|
||||
MetricName: "json_test",
|
||||
TimeKey: "time",
|
||||
Strict: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = parserStrict.Parse([]byte(mixedValidityJSON))
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestParseWithTagKeys(t *testing.T) {
|
||||
// Test that strings not matching tag keys are ignored
|
||||
parser, err := New(&Config{
|
||||
|
|
|
@ -89,6 +89,9 @@ type Config struct {
|
|||
// default timezone
|
||||
JSONTimezone string `toml:"json_timezone"`
|
||||
|
||||
// Whether to continue if a JSON object can't be coerced
|
||||
JSONStrict bool `toml:"json_strict"`
|
||||
|
||||
// Authentication file for collectd
|
||||
CollectdAuthFile string `toml:"collectd_auth_file"`
|
||||
// One of none (default), sign, or encrypt
|
||||
|
@ -164,6 +167,7 @@ func NewParser(config *Config) (Parser, error) {
|
|||
TimeFormat: config.JSONTimeFormat,
|
||||
Timezone: config.JSONTimezone,
|
||||
DefaultTags: config.DefaultTags,
|
||||
Strict: config.JSONStrict,
|
||||
},
|
||||
)
|
||||
case "value":
|
||||
|
|
Loading…
Reference in New Issue