diff --git a/pkg/api/testing/serialization_proto_test.go b/pkg/api/testing/serialization_proto_test.go index 7cc03b9faff..8790809a4ce 100644 --- a/pkg/api/testing/serialization_proto_test.go +++ b/pkg/api/testing/serialization_proto_test.go @@ -88,7 +88,8 @@ func fieldsHaveProtobufTags(obj reflect.Type) error { // TypeMeta is not included in external protobuf because we use an envelope type with TypeMeta continue } - if len(f.Tag.Get("json")) > 0 && len(f.Tag.Get("protobuf")) == 0 { + _, jsonTagExists := f.Tag.Lookup("json") + if jsonTagExists && len(f.Tag.Get("protobuf")) == 0 { return fmt.Errorf("field %s in %s has a 'json' tag but no protobuf tag", f.Name, obj) } } diff --git a/staging/src/k8s.io/apimachinery/pkg/api/apitesting/naming/naming.go b/staging/src/k8s.io/apimachinery/pkg/api/apitesting/naming/naming.go index c235d017e33..d089b9f53be 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/apitesting/naming/naming.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/apitesting/naming/naming.go @@ -88,9 +88,9 @@ func ensureNoTags(gvk schema.GroupVersionKind, tp reflect.Type, parents []reflec if f.PkgPath != "" { continue // Ignore unexported fields } - jsonTag := f.Tag.Get("json") + _, jsonTagExists := f.Tag.Lookup("json") protoTag := f.Tag.Get("protobuf") - if len(jsonTag) > 0 || len(protoTag) > 0 { + if jsonTagExists || len(protoTag) > 0 { errs = append(errs, fmt.Errorf("internal types should not have json or protobuf tags. %#v has tag on field %v: %v.\n%s", gvk, f.Name, f.Tag, fmtParentString(parents))) } @@ -126,9 +126,13 @@ func ensureTags(gvk schema.GroupVersionKind, tp reflect.Type, parents []reflect. case reflect.Struct: for i := 0; i < tp.NumField(); i++ { f := tp.Field(i) - jsonTag := f.Tag.Get("json") + jsonTag, jsonTagExists := f.Tag.Lookup("json") if len(jsonTag) == 0 { - errs = append(errs, fmt.Errorf("external types should have json tags. %#v tags on field %v are: %s.\n%s", gvk, f.Name, f.Tag, fmtParentString(parents))) + if f.Anonymous && jsonTagExists { + // allow json:"" on embedded fields + } else { + errs = append(errs, fmt.Errorf("external types should have json tags. %#v tags on field %v are: %s.\n%s", gvk, f.Name, f.Tag, fmtParentString(parents))) + } } jsonTagName := strings.Split(jsonTag, ",")[0] diff --git a/staging/src/k8s.io/apimachinery/pkg/api/apitesting/roundtrip/construct.go b/staging/src/k8s.io/apimachinery/pkg/api/apitesting/roundtrip/construct.go index 694dece2954..da334a373bf 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/apitesting/roundtrip/construct.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/apitesting/roundtrip/construct.go @@ -136,7 +136,8 @@ func fill(dataString string, dataInt int, t reflect.Type, v reflect.Value, fillF } // use the json field name, which must be stable - dataString := strings.Split(field.Tag.Get("json"), ",")[0] + jsonTag, _ := field.Tag.Lookup("json") + dataString = strings.Split(jsonTag, ",")[0] if dataString == "-" { // unserialized field, no need to fill it continue diff --git a/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go b/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go index b0a9246d973..5eb25e2e80f 100644 --- a/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go +++ b/staging/src/k8s.io/apimachinery/pkg/conversion/queryparams/convert.go @@ -34,8 +34,8 @@ type Unmarshaler interface { } func jsonTag(field reflect.StructField) (string, bool) { - structTag := field.Tag.Get("json") - if len(structTag) == 0 { + structTag, exists := field.Tag.Lookup("json") + if !exists || len(structTag) == 0 { return "", false } parts := strings.Split(structTag, ",") diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/conversion.go b/staging/src/k8s.io/apimachinery/pkg/runtime/conversion.go index d04d701f376..7cef382de23 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/conversion.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/conversion.go @@ -20,7 +20,6 @@ package runtime import ( "fmt" - "reflect" "strconv" "strings" @@ -41,18 +40,6 @@ func DefaultMetaV1FieldSelectorConversion(label, value string) (string, string, } } -// JSONKeyMapper uses the struct tags on a conversion to determine the key value for -// the other side. Use when mapping from a map[string]* to a struct or vice versa. -func JSONKeyMapper(key string, sourceTag, destTag reflect.StructTag) (string, string) { - if s := destTag.Get("json"); len(s) > 0 { - return strings.SplitN(s, ",", 2)[0], key - } - if s := sourceTag.Get("json"); len(s) > 0 { - return key, strings.SplitN(s, ",", 2)[0] - } - return key, key -} - func Convert_Slice_string_To_string(in *[]string, out *string, s conversion.Scope) error { if len(*in) == 0 { *out = "" diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go b/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go index b1a300959b3..c86520691ba 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go @@ -376,8 +376,8 @@ func fieldInfoFromField(structType reflect.Type, field int) *fieldInfo { // Cache miss - we need to compute the field name. info := &fieldInfo{} typeField := structType.Field(field) - jsonTag := typeField.Tag.Get("json") - if len(jsonTag) == 0 { + jsonTag, exists := typeField.Tag.Lookup("json") + if !exists || len(jsonTag) == 0 { if !typeField.Anonymous { // match stdlib behavior for naming fields that don't specify a json tag name info.name = typeField.Name diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go index 56c392fd057..d6cd2b75686 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go @@ -30,6 +30,7 @@ import ( "golang.org/x/text/cases" "golang.org/x/text/language" + apidiscoveryv2 "k8s.io/api/apidiscovery/v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/conversion" @@ -1177,7 +1178,7 @@ func AddObjectParams(ws *restful.WebService, route *restful.RouteBuilder, obj in } fallthrough default: - jsonTag := sf.Tag.Get("json") + jsonTag, _ := sf.Tag.Lookup("json") if len(jsonTag) == 0 { continue } diff --git a/staging/src/k8s.io/client-go/util/jsonpath/jsonpath.go b/staging/src/k8s.io/client-go/util/jsonpath/jsonpath.go index 86a3d6dde95..91525c0b482 100644 --- a/staging/src/k8s.io/client-go/util/jsonpath/jsonpath.go +++ b/staging/src/k8s.io/client-go/util/jsonpath/jsonpath.go @@ -361,7 +361,7 @@ func (j *JSONPath) findFieldInValue(value *reflect.Value, node *FieldNode) (refl var inlineValue *reflect.Value for ix := 0; ix < t.NumField(); ix++ { f := t.Field(ix) - jsonTag := f.Tag.Get("json") + jsonTag, _ := f.Tag.Lookup("json") parts := strings.Split(jsonTag, ",") if len(parts) == 0 { continue @@ -369,7 +369,7 @@ func (j *JSONPath) findFieldInValue(value *reflect.Value, node *FieldNode) (refl if parts[0] == node.Value { return value.Field(ix), nil } - if len(parts[0]) == 0 { + if len(parts[0]) == 0 && f.Anonymous { val := value.Field(ix) inlineValue = &val } diff --git a/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/generator.go b/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/generator.go index c92c7cec028..64634da8493 100644 --- a/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/generator.go +++ b/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/generator.go @@ -652,7 +652,7 @@ func membersToFields(locator ProtobufLocator, t *types.Type, localPackage types. } // extract information from JSON field tag - if tag := tags.Get("json"); len(tag) > 0 { + if tag, _ := tags.Lookup("json"); len(tag) > 0 { parts := strings.Split(tag, ",") if len(field.Name) == 0 && len(parts[0]) != 0 { field.Name = parts[0]