intellij-openapi-generator icon indicating copy to clipboard operation
intellij-openapi-generator copied to clipboard

Incorrect generation of api controller logic for query parameter that is a map.

Open rocanion opened this issue 5 years ago • 1 comments

I'm trying to specify the use of a query parameter for a GET operation that allows me to filter the list that the GET returns. In my JSON spec I have the path defined with this parameter clause:

{
  "name": "filter",
  "in": "query",
  "required": false,
  "description": "The filter specifies a field name as an array key and a value to search for.",
  "style": "form",
  "schema": {
    "type": "object"
  },
  "example": "/items?filter[CustomerID]=1234"
},

Then I use the go-server generator to make code. The generated code in the controller doesn't seem to properly deal with the fetching of the query param into a map though. Instead, it fetches into a plain string. Here's the code for the get operation that is generated, you can see how it's just trying to pass along a plain string instead of a map:

// ItemsGet - Returns a list of items.
func (c *ItemsApiController) ItemsGet(w http.ResponseWriter, r *http.Request) { 
   query := r.URL.Query()
   filter := query.Get("filter")
   sort := query.Get("sort")
   result, err := c.service.ItemsGet(filter, sort)
   if err != nil {
      w.WriteHeader(500)
      return
   }
   EncodeJSONResponse(result, nil, w)
}

The service file, on the other hand, seems to be crafted correctly:

// ItemsGet - Returns a list of items.
func (s *ItemsApiService) ItemsGet(filter map[string]interface{}, sort map[string]interface{}) (interface{}, error) {
   // TODO - update ItemsGet with the required logic for this service method.
   // Add api_items_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
   return nil, errors.New("service method 'ItemsGet' not implemented")
}

I'm guessing this is a bug in the generator.

rocanion avatar Jun 04 '20 18:06 rocanion

I've done some tinkering to identify some code that will properly parse query parameters that are formatted using an array notation. There's probably a better way but this at least may be helpful.

package main

import (
	"fmt"
	"net/url"
	"strings"
)

func main() {
	var params = map[string]map[string][]string{}
	uri := "filter[CustomerId]=1234&filter[Username]=dan,jane,chris&sort[ID]=asc"
	m, _ := url.ParseQuery(uri)

	for k, v := range m {
		// Check to see if the uri has map-encoded content.
		if strings.Contains(uri, "[") {
			namekey := strings.Split(k, "[")
			name := namekey[0]
			key := strings.Replace(namekey[1], "]", "", 1)
			fmt.Printf("Name: %s, Key: %s, Value: %s\n", name, key, v)
			if params[name] == nil {
				params[name] = map[string][]string{}
			}
			if params[name][key] == nil {
				params[name][key] = []string{}
			}
			params[name][key] = append(params[name][key], v...)
		}
	}
	fmt.Println(params)
}

rocanion avatar Jun 05 '20 18:06 rocanion