登录
首页 >  Golang >  Go问答

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

来源:stackoverflow

时间:2024-04-30 20:18:37 209浏览 收藏

在Golang实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《Go gin嵌套JSON请求体POST,错误意外结束JSON输入》,聊聊,希望可以帮助到正在努力赚钱的你。

问题内容

我是 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"
    }
  ]
}

后端收到请求后,即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: EOF\n"}

记录请求显示请求正文是预期的 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它应该是fallordersrequestspringordersrequestwinterorder srequest

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

终于介绍完啦!小伙伴们,这篇关于《Go gin嵌套JSON请求体POST,错误意外结束JSON输入》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>