diff --git a/internal/gengapic/genrest.go b/internal/gengapic/genrest.go index 5a2569ea1..6fbb96c10 100644 --- a/internal/gengapic/genrest.go +++ b/internal/gengapic/genrest.go @@ -420,6 +420,7 @@ func (g *generator) generateQueryString(m *descriptor.MethodDescriptorProto) { singularPrimitive := field.GetType() != fieldTypeMessage && field.GetType() != fieldTypeBytes && field.GetLabel() != fieldLabelRepeated + key := lowerFirst(snakeToCamel(path)) var paramAdd string // Handle well known protobuf types with special JSON encodings. @@ -435,10 +436,10 @@ func (g *generator) generateQueryString(m *descriptor.MethodDescriptorProto) { b.WriteString(" return nil, err\n") } b.WriteString("}\n") - b.WriteString(fmt.Sprintf("params.Add(%q, string(%s))", lowerFirst(snakeToCamel(path)), field.GetJsonName())) + b.WriteString(fmt.Sprintf("params.Add(%q, string(%s))", key, field.GetJsonName())) paramAdd = b.String() } else { - paramAdd = fmt.Sprintf("params.Add(%q, fmt.Sprintf(%q, req%s))", lowerFirst(snakeToCamel(path)), "%v", accessor) + paramAdd = fmt.Sprintf("params.Add(%q, fmt.Sprintf(%q, req%s))", key, "%v", accessor) g.imports[pbinfo.ImportSpec{Path: "fmt"}] = true } @@ -450,8 +451,14 @@ func (g *generator) generateQueryString(m *descriptor.MethodDescriptorProto) { } if field.GetLabel() == fieldLabelRepeated { - // It's a slice, so check for nil - p("if req%s != nil {", accessor) + // It's a slice, so check for len > 0, nil slice returns 0. + p("if items := req%s; len(items) > 0 {", accessor) + b := strings.Builder{} + b.WriteString("for _, item := range items {\n") + b.WriteString(fmt.Sprintf(" params.Add(%q, fmt.Sprintf(%q, item))\n", key, "%v")) + b.WriteString("}") + paramAdd = b.String() + } else if field.GetProto3Optional() { // Split right before the raw access toks := strings.Split(path, ".") diff --git a/internal/gengapic/genrest_test.go b/internal/gengapic/genrest_test.go index d2f0a300f..adddf0e0e 100644 --- a/internal/gengapic/genrest_test.go +++ b/internal/gengapic/genrest_test.go @@ -499,9 +499,16 @@ func TestGenRestMethod(t *testing.T) { TypeName: proto.String(".google.protobuf.FieldMask"), } + repeatedPrimField := &descriptor.FieldDescriptorProto{ + Name: proto.String("primitives"), + Type: descriptor.FieldDescriptorProto_TYPE_STRING.Enum().Enum(), + TypeName: proto.String(foofqn), + Label: descriptor.FieldDescriptorProto_LABEL_REPEATED.Enum(), + } + updateReq := &descriptor.DescriptorProto{ Name: proto.String("UpdateRequest"), - Field: []*descriptor.FieldDescriptorProto{fooField, maskField}, + Field: []*descriptor.FieldDescriptorProto{fooField, maskField, repeatedPrimField}, } updateReqFqn := fmt.Sprintf(".%s.UpdateRequest", pkg) diff --git a/internal/gengapic/testdata/rest_UpdateRPC.want b/internal/gengapic/testdata/rest_UpdateRPC.want index 7d31bdfa9..2236933f9 100644 --- a/internal/gengapic/testdata/rest_UpdateRPC.want +++ b/internal/gengapic/testdata/rest_UpdateRPC.want @@ -14,6 +14,11 @@ func (c *fooRESTClient) UpdateRPC(ctx context.Context, req *foopb.UpdateRequest, params := url.Values{} params.Add("$alt", "json;enum-encoding=int") + if items := req.GetPrimitives(); len(items) > 0 { + for _, item := range items { + params.Add("primitives", fmt.Sprintf("%v", item)) + } + } if req.GetUpdateMask() != nil { updateMask, err := protojson.Marshal(req.GetUpdateMask()) if err != nil {