@@ -104,6 +104,7 @@ tags, and then generate with `hack/update-toc.sh`.
104
104
- [ Unit tests] ( #unit-tests )
105
105
- [ Integration tests] ( #integration-tests )
106
106
- [ e2e tests] ( #e2e-tests )
107
+ - [ Custom JSON Marshalers] ( #custom-json-marshalers )
107
108
- [ Graduation Criteria] ( #graduation-criteria )
108
109
- [ Alpha] ( #alpha )
109
110
- [ Beta] ( #beta )
@@ -752,6 +753,48 @@ We expect no non-infra related flakes in the last month as a GA graduation crite
752
753
753
754
- request and response content-type negotiation with 1.17 sample API server
754
755
756
+ ### Custom JSON Marshalers
757
+
758
+ If a type implements json.Marshaler or json.Unmarshaler without corresponding CBOR behaviors,
759
+ serializing values of that type to and from CBOR using default behaviors risks mangling the data.
760
+
761
+ As an example, consider the structure of a marshalled
762
+ [ IntOrString] ( https://pkg.go.dev/k8s.io/apimachinery/pkg/util/intstr#IntOrString ) with the custom
763
+ behavior versus the default behavior:
764
+
765
+ | Go | Custom | Default |
766
+ | ------------------------------------------| ---------| ---------------------------------------|
767
+ | IntOrString{Type: Int, IntVal: 7} | 7 | {"IntVal":7,"StrVal":"","Type:":0} |
768
+ | IntOrString{Type: String, StrVal: "foo"} | "foo" | {"IntVal":0,"StrVal":"foo","Type:":1} |
769
+ | IntOrString{Type: -1} | <error > | {"IntVal":0,"StrVal":"","Type:":-1} |
770
+
771
+ Imagine a similar type is declared out-of-tree. It has a similar implementation of ` json.Marshaler ` ,
772
+ but not corresponding custom implementation for CBOR. From this type, a CRD and typed client are
773
+ generated. This typed client is used in a program to write to a custom resource, using JSON to
774
+ encode the request body as either a JSON number or a JSON string. On the server side, the request
775
+ body is decoded into an Unstructured object, and within that object, the IntOrString value is
776
+ represented by either a ` string ` or an ` int64 ` .
777
+
778
+ Now imagine that the same request is repeated, but with CBOR as the negotiated content type of the
779
+ request body, and that the CBOR serializer implementation _ does not_ recognize types that implement
780
+ ` json.Marshaler ` or ` json.Unmarshaler ` . By changing the request content type from JSON to CBOR, the
781
+ actual bytes of the request body represent a structurally different object. Referencing the table
782
+ above, instead of the "Custom" encoding, the encoded CBOR would look like the "Default" encoding.
783
+
784
+ On the server side, the value is represented within the decoded Unstructured as a
785
+ ` map[string]interface{} ` with three keys, ` "IntVal" ` , ` "StrVal ` ", and ` "Type" ` . A change in the
786
+ request encoding resulted in a structural change to the object the client intended to send.
787
+
788
+ The CBOR serializer must not use the default behaviors to marshal and unmarshal values that
789
+ implement only custom JSON behaviors. Rejecting them with an error is a minimum requirement for
790
+ alpha, since it prevents corruption. This would support in-tree types, server-side custom resource
791
+ serialization, and typical dynamic client usage. A second alpha release will support these types
792
+ automatically by invoking the JSON methods and transcoding to or from CBOR.
793
+
794
+ All of the above also applies to types implementing ` encoding.TextMarshaler ` (which is used if
795
+ implemented unless ` json.Marshaler ` is also implemented) and ` encoding.TextUnmarshaler ` (which is
796
+ used if implemented when the input is a JSON string unless ` json.Unmarshaler ` is also implemented).
797
+
755
798
### Graduation Criteria
756
799
757
800
<!--
@@ -824,11 +867,17 @@ in back-to-back releases.
824
867
- Client generation updated to support CBOR behind client-side gates.
825
868
- Runtime gating mechanism added to client-go.
826
869
- Maintenance of CBOR library is understood.
870
+ - Types that implement json.Marshaler or json.Unmarshaler without corresponding custom CBOR
871
+ behaviors are either rejected with an error on Encode and Decode or automatically transcoded from
872
+ JSON.
827
873
828
874
#### Beta
829
875
830
876
- Review of nondeterministic encoding mode and final decision on whether to keep
831
877
or remove it.
878
+ - To support rollback from beta to alpha, at least one alpha release has supported automatic
879
+ transcoding of types that implement json.Marshaler or json.Unmarshaler without corresponding
880
+ custom CBOR behaviors.
832
881
833
882
#### GA
834
883
0 commit comments