当前位置:首页 > 文章列表 > Golang > Go问答 > Go gin嵌套JSON请求体POST,错误意外结束JSON输入

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

来源:stackoverflow 2024-04-30 20:18:37 0浏览 收藏

在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删除
HMD Global将推新手机HMD XR21:诺基亚XR21换标版HMD Global将推新手机HMD XR21:诺基亚XR21换标版
上一篇
HMD Global将推新手机HMD XR21:诺基亚XR21换标版
如何使用 Java 中的信号量实现并发编程?
下一篇
如何使用 Java 中的信号量实现并发编程?
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ljg-skills -
    ljg-skills
    ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
    286次使用
  • MELO音乐 - AI 音乐生成平台,支持多模态创作能力
    MELO音乐
    MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
    303次使用
  • UniScribe - AI 免费在线音视频转文字平台
    UniScribe
    UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
    273次使用
  • 剧云 - 免费 AI 智能中文剧本创作平台
    剧云
    剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
    444次使用
  • 万象有声 - AI 一站式有声内容创作平台
    万象有声
    万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
    433次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码