Go gin嵌套JSON请求体POST,错误意外结束JSON输入

发布于 01-17 12:57 字数 5675 浏览 5 评论 0原文

我是GO的新手,并且试图用gingorm创建一个简单的post api。

请求数据嵌套JSON如下:

{
  "fall_orders_request": [
    {
      "fruit": "Watermelon",
      "vegetable": "Carrot"
    }
  ],
  "spring_orders_request": [
    {
      "fruit": "Watermelon",
      "vegetable": "Carrot",
      "cupcake": "minions"
    }
  ],
  "custome_rates": [
    {
      "fruit": "Watermelon",
      "greentea": "Japanese",
      "cupcake": "pokemon"
    }
  ]
}

接收请求IE 订单后端将其保存到每个会话的相应数据库中。

这是我的orders.go的代码:

package order

import (
    "net/http"

    "github.com/gin-gonic/gin"

    "gorm.io/gorm"
)

type FallOrders struct {
    ID        uint   `gorm:"primarykey"`
    Fruit     string `json:"fruit"`
    Vegetable string `json:"vegetable"`
}

type SpringOrders struct {
    ID        uint   `gorm:"primarykey"`
    Fruit     string `json:"fruit"`
    Vegetable string `json:"vegetable"`
    Cupcake   string `json:"cupcake"`
}

type WinterOrders struct {
    ID       uint   `gorm:"primarykey"`
    Fruit    string `json:"fruit"`
    Greentea string `json:"greentea"`
    Cupcake  string `json:"cupcake"`
}

type allOrders struct {
    FallOrders   []FallOrders   `json:"fall_orders"`
    SpringOrders []SpringOrders `json:"spring_orders"`
    WinterOrders []WinterOrders `json:"winter_orders"`
}

type FallOrdersRequest struct {
    Fruit     string `json:"fruit"`
    Vegetable string `json:"vegetable"`
}

type SpringOrdersRequest struct {
    Fruit     string `json:"fruit"`
    Vegetable string `json:"vegetable"`
    Cupcake   string `json:"cupcake"`
}

type WinterOrdersRequest struct {
    Fruit    string `json:"fruit"`
    Greentea string `json:"greentea"`
    Cupcake  string `json:"cupcake"`
}

type AllOrdersRequest struct {
    FallOrdersRequest   []FallOrdersRequest   `json:"fall_orders_request"`
    SpringOrdersRequest []SpringOrdersRequest `json:"spring_orders_request"`
    WinterOrdersRequest []WinterOrdersRequest `json:"winter_orders_request"`
}

type AllOrdersManager struct {
    DB *gorm.DB
}

type FallOrdersManager struct {
    DB *gorm.DB
}

type SpringOrdersManager struct {
    DB *gorm.DB
}

type WinterOrdersManager struct {
    DB *gorm.DB
}

func CreateModularRates() gin.HandlerFunc {
    return func(c *gin.Context) {
        var aor AllOrdersRequest
        var form FallOrdersManager
        var sorm SpringOrdersManager
        var worm WinterOrdersManager

        if err := c.BindJSON(&aor); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }

        for _, fall := range aor.FallOrdersRequest {

            fallOrders := FallOrders{
                Fruit:     fall.Fruit,
                Vegetable: fall.Vegetable,
            }
            c.JSON(http.StatusCreated, fallOrders)
            res := form.DB.Create(&fallOrders)
            if res.Error != nil {
                return
            }
        }

        for _, spring := range aor.SpringOrdersRequest {

            springOrders := SpringOrders{
                Fruit:     spring.Fruit,
                Vegetable: spring.Vegetable,
                Cupcake:   spring.Cupcake,
            }
            c.JSON(http.StatusCreated, springOrders)
            res := sorm.DB.Create(&springOrders)
            if res.Error != nil {
                return
            }
        }

        for _, winter := range aor.WinterOrdersRequest {

            winterOrders := WinterOrders{
                Fruit:    winter.Fruit,
                Greentea: winter.Greentea,
                Cupcake:  winter.Cupcake,
            }
            c.JSON(http.StatusCreated, winterOrders)
            res := worm.DB.Create(&winterOrders)
            if res.Error != nil {
                return
            }
        }

    }
}

这是自动测试orders_test.go

package order

import (
    "bytes"
    "encoding/json"
    "net/http"
    "net/http/httptest"
    "testing"

    "github.com/gin-gonic/gin"
    "github.com/stretchr/testify/assert"
)

func TestOrderData() order.AllOrdersRequest {
    fall_orders_request := []order.FallOrdersRequest{}
    spring_orders_request := []order.SpringOrdersRequest{}
    winter_orders_request := []order.WinterOrdersRequest{}
    fall_orders_request = append(fall_orders_request, order.FallOrdersRequest{
        Fruit:     "Watermelon",
        Vegetable: "Carrot",
    })
    spring_orders_request = append(spring_orders_request, order.spring_orders_request{
        Fruit:     "Watermelon",
        Vegetable: "Carrot",
        Cupcake:   "minions",
    })
    winter_orders_request = append(winter_orders_request, order.winter_orders_request{
        Fruit:    "Watermelon",
        Greentea: "Japanese",
        Cupcake:  "pokemon",
    })

    return order.AllOrdersRequest{
        fall_orders_request:   fall_orders_request,
        spring_orders_request: spring_orders_request,
        winter_orders_request: winter_orders_request,
    }
}

func TestOrderCreation(t *testing.T) {
    params := TestOrderData()

    jsonPayload, _ := json.Marshal(params)
    w := httptest.NewRecorder()
    req, _ := http.NewRequest(
        "POST",
        "/orders",
        bytes.NewReader(jsonPayload),
    )
    var c *gin.Context
    assert.Equal(t, 201, w.Code)
    err2 := c.ShouldBindJSON(&req)
    if err2 == nil {
        return
    }

}

运行测试后,我会收到以下错误:

Error: unexpected end of JSON input
{"message":"Error #01: EOF\n"}

记录请求显示请求主体JSON是预期的,但不确定为什么我会遇到此错误。

I am new to GO and was trying to create a simple POST API with gin and gorm.

The request data is nested JSON like below:

{
  "fall_orders_request": [
    {
      "fruit": "Watermelon",
      "vegetable": "Carrot"
    }
  ],
  "spring_orders_request": [
    {
      "fruit": "Watermelon",
      "vegetable": "Carrot",
      "cupcake": "minions"
    }
  ],
  "custome_rates": [
    {
      "fruit": "Watermelon",
      "greentea": "Japanese",
      "cupcake": "pokemon"
    }
  ]
}

After receiving the request i.e orders the backend will save it to corresponding Databases for each session.

This is my code for the orders.go:

package order

import (
    "net/http"

    "github.com/gin-gonic/gin"

    "gorm.io/gorm"
)

type FallOrders struct {
    ID        uint   `gorm:"primarykey"`
    Fruit     string `json:"fruit"`
    Vegetable string `json:"vegetable"`
}

type SpringOrders struct {
    ID        uint   `gorm:"primarykey"`
    Fruit     string `json:"fruit"`
    Vegetable string `json:"vegetable"`
    Cupcake   string `json:"cupcake"`
}

type WinterOrders struct {
    ID       uint   `gorm:"primarykey"`
    Fruit    string `json:"fruit"`
    Greentea string `json:"greentea"`
    Cupcake  string `json:"cupcake"`
}

type allOrders struct {
    FallOrders   []FallOrders   `json:"fall_orders"`
    SpringOrders []SpringOrders `json:"spring_orders"`
    WinterOrders []WinterOrders `json:"winter_orders"`
}

type FallOrdersRequest struct {
    Fruit     string `json:"fruit"`
    Vegetable string `json:"vegetable"`
}

type SpringOrdersRequest struct {
    Fruit     string `json:"fruit"`
    Vegetable string `json:"vegetable"`
    Cupcake   string `json:"cupcake"`
}

type WinterOrdersRequest struct {
    Fruit    string `json:"fruit"`
    Greentea string `json:"greentea"`
    Cupcake  string `json:"cupcake"`
}

type AllOrdersRequest struct {
    FallOrdersRequest   []FallOrdersRequest   `json:"fall_orders_request"`
    SpringOrdersRequest []SpringOrdersRequest `json:"spring_orders_request"`
    WinterOrdersRequest []WinterOrdersRequest `json:"winter_orders_request"`
}

type AllOrdersManager struct {
    DB *gorm.DB
}

type FallOrdersManager struct {
    DB *gorm.DB
}

type SpringOrdersManager struct {
    DB *gorm.DB
}

type WinterOrdersManager struct {
    DB *gorm.DB
}

func CreateModularRates() gin.HandlerFunc {
    return func(c *gin.Context) {
        var aor AllOrdersRequest
        var form FallOrdersManager
        var sorm SpringOrdersManager
        var worm WinterOrdersManager

        if err := c.BindJSON(&aor); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }

        for _, fall := range aor.FallOrdersRequest {

            fallOrders := FallOrders{
                Fruit:     fall.Fruit,
                Vegetable: fall.Vegetable,
            }
            c.JSON(http.StatusCreated, fallOrders)
            res := form.DB.Create(&fallOrders)
            if res.Error != nil {
                return
            }
        }

        for _, spring := range aor.SpringOrdersRequest {

            springOrders := SpringOrders{
                Fruit:     spring.Fruit,
                Vegetable: spring.Vegetable,
                Cupcake:   spring.Cupcake,
            }
            c.JSON(http.StatusCreated, springOrders)
            res := sorm.DB.Create(&springOrders)
            if res.Error != nil {
                return
            }
        }

        for _, winter := range aor.WinterOrdersRequest {

            winterOrders := WinterOrders{
                Fruit:    winter.Fruit,
                Greentea: winter.Greentea,
                Cupcake:  winter.Cupcake,
            }
            c.JSON(http.StatusCreated, winterOrders)
            res := worm.DB.Create(&winterOrders)
            if res.Error != nil {
                return
            }
        }

    }
}

And this is the automated test orders_test.go

package order

import (
    "bytes"
    "encoding/json"
    "net/http"
    "net/http/httptest"
    "testing"

    "github.com/gin-gonic/gin"
    "github.com/stretchr/testify/assert"
)

func TestOrderData() order.AllOrdersRequest {
    fall_orders_request := []order.FallOrdersRequest{}
    spring_orders_request := []order.SpringOrdersRequest{}
    winter_orders_request := []order.WinterOrdersRequest{}
    fall_orders_request = append(fall_orders_request, order.FallOrdersRequest{
        Fruit:     "Watermelon",
        Vegetable: "Carrot",
    })
    spring_orders_request = append(spring_orders_request, order.spring_orders_request{
        Fruit:     "Watermelon",
        Vegetable: "Carrot",
        Cupcake:   "minions",
    })
    winter_orders_request = append(winter_orders_request, order.winter_orders_request{
        Fruit:    "Watermelon",
        Greentea: "Japanese",
        Cupcake:  "pokemon",
    })

    return order.AllOrdersRequest{
        fall_orders_request:   fall_orders_request,
        spring_orders_request: spring_orders_request,
        winter_orders_request: winter_orders_request,
    }
}

func TestOrderCreation(t *testing.T) {
    params := TestOrderData()

    jsonPayload, _ := json.Marshal(params)
    w := httptest.NewRecorder()
    req, _ := http.NewRequest(
        "POST",
        "/orders",
        bytes.NewReader(jsonPayload),
    )
    var c *gin.Context
    assert.Equal(t, 201, w.Code)
    err2 := c.ShouldBindJSON(&req)
    if err2 == nil {
        return
    }

}

After running the test I get the following error:

Error: unexpected end of JSON input
{"message":"Error #01: EOF\n"}

Logging the request shows the request body is JSON as expected but not sure why I am getting this error.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甜嗑2025-01-24 12:57:06

软件包中

如果您已经在order order.spring_orders_requestorder.winter_orders_request应该是order.springordersrequestorder> order> winterordersrequest

spring_orders_request = append(spring_orders_request, order.spring_orders_request{
    Fruit:     "Watermelon",
    Vegetable: "Carrot",
    Cupcake:   "minions",
})
winter_orders_request = append(winter_orders_request, order.winter_orders_request{
    Fruit:    "Watermelon",
    Greentea: "Japanese",
    Cupcake:  "pokemon",
})

此处的关键是错误的是fall_orders_requestspring_orders_requestwinter_orders_request应该是fallordersrequestspring> spring> spring> > winterordersrequest

return order.AllOrdersRequest{
       fall_orders_request:   fall_orders_request,
       spring_orders_request: spring_orders_request,
       winter_orders_request: winter_orders_request,
}

最终:

package order

import (
    "fmt"

    "bytes"
    "encoding/json"
    "net/http"
    "net/http/httptest"
    "testing"

    // "github.com/gin-gonic/gin"
    "github.com/stretchr/testify/assert"
)

func OrderData() AllOrdersRequest {
    fall_orders_request := []FallOrdersRequest{}
    spring_orders_request := []SpringOrdersRequest{}
    winter_orders_request := []WinterOrdersRequest{}
    fall_orders_request = append(fall_orders_request, FallOrdersRequest{
        Fruit:     "Watermelon",
        Vegetable: "Carrot",
    })
    spring_orders_request = append(spring_orders_request, SpringOrdersRequest{
        Fruit:     "Watermelon",
        Vegetable: "Carrot",
        Cupcake:   "minions",
    })
    winter_orders_request = append(winter_orders_request, WinterOrdersRequest{
        Fruit:    "Watermelon",
        Greentea: "Japanese",
        Cupcake:  "pokemon",
    })

    return AllOrdersRequest{
        FallOrdersRequest:   fall_orders_request,
        SpringOrdersRequest: spring_orders_request,
        WinterOrdersRequest: winter_orders_request,
    }
}

func TestOrderCreation(t *testing.T) {
    params := OrderData()

    jsonPayload, _ := json.Marshal(params)
    // fmt.Println(jsonPayload)
    _bytes := bytes.NewReader(jsonPayload)

    // default `ResponseRecorder` `http.Response` status is 200
    // we need to update it to 201 before we access it in `assert`
    w := httptest.NewRecorder()
    w.WriteHeader(201)
    contentLength, err := w.Write(jsonPayload)
    fmt.Println(contentLength, err)
    req, _ := http.NewRequest(
        "POST",
        "http://localhost:8080/orders",
        _bytes,
    )
    assert.Equal(t, 201, w.Code)
    res := w.Result()
    fmt.Println(req)
    fmt.Println(res)
    // Not sure what you are trying to do here but since there is nothing
    // in the context and req variable is already defined of `http.Request` type
    // below statements doesn't make sense.
    // var c *gin.Context
    // if err := c.ShouldBindJSON(&req); err != nil {
    //     return
    // }
}

If you are already in the order package you don't need it to reference it in each place you can directly access the method defined in the order package

Here struct name are incorrect order.spring_orders_request, order.winter_orders_request it should be order.SpringOrdersRequest, order.WinterOrdersRequest

spring_orders_request = append(spring_orders_request, order.spring_orders_request{
    Fruit:     "Watermelon",
    Vegetable: "Carrot",
    Cupcake:   "minions",
})
winter_orders_request = append(winter_orders_request, order.winter_orders_request{
    Fruit:    "Watermelon",
    Greentea: "Japanese",
    Cupcake:  "pokemon",
})

The key here are wrong is fall_orders_request, spring_orders_request, winter_orders_request it should be FallOrdersRequest, SpringOrdersRequest, WinterOrdersRequest

return order.AllOrdersRequest{
       fall_orders_request:   fall_orders_request,
       spring_orders_request: spring_orders_request,
       winter_orders_request: winter_orders_request,
}

Final:

package order

import (
    "fmt"

    "bytes"
    "encoding/json"
    "net/http"
    "net/http/httptest"
    "testing"

    // "github.com/gin-gonic/gin"
    "github.com/stretchr/testify/assert"
)

func OrderData() AllOrdersRequest {
    fall_orders_request := []FallOrdersRequest{}
    spring_orders_request := []SpringOrdersRequest{}
    winter_orders_request := []WinterOrdersRequest{}
    fall_orders_request = append(fall_orders_request, FallOrdersRequest{
        Fruit:     "Watermelon",
        Vegetable: "Carrot",
    })
    spring_orders_request = append(spring_orders_request, SpringOrdersRequest{
        Fruit:     "Watermelon",
        Vegetable: "Carrot",
        Cupcake:   "minions",
    })
    winter_orders_request = append(winter_orders_request, WinterOrdersRequest{
        Fruit:    "Watermelon",
        Greentea: "Japanese",
        Cupcake:  "pokemon",
    })

    return AllOrdersRequest{
        FallOrdersRequest:   fall_orders_request,
        SpringOrdersRequest: spring_orders_request,
        WinterOrdersRequest: winter_orders_request,
    }
}

func TestOrderCreation(t *testing.T) {
    params := OrderData()

    jsonPayload, _ := json.Marshal(params)
    // fmt.Println(jsonPayload)
    _bytes := bytes.NewReader(jsonPayload)

    // default `ResponseRecorder` `http.Response` status is 200
    // we need to update it to 201 before we access it in `assert`
    w := httptest.NewRecorder()
    w.WriteHeader(201)
    contentLength, err := w.Write(jsonPayload)
    fmt.Println(contentLength, err)
    req, _ := http.NewRequest(
        "POST",
        "http://localhost:8080/orders",
        _bytes,
    )
    assert.Equal(t, 201, w.Code)
    res := w.Result()
    fmt.Println(req)
    fmt.Println(res)
    // Not sure what you are trying to do here but since there is nothing
    // in the context and req variable is already defined of `http.Request` type
    // below statements doesn't make sense.
    // var c *gin.Context
    // if err := c.ShouldBindJSON(&req); err != nil {
    //     return
    // }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文