@@ -17,6 +17,7 @@ limitations under the License.
17
17
package json_test
18
18
19
19
import (
20
+ "bytes"
20
21
"fmt"
21
22
"reflect"
22
23
"strings"
@@ -29,6 +30,8 @@ import (
29
30
"k8s.io/apimachinery/pkg/runtime/serializer/json"
30
31
runtimetesting "k8s.io/apimachinery/pkg/runtime/testing"
31
32
"k8s.io/apimachinery/pkg/util/diff"
33
+
34
+ "github.com/google/go-cmp/cmp"
32
35
)
33
36
34
37
type testDecodable struct {
@@ -933,3 +936,68 @@ func (t *mockTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind,
933
936
func (t * mockTyper ) Recognizes (_ schema.GroupVersionKind ) bool {
934
937
return false
935
938
}
939
+
940
+ type testEncodableDuplicateTag struct {
941
+ metav1.TypeMeta `json:",inline"`
942
+
943
+ A1 int `json:"a"`
944
+ A2 int `json:"a"` //nolint:govet // This is intentional to test that the encoder will not encode two map entries with the same key.
945
+ }
946
+
947
+ func (testEncodableDuplicateTag ) DeepCopyObject () runtime.Object {
948
+ panic ("unimplemented" )
949
+ }
950
+
951
+ type testEncodableTagMatchesUntaggedName struct {
952
+ metav1.TypeMeta `json:",inline"`
953
+
954
+ A int
955
+ TaggedA int `json:"A"`
956
+ }
957
+
958
+ func (testEncodableTagMatchesUntaggedName ) DeepCopyObject () runtime.Object {
959
+ panic ("unimplemented" )
960
+ }
961
+
962
+ func TestEncode (t * testing.T ) {
963
+ for _ , tc := range []struct {
964
+ name string
965
+ in runtime.Object
966
+ want []byte
967
+ }{
968
+ // The Go visibility rules for struct fields are amended for JSON when deciding
969
+ // which field to marshal or unmarshal. If there are multiple fields at the same
970
+ // level, and that level is the least nested (and would therefore be the nesting
971
+ // level selected by the usual Go rules), the following extra rules apply:
972
+
973
+ // 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
974
+ // even if there are multiple untagged fields that would otherwise conflict.
975
+ {
976
+ name : "only tagged field is considered if any are tagged" ,
977
+ in : & testEncodableTagMatchesUntaggedName {
978
+ A : 1 ,
979
+ TaggedA : 2 ,
980
+ },
981
+ want : []byte ("{\" A\" :2}\n " ),
982
+ },
983
+ // 2) If there is exactly one field (tagged or not according to the first rule),
984
+ // that is selected.
985
+ // 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
986
+ {
987
+ name : "all duplicate fields are ignored" ,
988
+ in : & testEncodableDuplicateTag {},
989
+ want : []byte ("{}\n " ),
990
+ },
991
+ } {
992
+ t .Run (tc .name , func (t * testing.T ) {
993
+ var dst bytes.Buffer
994
+ s := json .NewSerializerWithOptions (json .DefaultMetaFactory , nil , nil , json.SerializerOptions {})
995
+ if err := s .Encode (tc .in , & dst ); err != nil {
996
+ t .Errorf ("unexpected error: %v" , err )
997
+ }
998
+ if diff := cmp .Diff (tc .want , dst .Bytes ()); diff != "" {
999
+ t .Errorf ("unexpected output:\n %s" , diff )
1000
+ }
1001
+ })
1002
+ }
1003
+ }
0 commit comments