Skip to content

Skip null check in doMarshal JSON serializer#6807

Merged
RanVaknin merged 6 commits intomasterfrom
rvaknin/json-serializer-null-skip
Mar 30, 2026
Merged

Skip null check in doMarshal JSON serializer#6807
RanVaknin merged 6 commits intomasterfrom
rvaknin/json-serializer-null-skip

Conversation

@RanVaknin
Copy link
Copy Markdown
Contributor

@RanVaknin RanVaknin commented Mar 20, 2026

Background

During JSON serialization, JsonProtocolMarshaller.doMarshall() iterates every SdkField on a POJO and calls marshallField() for each one, including fields that are null. marshallField uses a registry to dispatch to a type specific marshaller (string, int, map, null, etc ) based on the field's value.
When the value is null, it dispatches to the NULL marshaller, that checks if the field is required (throw) or not (no-op). For non-required null fields, this entire chain (registry lookup, marshaller resolution, trait check) is wasted work.

The proposed change is to short circuit null handling for payload fields directly on the generic doMarshall() layer, and avoid the dispatch. Non payload fields still delegate to marshallField since their null marshallers have different validation logic.

Boto3's RestJson serializer handles it very similarly.

Testing

Our protocol tests already cover the main code paths of doMarshal (null headers, null query params, partial payload serialization). I added one unit test to specific JsonProtocolMarshaller directly to cover the case where a null required payload field reaches the marshaller. This codepath is caught earlier by the SDK's generated validators, but the this is just make sure the marshaller handles it correctly if that layer is ever bypassed.

Results:

Benchmarks written in #6776

Before:
image

After
image

Protocol Operation Master (ops/µs) Feature (ops/µs) Improvement
RestJson CreateFunction deser 0.176 0.175 -0.57%
RestJson CreateFunction ser 0.284 0.327 15.14%
JSON DynamoDB PutItem deser 0.141 0.141 0.00%
JSON DynamoDB PutItem ser 0.101 0.124 22.77%
CBOR CloudWatch GetMetricData deser 0.382 0.385 0.79%
CBOR CloudWatch GetMetricData ser 0.416 0.457 9.86%

@RanVaknin RanVaknin changed the title Rvaknin/json serializer null skip skip null check in doMarshal JSON serializer Mar 20, 2026
@RanVaknin RanVaknin changed the title skip null check in doMarshal JSON serializer Skip null check in doMarshal JSON serializer Mar 23, 2026
@RanVaknin RanVaknin marked this pull request as ready for review March 23, 2026 18:28
@RanVaknin RanVaknin requested a review from a team as a code owner March 23, 2026 18:28
import software.amazon.awssdk.protocols.json.AwsJsonProtocolMetadata;
import software.amazon.awssdk.protocols.json.internal.AwsStructuredPlainJsonFactory;

class JsonProtocolMarshallerTest {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost all of the codepaths that this file tests are covered by the protocol test package. nullPayloadField_required_throwsIllegalArgumentException is the only test that is not covered by the end to end tests because its technically not possible to get there. This codepath branch was likely added as a defense in depth.

Comment on lines +220 to +222
} else if (field.containsTrait(RequiredTrait.class, TraitType.REQUIRED_TRAIT)) {
throw new IllegalArgumentException(
String.format("Parameter '%s' must not be null", field.locationName()));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we validate required client side? I thought we generally didn't do client side validation of required and instead just sent these requests to the service (since the api may have evolved and removed the required over time).

Copy link
Copy Markdown
Contributor Author

@RanVaknin RanVaknin Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but this is not a new validation. I had to port this logic out from the null marshaller:

https://github.com/aws/aws-sdk-java-v2/blob/master/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/internal/marshall/SimpleTypeJsonMarshaller.java#L42

since we are handling nulls now at the doMarshal level.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see - yeah, agree this makes sense here then.

Copy link
Copy Markdown
Contributor

@alextwoods alextwoods left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good. Needs a changelog I think.

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@RanVaknin RanVaknin added this pull request to the merge queue Mar 26, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 26, 2026
@RanVaknin RanVaknin added this pull request to the merge queue Mar 30, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 30, 2026
@RanVaknin RanVaknin added this pull request to the merge queue Mar 30, 2026
Merged via the queue into master with commit 54a01b7 Mar 30, 2026
47 of 49 checks passed
@github-actions
Copy link
Copy Markdown

This pull request has been closed and the conversation has been locked. Comments on closed PRs are hard for our team to see. If you need more assistance, please open a new issue that references this one.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants