mirror of
https://github.com/golang/go
synced 2024-11-21 17:44:40 -07:00
json: do not write to unexported fields
Fixes #977. Fixes #451. R=r, r2 CC=golang-dev https://golang.org/cl/2246049
This commit is contained in:
parent
00ffd59c1a
commit
a400b0e7d7
@ -82,6 +82,18 @@ func (e *UnmarshalTypeError) String() string {
|
|||||||
return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
|
return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An UnmarshalFieldError describes a JSON object key that
|
||||||
|
// led to an unexported (and therefore unwritable) struct field.
|
||||||
|
type UnmarshalFieldError struct {
|
||||||
|
Key string
|
||||||
|
Type *reflect.StructType
|
||||||
|
Field reflect.StructField
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *UnmarshalFieldError) String() string {
|
||||||
|
return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
|
||||||
|
}
|
||||||
|
|
||||||
// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
|
// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
|
||||||
// (The argument to Unmarshal must be a non-nil pointer.)
|
// (The argument to Unmarshal must be a non-nil pointer.)
|
||||||
type InvalidUnmarshalError struct {
|
type InvalidUnmarshalError struct {
|
||||||
@ -450,20 +462,32 @@ func (d *decodeState) object(v reflect.Value) {
|
|||||||
if mv != nil {
|
if mv != nil {
|
||||||
subv = reflect.MakeZero(mv.Type().(*reflect.MapType).Elem())
|
subv = reflect.MakeZero(mv.Type().(*reflect.MapType).Elem())
|
||||||
} else {
|
} else {
|
||||||
|
var f reflect.StructField
|
||||||
|
var ok bool
|
||||||
// First try for field with that tag.
|
// First try for field with that tag.
|
||||||
|
st := sv.Type().(*reflect.StructType)
|
||||||
for i := 0; i < sv.NumField(); i++ {
|
for i := 0; i < sv.NumField(); i++ {
|
||||||
f := sv.Type().(*reflect.StructType).Field(i)
|
f = st.Field(i)
|
||||||
if f.Tag == key {
|
if f.Tag == key {
|
||||||
subv = sv.Field(i)
|
ok = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if subv == nil {
|
if !ok {
|
||||||
// Second, exact match.
|
// Second, exact match.
|
||||||
subv = sv.FieldByName(key)
|
f, ok = st.FieldByName(key)
|
||||||
if subv == nil {
|
}
|
||||||
// Third, case-insensitive match.
|
if !ok {
|
||||||
subv = sv.FieldByNameFunc(func(s string) bool { return matchName(key, s) })
|
// Third, case-insensitive match.
|
||||||
|
f, ok = st.FieldByNameFunc(func(s string) bool { return matchName(key, s) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract value; name must be exported.
|
||||||
|
if ok {
|
||||||
|
if f.PkgPath != "" {
|
||||||
|
d.saveError(&UnmarshalFieldError{key, st, f})
|
||||||
|
} else {
|
||||||
|
subv = sv.FieldByIndex(f.Index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,12 @@ type T struct {
|
|||||||
Y int
|
Y int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type tx struct {
|
||||||
|
x int
|
||||||
|
}
|
||||||
|
|
||||||
|
var txType = reflect.Typeof((*tx)(nil)).(*reflect.PtrType).Elem().(*reflect.StructType)
|
||||||
|
|
||||||
type unmarshalTest struct {
|
type unmarshalTest struct {
|
||||||
in string
|
in string
|
||||||
ptr interface{}
|
ptr interface{}
|
||||||
@ -36,6 +42,7 @@ var unmarshalTests = []unmarshalTest{
|
|||||||
unmarshalTest{`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
|
unmarshalTest{`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
|
||||||
unmarshalTest{"null", new(interface{}), nil, nil},
|
unmarshalTest{"null", new(interface{}), nil, nil},
|
||||||
unmarshalTest{`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.Typeof("")}},
|
unmarshalTest{`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.Typeof("")}},
|
||||||
|
unmarshalTest{`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
|
||||||
|
|
||||||
// syntax errors
|
// syntax errors
|
||||||
unmarshalTest{`{"X": "foo", "Y"}`, nil, nil, SyntaxError("invalid character '}' after object key")},
|
unmarshalTest{`{"X": "foo", "Y"}`, nil, nil, SyntaxError("invalid character '}' after object key")},
|
||||||
|
Loading…
Reference in New Issue
Block a user