当前位置:首页 > 文章列表 > 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基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • 笔灵AI生成答辩PPT:高效制作学术与职场PPT的利器
    笔灵AI生成答辩PPT
    探索笔灵AI生成答辩PPT的强大功能,快速制作高质量答辩PPT。精准内容提取、多样模板匹配、数据可视化、配套自述稿生成,让您的学术和职场展示更加专业与高效。
    23次使用
  • 知网AIGC检测服务系统:精准识别学术文本中的AI生成内容
    知网AIGC检测服务系统
    知网AIGC检测服务系统,专注于检测学术文本中的疑似AI生成内容。依托知网海量高质量文献资源,结合先进的“知识增强AIGC检测技术”,系统能够从语言模式和语义逻辑两方面精准识别AI生成内容,适用于学术研究、教育和企业领域,确保文本的真实性和原创性。
    35次使用
  • AIGC检测服务:AIbiye助力确保论文原创性
    AIGC检测-Aibiye
    AIbiye官网推出的AIGC检测服务,专注于检测ChatGPT、Gemini、Claude等AIGC工具生成的文本,帮助用户确保论文的原创性和学术规范。支持txt和doc(x)格式,检测范围为论文正文,提供高准确性和便捷的用户体验。
    37次使用
  • 易笔AI论文平台:快速生成高质量学术论文的利器
    易笔AI论文
    易笔AI论文平台提供自动写作、格式校对、查重检测等功能,支持多种学术领域的论文生成。价格优惠,界面友好,操作简便,适用于学术研究者、学生及论文辅导机构。
    46次使用
  • 笔启AI论文写作平台:多类型论文生成与多语言支持
    笔启AI论文写作平台
    笔启AI论文写作平台提供多类型论文生成服务,支持多语言写作,满足学术研究者、学生和职场人士的需求。平台采用AI 4.0版本,确保论文质量和原创性,并提供查重保障和隐私保护。
    40次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码