Get nested key value pair of x-www-form-urlencoded request in JSON format in golang

400 Views Asked by At

I have use case where we are getting nested key value in x-www-form-urlencoded body like below

name=abc&age=12&notes[key1]=value1&notes[key2]=value2

I tried url.ParseQuery("name=abc&age=12&notes\[key1\]=value1&notes\[key2\]=value2") but it's giving

{
  "name": "abc",
  "age": 12,
  "notes[key1]": "value1",
  "notes[key2]": "value2"
}

How can I get this value in below JSON format for above body

{
  "name": "abc",
  "age": 12,
  "notes": {
    "key1": "value1",
    "key2": "value2"
  }
}

There is possibility that notes might be in 3 level nested format

I have tried url.ParseQuery and r.Form but both of them giving notes[key1] and notes[key2].

1

There are 1 best solutions below

0
Grokify On BEST ANSWER

To unmarshal nested key values with this type of query string parameter names, it's possible to use derekstavis/go-qs which is a port of Rack's query string parser.

This returns a map[string]interface{} with nested key values as follows.

Of note, the value for age is returned as a string, however, this is the same for url.ParseQuery. If marshaling this to an integer is desired, the package can be forked and modified.

{
  "age": "12",
  "name": "abc",
  "notes": {
    "key1": "value1",
    "key2": "value2"
  }
}

A complete example is available on the Go Playground with the following code:

Go Playground URL: https://go.dev/play/p/Px7uZWRNs5V

package main

import (
    "encoding/json"
    "fmt"
    "log"

    qs "github.com/derekstavis/go-qs"
)

func main() {
    v := "name=abc&age=12&notes[key1]=value1&notes[key2]=value2"

    q, err := qs.Unmarshal(v)
    if err != nil {
        log.Fatal(err)
    }

    j, err := json.MarshalIndent(q, "", "  ")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(j))
}