url.Values中的嵌套值

I'm working on an API client and I need to be able to send a nested JSON structure with a client.PostForm request. The issue I'm encountering is this:

reqBody := url.Values{
    "method": {"server-method"},
    "arguments": {
        "download-dir": {"/path/to/downloads/dir"},
        "filename":     {variableWithURL},
        "paused":       {"false"},
    },
}

When I try to go build this, I get the following errors:

./transmission.go:17: syntax error: unexpected :, expecting }
./transmission.go:24: non-declaration statement outside function body
./transmission.go:26: non-declaration statement outside function body
./transmission.go:27: non-declaration statement outside function body
./transmission.go:29: non-declaration statement outside function body
./transmission.go:38: non-declaration statement outside function body
./transmission.go:39: syntax error: unexpected }

I'm wondering what the correct way to created a nested set of values in this scenario. Thanks in advance!

You are not using properly the url.Values, according to the source code (url package, url.go):

// Values maps a string key to a list of values.
// It is typically used for query parameters and form values.
// Unlike in the http.Header map, the keys in a Values map
// are case-sensitive.
type Values map[string][]string

But arguments is not compliant with the definition because the object of arguments is not an array of strings.

I was able to figure this out on my own! The answer is to struct all-the-things!

type Command struct {
    Method          string      `json:"method,omitempty"`
    Arguments       Arguments   `json:"arguments,omitempty"`
}

type Arguments struct {
    DownloadDir     string      `json:"download-dir,omitempty"`
    Filename        string      `json:"filename,omitempty"`
    Paused          bool        `json:"paused,omitempty"`
}

Then, when creating your PostForm:

jsonBody, err := json.Marshal(reqBody) // reqBody is a Command

if (err != nil) {
    return false
}

req, err := http.NewRequest("POST", c.Url, strings.NewReader(string(jsonBody)))

Hope this helps!

I used NewRequest as Connor mentions in his answer but using a struct and then marshalling it seems an unnecessary step to me.

I passed my nested json string straight to strings.NewReader:

import (
    "net/http"
    "strings"
)

reqBody := strings.NewReader(`{
    "method": {"server-method"},
    "arguments": {
        "download-dir": {"/path/to/downloads/dir"},
        "paused":       {"false"},
    },
}`)

req, err := http.NewRequest("POST", "https://httpbin.org/post", reqBody)

Hope it helps those who are stuck with Go's http PostForm which only accepts url.Values as argument while url.Values cannot generate nested json.