'How to parse POST request body with arbitrary number of parameters in Go Fiber/ fasthttp
type Person struct {
    Name string `json:"name" xml:"name" form:"name"`
    Pass string `json:"pass" xml:"pass" form:"pass"`
}
app.Post("/", func(c *fiber.Ctx) error {
        p := new(Person)
        if err := c.BodyParser(p); err != nil {
            return err
        }
        log.Println(p.Name) // john
        log.Println(p.Pass) // doe
        // ...
})
Above is the code to Parse a POST request with a struct. In my case, the number of POST parameters can be any number. How will it be parsed in that situation?
Solution 1:[1]
JSON (application/json)
Curl request for multiple parameters
curl -X POST -H "Content-Type: application/json" --data '[{"name":"john","pass":"doe"},{"name": "jack", "pass":"jill"}]' localhost:3000
Code:
package main
import (
  "log"
  "github.com/gofiber/fiber/v2"
)
type Person struct {
  Name string `json:"name" xml:"name" form:"name"`
  Pass string `json:"pass" xml:"pass" form:"pass"`
}
func main() {
  app := fiber.New()
  app.Post("/", func(c *fiber.Ctx) error {
    persons := []Person{}
    if err := c.BodyParser(&persons); err != nil {
      return err
    }
    log.Printf("%#v\n", persons)
    // []main.Person{main.Person{Name:"john", Pass:"doe"}, main.Person{Name:"jack", Pass:"jill"}}
    return c.SendString("Post Called")
  })
  app.Listen(":3000")
}
Form (application/x-www-form-urlencoded)
After exploring go-fiber source code which has custom form data processing implementation at the moment which doesn't seem to support slice of custom type ([]Person{}).
For more information you can check these links to go-fiber source code which process form data: 1 2 3
Instead we can use go-playground/form to process form data
Curl request for multiple parameters
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --data '[0].name=john&[0].pass=doe&[1].name=jack&[1].pass=jill' localhost:3000
Code:
package main
import (
  "log"
  "net/url"
  "github.com/gofiber/fiber/v2"
  "github.com/go-playground/form/v4"
)
type Person struct {
  Name string `json:"name" xml:"name" form:"name"`
  Pass string `json:"pass" xml:"pass" form:"pass"`
}
var decoder = form.NewDecoder()
func main() {
  app := fiber.New()
  app.Post("/", func(c *fiber.Ctx) error {
    persons := []Person{}
    m, err := url.ParseQuery(string(c.Body()))
    if err != nil {
      return err
    }
    err = decoder.Decode(&persons, m)
    if err != nil {
      return err
    }
    log.Printf("%#v\n", persons)
    // []main.Person{main.Person{Name:"john", Pass:"doe"}, main.Person{Name:"jack", Pass:"jill"}}
    return c.SendString("Post Called")
  })
  app.Listen(":3000")
}
I have raised an issue and PR at go-fiber github repository which has been merged so below request and code will work now.
Curl request for multiple parameters
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --data 'persons[0].name=one&persons[0].pass=1&persons[1].name=two&persons[1].pass=2' localhost:3000
Code:
package main
import (
    "log"
    "github.com/gofiber/fiber/v2"
)
// recommendation -> name of the api and parameters
type ApiParameters struct {
    Persons []Person `query:"persons" json:"persons" xml:"persons" form:"persons"`
}
type Person struct {
    Name string `query:"name" json:"name" xml:"name" form:"name"`
    Pass string `query:"pass" json:"pass" xml:"pass" form:"pass"`
}
func main() {
    app := fiber.New()
    app.Post("/", func(c *fiber.Ctx) error {
        parameters := ApiParameters{}
        if err := c.BodyParser(¶meters); err != nil {
            return err
        }
        log.Printf("POST: %#v\n", parameters)
        return c.SendString("Post Called")
    })
    log.Fatalln(app.Listen(":3000"))
}
Solution 2:[2]
You may find that creating an empty map will work, this code is from enter link description here as follows:(Edited to simplify)
var x map[string]interface{}
json.Unmarshal([]byte(str), &x)
str2 := "{"foo":{"baz": [1,2,3]}}"
var y map[string]interface{}
json.Unmarshal([]byte(str2), &y)
fmt.Println("%v", y)
So you would
err = c.BodyParser(str2)
In this example. Hope it helps.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | |
| Solution 2 | 
