diff --git a/aws/protocol/query/array.go b/aws/protocol/query/array.go index 9d7d3a0cb5e..c54e358da20 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/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..671065b5223 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,17 @@ 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"); + + // If the list is empty, serialize an empty query value. + writer.write(""" + if len(v) == 0 { + value.Array($S).Empty() + return nil + } + """, arrayName); - writer.write("array := value.Array($S)", getSerializedLocationName(member, "member")); + writer.write("array := value.Array($S)", arrayName); writer.write(""); writer.openBlock("for i := range v {", "}", () -> {