Commit f80d0024 authored by Russ Cox's avatar Russ Cox

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
parent 6e03ed32
...@@ -466,13 +466,15 @@ func (d *decodeState) object(v reflect.Value) { ...@@ -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 ( ...@@ -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{ ...@@ -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 ( ...@@ -13,6 +13,7 @@ import (
"runtime" "runtime"
"sort" "sort"
"strconv" "strconv"
"unicode"
"utf8" "utf8"
) )
...@@ -35,8 +36,9 @@ import ( ...@@ -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) { ...@@ -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) { ...@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment