Why is the result of the gourl.ParseQuery method so unexpected?

The result of this program is {"x":["1 1 3"], "y":["2", "3"]}.
But why is not {"x":["1+1+3"], "y":["2", "3"]}?
What do I need to do to get the expected result"1+1+3"?

import (
    "encoding/json"
    "fmt"
    "log"
    "net/url"
    "strings"
)

func main() {
    m, err := url.ParseQuery(`x=1+1+3&y=2&y=3`)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(toJSON(m))
}

func toJSON(m any) string {
    js, err := json.Marshal(m)
    if err != nil {
        log.Fatal(err)
    }
    return strings.ReplaceAll(string(js), ",", ", ")
}

Sandbox: https://go.dev/play/p/o0TiRTVpaQk

{"x":["1+1+3"], "y":["2", "3"]}

>Solution :

url.ParseQuery replaces + with

relevant code fragment:

        case '+':
            if mode == encodeQueryComponent {
                t.WriteByte(' ')
            } else {
                t.WriteByte('+')
            }

the solution is to encode + (replace them with %2B)

like so:

import (
    "encoding/json"
    "fmt"
    "log"
    "net/url"
    "strings"
)

func main() {
    m, err := url.ParseQuery(`x=1%2B1%2B3&y=2&y=3`)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(toJSON(m))
}

func toJSON(m any) string {
    js, err := json.Marshal(m)
    if err != nil {
        log.Fatal(err)
    }
    return strings.ReplaceAll(string(js), ",", ", ")
}

Leave a Reply