Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure slices are serialized as zero-length, not null #43422

Merged
merged 3 commits into from
Mar 21, 2017

Conversation

liggitt
Copy link
Member

@liggitt liggitt commented Mar 21, 2017

Fixes #43203 null serialization of slices to prevent NPE errors in clients that store and expect to receive non-null JSON values in these fields.

Ensures when we are converting to an external slice field that will be serialized even if empty (has json tag that does not include omitempty), we populate it with [], not nil

Other places I considered putting this logic instead:

  • When unmarshaling
    • Would have to be done for both protobuf and ugorji
    • Would still have to be done here (or on marshal) to handle cases where we construct objects to return
  • When marshaling
    • Would have to switch to use custom json marshaler (currently we use stdlib) (or alias all field types and write per-field json marshalers)
  • When defaulting
    • Defaulting isn't run on some fields, notably, pod template in rc/deployment spec
    • Would still have to be done here (or on marshal) to handle cases where we construct objects to return
API fields that previously serialized null arrays as `null` and empty arrays as `[]` no longer distinguish between those values and always output `[]` when serializing to JSON.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Mar 21, 2017
@k8s-reviewable
Copy link

This change is Reviewable

@k8s-github-robot k8s-github-robot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Mar 21, 2017
@liggitt liggitt added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Mar 21, 2017
@k8s-github-robot k8s-github-robot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Mar 21, 2017
@smarterclayton
Copy link
Contributor

It's even better because this will regress performance in the normal case. Sad.

@smarterclayton
Copy link
Contributor

This looks like what I expected.

@thockin
Copy link
Member

thockin commented Mar 21, 2017

puke. LGTM.

@thockin thockin added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Mar 21, 2017
@thockin
Copy link
Member

thockin commented Mar 21, 2017

Any reason not to approve, @smarterclayton ?

@liggitt
Copy link
Member Author

liggitt commented Mar 21, 2017

this is definitely in the "things API compatibility made me do under duress" category

@smarterclayton
Copy link
Contributor

No, I think this is required for back compat, and while it makes me die a little on the inside every time I look at it, them's the breaks.

/approve

@smarterclayton smarterclayton added the area/api Indicates an issue on api area. label Mar 21, 2017
@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: liggitt, smarterclayton

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-github-robot k8s-github-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 21, 2017
@k8s-github-robot
Copy link

Automatic merge from submit-queue

@k8s-github-robot k8s-github-robot merged commit 51beb16 into kubernetes:master Mar 21, 2017
@liggitt liggitt deleted the convert-null-list branch March 22, 2017 20:11
k8s-github-robot pushed a commit that referenced this pull request Aug 26, 2017
Automatic merge from submit-queue

Remove null -> [] slice hack

Closes #44593

When 1.6 added protobuf storage, the storage layer lost the ability to persist slice fields with empty but non-null values.

As a workaround, we tried to convert empty slice fields to `[]`, rather than `null`. Compressing `null` -> `[]` was just as much of an API breakage as `[]` -> `null`, but was hoped to cause fewer problems in clients that don't do null checks.

Because of conversion optimizations around converting lists of objects, the `null` -> `[]` hack was discovered to only apply to individual get requests, not to a list of objects. 1.6 and 1.7 was released with this behavior, and the world didn't explode. 1.7 documented the breaking API change that `null` and `[]` should be considered equivalent, unless otherwise noted on a particular field.

This PR:

* Reverts the earlier attempt (#43422) at ensuring non-null json slice output in conversion
* Makes results of `get` consistent with the results of `list` (which helps naive clients that do deepequal comparisons of objects obtained via list/watch and get), and allows empty slice fields to be returned as `null`

```release-note
Protobuf serialization does not distinguish between `[]` and `null`.
API fields previously capable of storing and returning either `[]` and `null` via JSON API requests (for example, the Endpoints `subsets` field) can now store only `null` when created using the protobuf content-type or stored in etcd using protobuf serialization (the default in 1.6+). JSON API clients should tolerate `null` values for such fields, and treat `null` and `[]` as equivalent in meaning unless specifically documented otherwise for a particular field.
```
perotinus pushed a commit to kubernetes-retired/cluster-registry that referenced this pull request Sep 2, 2017
Automatic merge from submit-queue

Remove null -> [] slice hack

Closes #44593

When 1.6 added protobuf storage, the storage layer lost the ability to persist slice fields with empty but non-null values.

As a workaround, we tried to convert empty slice fields to `[]`, rather than `null`. Compressing `null` -> `[]` was just as much of an API breakage as `[]` -> `null`, but was hoped to cause fewer problems in clients that don't do null checks.

Because of conversion optimizations around converting lists of objects, the `null` -> `[]` hack was discovered to only apply to individual get requests, not to a list of objects. 1.6 and 1.7 was released with this behavior, and the world didn't explode. 1.7 documented the breaking API change that `null` and `[]` should be considered equivalent, unless otherwise noted on a particular field.

This PR:

* Reverts the earlier attempt (kubernetes/kubernetes#43422) at ensuring non-null json slice output in conversion
* Makes results of `get` consistent with the results of `list` (which helps naive clients that do deepequal comparisons of objects obtained via list/watch and get), and allows empty slice fields to be returned as `null`

```release-note
Protobuf serialization does not distinguish between `[]` and `null`.
API fields previously capable of storing and returning either `[]` and `null` via JSON API requests (for example, the Endpoints `subsets` field) can now store only `null` when created using the protobuf content-type or stored in etcd using protobuf serialization (the default in 1.6+). JSON API clients should tolerate `null` values for such fields, and treat `null` and `[]` as equivalent in meaning unless specifically documented otherwise for a particular field.
```
akhilerm pushed a commit to akhilerm/apimachinery that referenced this pull request Sep 20, 2022
Automatic merge from submit-queue

Remove null -> [] slice hack

Closes #44593

When 1.6 added protobuf storage, the storage layer lost the ability to persist slice fields with empty but non-null values.

As a workaround, we tried to convert empty slice fields to `[]`, rather than `null`. Compressing `null` -> `[]` was just as much of an API breakage as `[]` -> `null`, but was hoped to cause fewer problems in clients that don't do null checks.

Because of conversion optimizations around converting lists of objects, the `null` -> `[]` hack was discovered to only apply to individual get requests, not to a list of objects. 1.6 and 1.7 was released with this behavior, and the world didn't explode. 1.7 documented the breaking API change that `null` and `[]` should be considered equivalent, unless otherwise noted on a particular field.

This PR:

* Reverts the earlier attempt (kubernetes/kubernetes#43422) at ensuring non-null json slice output in conversion
* Makes results of `get` consistent with the results of `list` (which helps naive clients that do deepequal comparisons of objects obtained via list/watch and get), and allows empty slice fields to be returned as `null`

```release-note
Protobuf serialization does not distinguish between `[]` and `null`.
API fields previously capable of storing and returning either `[]` and `null` via JSON API requests (for example, the Endpoints `subsets` field) can now store only `null` when created using the protobuf content-type or stored in etcd using protobuf serialization (the default in 1.6+). JSON API clients should tolerate `null` values for such fields, and treat `null` and `[]` as equivalent in meaning unless specifically documented otherwise for a particular field.
```

Kubernetes-commit: 217513e27a6e54eb92d09165293cf811d5bdf878
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/api Indicates an issue on api area. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants