From 436ac02ebd63bedc7b6e8981790c4fe1ccf875c3 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 30 Mar 2018 15:50:27 -0400 Subject: [PATCH 1/2] Better error text for JSON syntax errors during schema parsing --- schema.go | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/schema.go b/schema.go index e024909..4b68a87 100644 --- a/schema.go +++ b/schema.go @@ -1,6 +1,7 @@ package avro import ( + "bytes" "encoding/json" "fmt" "io/ioutil" @@ -926,7 +927,11 @@ func ParseSchema(rawSchema string) (Schema, error) { func ParseSchemaWithRegistry(rawSchema string, schemas map[string]Schema) (Schema, error) { var schema interface{} if err := json.Unmarshal([]byte(rawSchema), &schema); err != nil { - schema = rawSchema + if syntaxErr, ok := err.(*json.SyntaxError); ok { + line, col, highlight := highlightPosition(rawSchema, syntaxErr.Offset, 3) + return nil, fmt.Errorf("Error at line %d, char %d (offset %d):\n%s\n%v", line, col, syntaxErr.Offset, highlight, err) + } + return nil, err } return schemaByType(schema, schemas, "") @@ -1181,3 +1186,26 @@ func dereference(v reflect.Value) reflect.Value { return v } + +func highlightPosition(s string, pos int64, scrollback int) (line, col int, highlight string) { + lines := make([]string, 0) + currentLine := new(bytes.Buffer) + for i := 0; i < int(pos); i++ { + c := s[i] + if c == '\n' { + lines = append(lines, currentLine.String()) + currentLine.Reset() + col = 1 + continue + } + col++ + currentLine.WriteByte(c) + } + lines = append(lines, currentLine.String()) + line = len(lines) + for i := len(lines) - scrollback; i < len(lines); i++ { + highlight += fmt.Sprintf("%5d: %s\n", i, lines[i]) + } + highlight += fmt.Sprintf("%s^\n", strings.Repeat(" ", col+5)) + return +} From 0ff56f7fdf267356456b1d41116c24ae3bd960b1 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 30 Mar 2018 16:33:23 -0400 Subject: [PATCH 2/2] Add special handling for primitve types --- schema.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/schema.go b/schema.go index 4b68a87..cd4e9a3 100644 --- a/schema.go +++ b/schema.go @@ -921,10 +921,25 @@ func ParseSchema(rawSchema string) (Schema, error) { return ParseSchemaWithRegistry(rawSchema, make(map[string]Schema)) } +var primitiveSchemas = map[string]Schema{ + "boolean": new(BooleanSchema), + "bytes": new(BytesSchema), + "double": new(DoubleSchema), + "float": new(FloatSchema), + "int": new(IntSchema), + "long": new(LongSchema), + "null": new(NullSchema), + "string": new(StringSchema), +} + // ParseSchemaWithRegistry parses a given schema using the provided registry for type lookup. // Registry will be filled up during parsing. // May return an error if schema is not parsable or has insufficient information about any type. func ParseSchemaWithRegistry(rawSchema string, schemas map[string]Schema) (Schema, error) { + // check if the provided schema is a primitive schema type + if schema, ok := primitiveSchemas[rawSchema]; ok { + return schema, nil + } var schema interface{} if err := json.Unmarshal([]byte(rawSchema), &schema); err != nil { if syntaxErr, ok := err.(*json.SyntaxError); ok {