-1

Send json data to golang fiber, try to bind data received from fiber to struct but it fails,

type MapTag struct {
    Id        uint      `json:"id" form:"tag_name" xorm:"bigint unsigned pk autoincr"`
    TagName   string    `json:"tag_name" form:"tag_name" xorm:"index"`
    CreatedAt time.Time `json:"created_at" form:"created_at" xorm:"timestamp created"`
    UpdatedAt time.Time `json:"updated_at" form:"updated_at" xorm:"timestamp updated"`
}
type _inData struct {
    Title   string         `json:"title" form:"title"`
    TagList []model.MapTag `json:"tag_list" form:"tag_list"`
}


inData := new(_inData)
c.BodyParser(inData)

fmt.Print(inData)

result is &{title.value []}, Why can't bind to TagList??

i sened, json like that {"title" : "title.value", "tag_list":[{"id":"1", "tag_name" :"test"},{"id":"2","tag_name":"test2"}]}

I'm wasting a lot of time, please help

Again, I wrote the code as below,

fmt.Println(string(c.Body()))
type _inData struct {
    Title   string
    TagList []model.MapTag `form:"tag_list"`
}
inData := &_inData{}
if err := c.BodyParser(inData); err != nil {
    return err
}
fmt.Println(inData)

I get the result as below, still not binding to tagList

{"title":"123123","tag_list":[{"id":42,"tag_name":"234234"}, 
{"id":43,"tag_name":"345345"}]}

&{123123 []}

I am sending data from flutter to golang fiber as below, Could it be of any help in resolving the question?

var response = await dio.post(
  Uri.parse(System.baseV1 + "/v1/map/create").toString(),
  data: {
    "title": mapTitle,
    "tag_list": tagList.toList(),
    // "file": await MultipartFile.fromFile(mainImage!.path),
  },
  options: Options(
    headers: {
      "Authorization": "Barer " + storage.getString('token').toString(),
      "Content-Type": "application/json"
    },
  ),
);
Choi yun seok
  • 309
  • 2
  • 15
  • Don't know about fiber, but if it is using stdlib json unmarshaling, the id in the input is a string, not an `uint`, and that may be the reason. – Burak Serdar Oct 30 '21 at 04:27
  • The error returned from `c.BodyParser(inData)` probably tells you what's wrong. Always check and handle errors. – Charlie Tumahai Oct 30 '21 at 04:40
  • slice unexpected end of JSON input << I'm getting the same error and I don't know how to fix it – Choi yun seok Oct 30 '21 at 04:57
  • Using `json.Unmarshal` on your sample input, [there is no error](https://play.golang.org/p/t55IXu4rpNw) (after fixing the type of `Id` field). Please consider adding more debug information to your question, e.g. the request that is failing, a minimal handler that reproduces the issue, etc. – blackgreen Oct 30 '21 at 09:55

1 Answers1

0

I am a frequent Fiber user.

The reason that happens is because you were not defining Content-Type: application/json as one of your headers in your request body, and you sent your request body wrongly.

Here's a solution that I hacked up.

package main

import (
    "fmt"
    "net/http"
    "time"

    "github.com/gofiber/fiber/v2"
)

type MapTag struct {
    Id        uint      `json:"id" form:"tag_name" xorm:"bigint unsigned pk autoincr"`
    TagName   string    `json:"tag_name" form:"tag_name" xorm:"index"`
    CreatedAt time.Time `json:"created_at" form:"created_at" xorm:"timestamp created"`
    UpdatedAt time.Time `json:"updated_at" form:"updated_at" xorm:"timestamp updated"`
}

type Input struct {
    Title   string   `json:"title" form:"title"`
    TagList []MapTag `json:"tag_list" form:"tag_list"`
}

func main() {
    app := fiber.New()

    app.Post("/", func(c *fiber.Ctx) error {
        data := &Input{}

        if err := c.BodyParser(data); err != nil {
            return err
        }

        fmt.Println(data)

        return c.SendStatus(http.StatusOK)
    })

    app.Listen(":8080")
}

You also have a problem with your JSON string. You should send a literal number (for your id attribute), not a string. Send your JSON body like the following.

curl -H "Content-Type: application/json" -X POST -d '{"title":"title.value", "tag_list":[{"id":1, "tag_name" :"test"},{"id":2,"tag_name":"test2"}]}' http://localhost:8080; echo

It should bring a result like this.

akasha@Akashas-MacBook-Pro so-answers % go run main.go

# snip...

&{title.value [{1 test 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC} {2 test2 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC}]}

If you need a further explanation on that matter, check out the docs.

Binds the request body to a struct. BodyParser supports decoding query parameters and the following content types based on the Content-Type header:

  • application/json
  • application/xml
  • application/x-www-form-urlencoded
  • multipart/form-data

Check out below reference in Fiber's official example repository in GitHub for further information (disclaimer: I wrote it)

Nicholas
  • 2,800
  • 1
  • 14
  • 21
  • I don't want to assume anything, but why do you need `model.MapTag` if both `MapTag` and `_inData` exist in the same package? Could you also make it clear what you want to ask? – Nicholas Oct 30 '21 at 11:17
  • I've edited the question, can you please confirm? – Choi yun seok Oct 30 '21 at 11:38
  • You forgot the `json:"tag_list"` if you're sending the body as JSON. Can you also explain how did you send your request body to the backend? – Nicholas Oct 30 '21 at 12:08
  • I am sending data with flutter, can you tell me which part is wrong? Edited the question thank you – Choi yun seok Oct 31 '21 at 14:57