diff --git a/.changelog/e0727d8e716742fdbb16b62e64b20456.json b/.changelog/e0727d8e716742fdbb16b62e64b20456.json new file mode 100644 index 00000000000..18ae69f980d --- /dev/null +++ b/.changelog/e0727d8e716742fdbb16b62e64b20456.json @@ -0,0 +1,31 @@ +{ + "id": "e0727d8e-7167-42fd-bb16-b62e64b20456", + "type": "feature", + "description": "Upgrade smithy to 1.27.x, updating query protocol serializers.", + "modules": [ + "internal/protocoltest/awsrestjson", + "internal/protocoltest/ec2query", + "internal/protocoltest/jsonrpc", + "internal/protocoltest/jsonrpc10", + "internal/protocoltest/query", + "internal/protocoltest/restxml", + "service/autoscaling", + "service/cloudformation", + "service/cloudsearch", + "service/cloudwatch", + "service/docdb", + "service/ec2", + "service/elasticache", + "service/elasticbeanstalk", + "service/elasticloadbalancing", + "service/elasticloadbalancingv2", + "service/iam", + "service/neptune", + "service/rds", + "service/redshift", + "service/ses", + "service/sns", + "service/sqs", + "service/sts" + ] +} \ No newline at end of file diff --git a/aws/protocol/query/array.go b/aws/protocol/query/array.go index 9d7d3a0cb5e..218f05c73a3 100644 --- a/aws/protocol/query/array.go +++ b/aws/protocol/query/array.go @@ -59,3 +59,20 @@ func (a *Array) Value() Value { // Lists can't have flat members return newValue(a.values, fmt.Sprintf("%s.%d", prefix, a.size), false) } + +// Empty allows empty Query Array URI encoding, e.g. +// +// "ListArg": [] -> ?ListArg= +// +// If this method is not called on an empty Query Array, it will +// not be serialized when encoded. +// +// The method should ONLY be used if the Array is known to be empty. +func (a *Array) Empty() { + // If the Array is not empty, return to avoid wrong encoding + if a.size != 0 { + return + } + // Set value of prefix to empty string (no text) + newValue(a.values, a.prefix, false).String("") +} diff --git a/aws/protocol/query/encoder_test.go b/aws/protocol/query/encoder_test.go index d0c21e537cb..5b4a5485b0f 100644 --- a/aws/protocol/query/encoder_test.go +++ b/aws/protocol/query/encoder_test.go @@ -35,6 +35,14 @@ func TestEncode(t *testing.T) { }, Expect: []byte(`list.spam.1=spam&list.spam.2=eggs`), }, + "empty list": { + Encode: func(e *Encoder) error { + list := e.Object().Key("ListArg").Array("member") + list.Empty() + return e.Encode() + }, + Expect: []byte(`ListArg=`), + }, "flat list": { Encode: func(e *Encoder) error { list := e.Object().FlatKey("list").Array("spam") @@ -44,6 +52,14 @@ func TestEncode(t *testing.T) { }, Expect: []byte(`list.1=spam&list.2=eggs`), }, + "empty flat list": { + Encode: func(e *Encoder) error { + list := e.Object().FlatKey("ListArg").Array("member") + list.Empty() + return e.Encode() + }, + Expect: []byte(`ListArg=`), + }, "map": { Encode: func(e *Encoder) error { mapValue := e.Object().Key("map").Map("key", "value") diff --git a/codegen/gradle.properties b/codegen/gradle.properties index ea3fa73f7c5..b30aec80489 100644 --- a/codegen/gradle.properties +++ b/codegen/gradle.properties @@ -1,2 +1,2 @@ -smithyVersion=1.25.2 +smithyVersion=[1.27.0,1.28.0[ smithyGradleVersion=0.6.0 diff --git a/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/QueryShapeSerVisitor.java b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/QueryShapeSerVisitor.java index bc0165ee36c..7486b01f24a 100644 --- a/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/QueryShapeSerVisitor.java +++ b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/QueryShapeSerVisitor.java @@ -23,6 +23,7 @@ import software.amazon.smithy.model.shapes.MapShape; import software.amazon.smithy.model.shapes.MemberShape; import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeType; import software.amazon.smithy.model.shapes.StructureShape; import software.amazon.smithy.model.shapes.UnionShape; import software.amazon.smithy.model.traits.EnumTrait; @@ -75,10 +76,16 @@ protected void serializeCollection(GenerationContext context, CollectionShape sh MemberShape member = shape.getMember(); Shape target = context.getModel().expectShape(member.getTarget()); - // If the list is empty, exit early to avoid extra effort. - writer.write("if len(v) == 0 { return nil }"); + String arrayName = getSerializedLocationName(member, "member"); + writer.write("array := value.Array($S)", arrayName); + + // If the list is empty, serialize an empty query value. + writer.write(""" + if len(v) == 0 { + array.Empty() + return nil + }"""); - writer.write("array := value.Array($S)", getSerializedLocationName(member, "member")); writer.write(""); writer.openBlock("for i := range v {", "}", () -> {