aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/json/v2_decode.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding/json/v2_decode.go')
-rw-r--r--src/encoding/json/v2_decode.go16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/encoding/json/v2_decode.go b/src/encoding/json/v2_decode.go
index 1041ec7ee4..f17d7ebcca 100644
--- a/src/encoding/json/v2_decode.go
+++ b/src/encoding/json/v2_decode.go
@@ -14,6 +14,7 @@ import (
"fmt"
"reflect"
"strconv"
+ "strings"
"encoding/json/internal/jsonwire"
"encoding/json/jsontext"
@@ -119,7 +120,20 @@ type UnmarshalTypeError struct {
func (e *UnmarshalTypeError) Error() string {
var s string
if e.Struct != "" || e.Field != "" {
- s = "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String()
+ // The design of UnmarshalTypeError overly assumes a struct-based
+ // Go representation for the JSON value.
+ // The logic in jsontext represents paths using a JSON Pointer,
+ // which is agnostic to the Go type system.
+ // Trying to convert a JSON Pointer into a UnmarshalTypeError.Field
+ // is difficult. As a heuristic, if the last path token looks like
+ // an index into a JSON array (e.g., ".foo.bar.0"),
+ // avoid the phrase "Go struct field ".
+ intoWhat := "Go struct field "
+ i := strings.LastIndexByte(e.Field, '.') + len(".")
+ if len(e.Field[i:]) > 0 && strings.TrimRight(e.Field[i:], "0123456789") == "" {
+ intoWhat = "" // likely a Go slice or array
+ }
+ s = "json: cannot unmarshal " + e.Value + " into " + intoWhat + e.Struct + "." + e.Field + " of type " + e.Type.String()
} else {
s = "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
}