mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
json: only use alphanumeric tags
Almost the same definition as Go identifier names. (Leading digits are allowed.) Fixes #1520. R=r, r2 CC=golang-dev https://golang.org/cl/4173061
This commit is contained in:
parent
6e03ed32c7
commit
f80d002438
3 changed files with 33 additions and 9 deletions
|
|
@ -466,13 +466,15 @@ func (d *decodeState) object(v reflect.Value) {
|
||||||
} else {
|
} else {
|
||||||
var f reflect.StructField
|
var f reflect.StructField
|
||||||
var ok bool
|
var ok bool
|
||||||
// First try for field with that tag.
|
|
||||||
st := sv.Type().(*reflect.StructType)
|
st := sv.Type().(*reflect.StructType)
|
||||||
for i := 0; i < sv.NumField(); i++ {
|
// First try for field with that tag.
|
||||||
f = st.Field(i)
|
if isValidTag(key) {
|
||||||
if f.Tag == key {
|
for i := 0; i < sv.NumField(); i++ {
|
||||||
ok = true
|
f = st.Field(i)
|
||||||
break
|
if f.Tag == key {
|
||||||
|
ok = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,11 @@ var (
|
||||||
umtrue = unmarshaler{true}
|
umtrue = unmarshaler{true}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type badTag struct {
|
||||||
|
X string
|
||||||
|
Y string "y"
|
||||||
|
Z string "@#*%(#@"
|
||||||
|
}
|
||||||
|
|
||||||
type unmarshalTest struct {
|
type unmarshalTest struct {
|
||||||
in string
|
in string
|
||||||
|
|
@ -62,6 +67,9 @@ var unmarshalTests = []unmarshalTest{
|
||||||
{`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.Typeof("")}},
|
{`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.Typeof("")}},
|
||||||
{`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
|
{`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
|
||||||
|
|
||||||
|
// skip invalid tags
|
||||||
|
{`{"X":"a", "y":"b", "Z":"c"}`, new(badTag), badTag{"a", "b", "c"}, nil},
|
||||||
|
|
||||||
// syntax errors
|
// syntax errors
|
||||||
{`{"X": "foo", "Y"}`, nil, nil, SyntaxError("invalid character '}' after object key")},
|
{`{"X": "foo", "Y"}`, nil, nil, SyntaxError("invalid character '}' after object key")},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"unicode"
|
||||||
"utf8"
|
"utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -35,8 +36,9 @@ import (
|
||||||
//
|
//
|
||||||
// Struct values encode as JSON objects. Each struct field becomes
|
// Struct values encode as JSON objects. Each struct field becomes
|
||||||
// a member of the object. By default the object's key name is the
|
// a member of the object. By default the object's key name is the
|
||||||
// struct field name. If the struct field has a tag, that tag will
|
// struct field name. If the struct field has a non-empty tag consisting
|
||||||
// be used as the name instead. Only exported fields will be encoded.
|
// of only Unicode letters, digits, and underscores, that tag will be used
|
||||||
|
// as the name instead. Only exported fields will be encoded.
|
||||||
//
|
//
|
||||||
// Map values encode as JSON objects.
|
// Map values encode as JSON objects.
|
||||||
// The map's key type must be string; the object keys are used directly
|
// The map's key type must be string; the object keys are used directly
|
||||||
|
|
@ -230,7 +232,7 @@ func (e *encodeState) reflectValue(v reflect.Value) {
|
||||||
} else {
|
} else {
|
||||||
e.WriteByte(',')
|
e.WriteByte(',')
|
||||||
}
|
}
|
||||||
if f.Tag != "" {
|
if isValidTag(f.Tag) {
|
||||||
e.string(f.Tag)
|
e.string(f.Tag)
|
||||||
} else {
|
} else {
|
||||||
e.string(f.Name)
|
e.string(f.Name)
|
||||||
|
|
@ -285,6 +287,18 @@ func (e *encodeState) reflectValue(v reflect.Value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isValidTag(s string) bool {
|
||||||
|
if s == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range s {
|
||||||
|
if c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
|
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
|
||||||
// It implements the methods to sort by string.
|
// It implements the methods to sort by string.
|
||||||
type stringValues []reflect.Value
|
type stringValues []reflect.Value
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue