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



我是GO的新手,曾尝试使用gingorm创建一个简单的POSTAPI。

请求数据嵌套在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"
}
]
}

在接收到请求(即orders(后,后端将其保存到每个会话的相应数据库中。

这是我的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: EOFn"}

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

如果您已经在order包中,您不需要它在每个地方引用它,您可以直接访问order包中定义的方法

此处结构体名称不正确order.spring_orders_requestorder.winter_orders_request应为order.SpringOrdersRequestorder.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应该是FallOrdersRequestSpringOrdersRequestWinterOrdersRequest

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
// }
}

最新更新