0

I am working on unit test for a restAPI implementation in Golang. I need to pass an array of object into url. Here is an example of struct I have:

    type version struct {
        Name string `json:"name"`
        Ver  string `json:"ver"`
    }
    
    type event struct {
        ID          string    `json:"id"`
        Title       string    `json:"Title"`
        Description string    `json:"Description"`
        Versions    []version `json:"versions"`
    }

The sample json input i tested in postman will be look like this one

{
    "id": "101",
    "title": "This is simple Golang title for testing!",
    "Description":"Sample code for REST api implementation in Golang 2021!",
    "versions": [
            {
                "name": "pingPong",
                "ver": "10.2"
            },
            {
                "name": "Ninja",
                "ver": "10.24"
            }
    ]

}

My question is that how can i pass an array of objects as URL parameters. I expect to have something like below but not how to fill the ending part i highlighted by the ...

url?ID=20&Title=urlTitle&Description=UrlDescription&...
Ashkanxy
  • 2,380
  • 2
  • 6
  • 17
  • 1
    Convert the struct into `net/url.Values` and encode the result. Keep in mind that the standard for URL query params does not specify how to encode nested structures, consequently the Go implementation doesn't support that. If you want to encode the `Versions` slice into query params you'll have to choose a syntax and implement a solution, or look for one on the web. – mkopriva May 17 '21 at 18:45
  • 2
    URL query strings support only plain text; it has no concept of arrays or objects. Typically a REST API accepts JSON in the request *body*, not the URL. – Adrian May 17 '21 at 20:48

1 Answers1

1

I don't know how you want the URL like, so I wrote it myself in a way that you can change it any way you want, And let me add that I don't know how many versions you have, so I wrote in such a way that no matter how many versions you have, it can handle it.

package main

import (
    "fmt"
    "strings"
    "encoding/json"
)

var jsonData string =
`{
    "id": "101",
    "title": "This is simple Golang title for testing!",
    "Description":"Sample code for REST api implementation in Golang 2021!",
    "versions": [
            {
                "name": "pingPong",
                "ver": "10.2"
            },
            {
                "name": "Ninja",
                "ver": "10.24"
            }
    ]

}`

type (
    Event struct {
        Id          string    `json:"id"`
        Title       string    `json:"title"`
        Description string    `json:"description"`
        Versions    []Version `json:"versions"`
    }

    Version struct {
        Name string `json:"name"`
        Ver  string `json:"ver"`
    }
)

func fillVersions(event *Event, baseUrl string) string {
    var finalUrl string = baseUrl

    for index, value := range event.Versions {
        restUrl := fmt.Sprintf("Version%d=%s-%s", index + 1, value.Name, value.Ver)

        finalUrl = fmt.Sprintf(
            finalUrl + "%s" + "&",
            restUrl,
        )
    }
    return strings.TrimRight(finalUrl, "&")
}

func main() {
    var event Event
    json.Unmarshal([]byte(jsonData), &event)

    baseUrl := fmt.Sprintf(
        "https://test.com/test?Id=%s&Title=%s&Description=%s&",
        event.Id,
        event.Title,
        event.Description,
    )

    finalUrl := fillVersions(&event, baseUrl)

    fmt.Println(finalUrl)
}

The output of the program is as follows:

https://test.com/test?Id=101&Title=This is simple Golang title for testing!&Description=Sample code for REST api implementation in Golang 2021!&Version1=pingPong-10.2&Version2=Ninja-10.24

I would also like to say that the last & will be removed, If you don't want to do this, Remove the following line and write as follows (also remove the strings library from the import scope):

return strings.TrimRight(finalUrl, "&") // remove this
return finalUrl // add this