Getting line and character positions from Go's JSON unmarshal errors

It’s really easy to map JSON to structs in Go using the json.Unmarshal function, but the default error message doesn’t include information which would help to fix the input file, such as the line and character position in the input file.

I’d guess this is because it would be a performance hit to make the JSON parser count line breaks as its going along or something.

Unmarshalling invalid JSON looks something like this:

You can run it at

The output, showing the error messages is:

test 1 passed
test 2 failed with error: invalid character '\n' in string literal
test 3 failed with error: json: cannot unmarshal number into Go struct field data.key of type string

The snippet demonstrates the two main types of JSON unmarshalling errors.

JSON Syntax Errors

Situations where the JSON is invalid because of a missing curly brace or quote mark etc.

The implementation of the error interface returned by Go in this case is

JSON Type Errors

This is returned when the JSON type (string, number, array) can’t be converted to the Go type (e.g. string, int32, float64) on a struct because the two are incompatible.

In this case, the error is of type

Getting more information

The problem with the snippet above is that it just prints out the results of the Error() function, while the actual error types returned by the json.Unmarshal function contain more information, including the offset (in bytes) of the error. In some cases, we’d want to give that information to the end user to help them understand what’s going wrong.

This second version retrieves the extra data and uses a function I wrote to get the line and character position where the error occurred from the offset, which helps greatly if you’re troubleshooting problems.

It can be run from

The output this time is more detailed:

test 1 passed
test 2 failed with error: Cannot parse JSON schema due to a syntax error at line 2, character 2: invalid character '\n' in string literal
test 3 failed with error: The JSON type 'number' cannot be converted into the Go 'string' type on struct 'data', field 'key'. See input file line 3, character 1