From: Mikio Hara Date: Thu, 14 Jul 2011 00:41:33 +0000 (-0700) Subject: json: allow using '$' and '-' as the struct field's tag X-Git-Tag: weekly.2011-07-19~70 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=689a2ec8c3896b122907fcb5e3d1399ca4598099;p=gostls13.git json: allow using '$' and '-' as the struct field's tag R=adg, rsc, bradfitz, mattn.jp, gustavo CC=golang-dev https://golang.org/cl/4625081 --- diff --git a/src/pkg/json/decode_test.go b/src/pkg/json/decode_test.go index 9b84bc76c4..24c97e576f 100644 --- a/src/pkg/json/decode_test.go +++ b/src/pkg/json/decode_test.go @@ -40,13 +40,6 @@ var ( umtrue = unmarshaler{true} ) -type badTag struct { - X string - Y string `json:"y"` - Z string `x:"@#*%(#@"` - W string `json:"@#$@#$"` -} - type unmarshalTest struct { in string ptr interface{} @@ -68,9 +61,6 @@ var unmarshalTests = []unmarshalTest{ {`{"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)}}, - // skip invalid tags - {`{"X":"a", "y":"b", "Z":"c", "W":"d"}`, new(badTag), badTag{"a", "b", "c", "d"}, nil}, - // syntax errors {`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}}, diff --git a/src/pkg/json/encode.go b/src/pkg/json/encode.go index 3e4532cee4..fbc00355a6 100644 --- a/src/pkg/json/encode.go +++ b/src/pkg/json/encode.go @@ -38,11 +38,11 @@ import ( // // Struct values encode as JSON objects. Each exported struct field // becomes a member of the object. By default the object's key string -// is the struct field name. If the struct field's tag has a "json" key with a -// value that is a non-empty string consisting of only Unicode letters, -// digits, and underscores, that value will be used as the object key. -// For example, the field tag `json:"myName"` says to use "myName" -// as the object key. +// is the struct field name. If the struct field's tag has a "json" +// key with a value that is a non-empty string consisting of only +// Unicode letters, digits, dollar signs, hyphens, and underscores, +// that value will be used as the object key. For example, the field +// tag `json:"myName"` says to use "myName" as the object key. // // Map values encode as JSON objects. // The map's key type must be string; the object keys are used directly @@ -316,7 +316,7 @@ func isValidTag(s string) bool { return false } for _, c := range s { - if c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) { + if c != '$' && c != '-' && c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) { return false } } diff --git a/src/pkg/json/tagkey_test.go b/src/pkg/json/tagkey_test.go new file mode 100644 index 0000000000..31fe2be362 --- /dev/null +++ b/src/pkg/json/tagkey_test.go @@ -0,0 +1,95 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package json + +import ( + "testing" +) + +type basicLatin2xTag struct { + V string `json:"$-"` +} + +type basicLatin3xTag struct { + V string `json:"0123456789"` +} + +type basicLatin4xTag struct { + V string `json:"ABCDEFGHIJKLMO"` +} + +type basicLatin5xTag struct { + V string `json:"PQRSTUVWXYZ_"` +} + +type basicLatin6xTag struct { + V string `json:"abcdefghijklmno"` +} + +type basicLatin7xTag struct { + V string `json:"pqrstuvwxyz"` +} + +type miscPlaneTag struct { + V string `json:"色は匂へど"` +} + +type emptyTag struct { + W string +} + +type misnamedTag struct { + X string `jsom:"Misnamed"` +} + +type badFormatTag struct { + Y string `:"BadFormat"` +} + +type badCodeTag struct { + Z string `json:" !\"#%&'()*+,./"` +} + +var structTagObjectKeyTests = []struct { + raw interface{} + value string + key string +}{ + {basicLatin2xTag{"2x"}, "2x", "$-"}, + {basicLatin3xTag{"3x"}, "3x", "0123456789"}, + {basicLatin4xTag{"4x"}, "4x", "ABCDEFGHIJKLMO"}, + {basicLatin5xTag{"5x"}, "5x", "PQRSTUVWXYZ_"}, + {basicLatin6xTag{"6x"}, "6x", "abcdefghijklmno"}, + {basicLatin7xTag{"7x"}, "7x", "pqrstuvwxyz"}, + {miscPlaneTag{"いろはにほへと"}, "いろはにほへと", "色は匂へど"}, + {emptyTag{"Pour Moi"}, "Pour Moi", "W"}, + {misnamedTag{"Animal Kingdom"}, "Animal Kingdom", "X"}, + {badFormatTag{"Orfevre"}, "Orfevre", "Y"}, + {badCodeTag{"Reliable Man"}, "Reliable Man", "Z"}, +} + +func TestStructTagObjectKey(t *testing.T) { + for _, tt := range structTagObjectKeyTests { + b, err := Marshal(tt.raw) + if err != nil { + t.Fatalf("Marshal(%#q) failed: %v", tt.raw, err) + } + var f interface{} + err = Unmarshal(b, &f) + if err != nil { + t.Fatalf("Unmarshal(%#q) failed: %v", b, err) + } + for i, v := range f.(map[string]interface{}) { + switch i { + case tt.key: + if s, ok := v.(string); !ok || s != tt.value { + t.Fatalf("Unexpected value: %#q, want %v", s, tt.value) + } + default: + t.Fatalf("Unexpected key: %#q", i) + } + } + } +}