2 Go语言JSON与XML解析与表单操作

article/2025/10/16 14:31:20

在这里插入图片描述

2 Go语言JSON与XML解析与表单操作

  • 1 数据交互的格式
  • 2 JSON方式
    • 2.1 JSON序列化
    • 2.2 JSON反序列化
    • 2.3 解析到interface
  • 3 XML方式
    • 3.1 解析XML
    • 3.2 生成XML
  • 4 字段校验
  • 5 文件上传
    • 2.1 前后端模拟上传
    • 2.2 go客户端模拟上传
  • 3 防止重复提交

1 数据交互的格式

常见的数据交互格式有

  • JSON:JavaScript Object Notation,轻量级的数据交换格式,如:{"name":"lisi","address": ["广州","深圳"]}
  • XML:工业开发中常用的数据交互标准格式

2 JSON方式

2.1 JSON序列化

JSON序列化与反序列化需要使用encoding/json包,如下案例所示:

type Person struct {Name stringAge int
}p := Person {Name: "lisi",Age: 50,
}data, _ := json.Marshal(&p)
fmt.Printf(string(data));	 	//{"Name":"lisi","Age":50}

同理,我们也可以使用上述方法对基本数据类型、切片、map等数据进行序列化。

在结构体序列化时,如果希望序列化后的key的名字可以自定义,可以给该结构体指定一个tag标签:

type Person struct {Name string `json:"my_name"`Age int `json:"my_age"`
}//序列化的结果:{"my_name":"lisi","my_age":50}

在定义struct tag的时候需要注意的几点是:

  • 字段的tag是"-",那么这个字段不会输出到JSON
  • tag中如果带有"omitempty"选项,那么如果该字段值为空,就不会输出到JSON串中
  • 如果字段类型是bool, string, int, int64等,而tag中带有",string"选项,那么这个字段在输出到JSON的时候会把该字段对应的值转换成JSON字符串
  • JSON对象只支持string作为key,所以要编码一个map,那么必须是map[string]T这种类型(T是Go语言中任意的类型)
  • Channel, complex和function是不能被编码成JSON的
  • 嵌套的数据是不能编码的,不然会让JSON编码进入死循环
  • 指针在编码的时候会输出指针指向的内容,而空指针会输出null

2.2 JSON反序列化

str :=  `{"Name":"lisi","Age":50}`// 反序列化json为结构体
type Person struct {Name string Age int 
}var p Person
json.Unmarshal([]byte(str), &p)
fmt.Println(p)							//{lisi 50}

2.3 解析到interface

2.1和2.2的案例中,我们知道json的数据结构,可以直接进行序列化操作,如果不知道JSON具体的结构,就需要解析到interface,因为interface{}可以用来存储任意数据类型的对象。

JSON包中采用map[string]interface{}[]interface{}结构来存储任意的JSON对象和数组。Go类型和JSON类型的对应关系如下:

  • bool 代表 JSON booleans,
  • float64 代表 JSON numbers,
  • string 代表 JSON strings,
  • nil 代表 JSON null

现在我们假设有如下的JSON数据

jsonStr := `{"Name":"Lisi","Age":6,"Parents":["Lisan","WW"]}`
jsonBytes := []byte(jsonStr)var i interface{}
json.Unmarshal(jsonBytes, &i)
fmt.Println(i)		// map[Age:6 Name:Lisi Parents:[Lisan WW]]

上述变量i存储了存储了一个map类型,key是strig,值存储在空接口内,
如果在我们不知道他的结构的情况下,我们把他解析到interface{}里面,其真实结构如下:

i = map[string]interface{}{"Name": "Lisi","Age":  6,"Parents": []interface{}{"Lisan","WW",},
}

由于是空接口类型,无法直接访问,需要使用断言方式:

m := i.(map[string]interface{})
for k, v := range m {switch r := v.(type) {case string:fmt.Println(k, " is string ", r)case int:fmt.Println(k, " is int ", r)case []interface{}:fmt.Println(k, " is array ", )for i, u := range r {fmt.Println(i, u)}default:fmt.Println(k, " cannot be recognized")}
}

上面是官方提供的解决方案,操作起来不是很方便,推荐使用第三方包有:

  • https://github.com/bitly/go-simplejson
  • https://github.com/thedevsaddam/gojsonq

3 XML方式

3.1 解析XML

现在有如下books.xml示例:

<?xml version="1.0" encoding="utf-8"?>
<books version="1"><book><bookName>离散数学</bookName><bookPrice>120</bookPrice></book><book><bookName>人月神话</bookName><bookPrice>75</bookPrice></book>
</books>

通过xml包的Unmarshal函数来解析:

package mainimport ("encoding/xml""fmt""io/ioutil""os"
)type BookStore struct {XMLName     xml.Name `xml:"books"`Version     string   `xml:"version,attr"`Store       []book	 `xml:"book"`Description string   `xml:",innerxml"`
}type book struct {XMLName    	xml.Name `xml:"book"`BookName 	string   `xml:"bookName"`BookPrice   string   `xml:"bookPrice"`
}func main() {file, err := os.Open("books.xml") 		if err != nil {fmt.Printf("error: %v", err)return}defer file.Close()data, err := ioutil.ReadAll(file)if err != nil {fmt.Printf("error: %v", err)return}v := BookStore{}err = xml.Unmarshal(data, &v)if err != nil {fmt.Printf("error: %v", err)return}fmt.Println(v)
}

3.2 生成XML

xml包中的MarshalMarshalIndent两个函数,可以用来生成xml。这两个函数主要的区别是第二个函数会增加前缀和缩进,函数的定义如下所示:

package mainimport ("encoding/xml""fmt""os"
)type BookStore struct {XMLName     xml.Name `xml:"books"`Version     string   `xml:"version,attr"`Store       []book	 `xml:"book"`
}type book struct {BookName 	string   `xml:"bookName"`BookPrice   string   `xml:"bookPrice"`
}func main() {bs := &BookStore{Version: "1"}bs.Store = append(bs.Store, book{"离散数学", "120"})bs.Store = append(bs.Store, book{"人月神话", "75"})output, err := xml.MarshalIndent(bs, "  ", "    ")if err != nil {fmt.Printf("error: %v\n", err)}// 生成正确xml头os.Stdout.Write([]byte(xml.Header))os.Stdout.Write(output)
}

4 字段校验

通过内置函数len()可以获取字符串的长度,以此可以校验参数的合法性:

if len(r.Form["username"][0])==0{//为空的处理
}

r.Form对不同类型的表单元素的留空有不同的处理:

  • 空文本框、空文本区域以及文件上传,元素的值为空值
  • 未选中的复选框和单选按钮,则不会在r.Form中产生相应条目,如果我们用上面例子中的方式去获取数据时程序就会报错。所以我们需要通过r.Form.Get()来获取值,因为如果字段不存在,通过该方式获取的是空值。但是通过r.Form.Get()只能获取单个的值,

5 文件上传

2.1 前后端模拟上传

前端代码:

<html>
<head><title>上传文件</title>
</head>
<body>
<form enctype="multipart/form-data" action="/upload" method="post"><input type="file" name="uploadfile" /><input type="submit" value="upload" />
</form>
</body>
</html>

form的enctype属性有如下三种情况:

application/x-www-form-urlencoded		# 表示在发送前编码所有字符(默认)
multipart/form-data	  					# 文件上传使用,不会不对字符编码。
text/plain	  							# 空格转换为 "+" 加号,但不对特殊字符编码。

golang的后端处理代码:

// 上传文件处理路由:http.HandleFunc("/upload", upload)
func upload(w http.ResponseWriter, r *http.Request) {// 设置上传文件能使用的内存大小,超过了,则存储在系统临时文件中r.ParseMultipartForm(32 << 20)// 获取上传文件句柄file, handler, err := r.FormFile("uploadfile")if err != nil {fmt.Println(err)return}defer file.Close()fmt.Fprintf(w, "%v", handler.Header)f, err := os.OpenFile("./upload/" + handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)if err != nil {fmt.Println(err)return}defer f.Close()io.Copy(f, file)
}

2.2 go客户端模拟上传

Go支持模拟客户端表单功能支持文件上传:

package mainimport ("bytes""fmt""io""io/ioutil""mime/multipart""net/http""os"
)func postFile(filename string, targetUrl string) error {bodyBuf := &bytes.Buffer{}bodyWriter := multipart.NewWriter(bodyBuf)//关键的一步操作fileWriter, err := bodyWriter.CreateFormFile("uploadfile", filename)if err != nil {fmt.Println("error writing to buffer")return err}//打开文件句柄操作fh, err := os.Open(filename)if err != nil {fmt.Println("error opening file")return err}defer fh.Close()//iocopy_, err = io.Copy(fileWriter, fh)if err != nil {return err}contentType := bodyWriter.FormDataContentType()bodyWriter.Close()resp, err := http.Post(targetUrl, contentType, bodyBuf)if err != nil {return err}defer resp.Body.Close()resp_body, err := ioutil.ReadAll(resp.Body)if err != nil {return err}fmt.Println(resp.Status)fmt.Println(string(resp_body))return nil
}// sample usage
func main() {target_url := "http://localhost:8080/upload"filename := "./test.pdf"postFile(filename, target_url)
}

3 防止重复提交

防止表单重复提交的方案有很多,其中之一是在表单中添加一个带有唯一值的隐藏字段:

  • 1.在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。
  • 2.将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token
  • 3.表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。

在下列情况下,服务器程序将拒绝处理用户提交的表单请求:

  • 存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。
  • 当前用户的Session中不存在Token(令牌)。
  • 用户提交的表单数据中没有Token(令牌)。
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="hidden" name="token" value="{{.}}">
<input type="submit" value="登陆">

在模版里面增加了一个隐藏字段token,该值通过MD5(时间戳)来确定唯一值,然后我们把这个值存储到服务器端,以方便表单提交时比对判定。

func login(w http.ResponseWriter, r *http.Request) {r.ParseForm()token := r.Form.Get("token")if token != "" {//验证token的合法性} else {//不存在token报错}// 执行具体登录业务
}

在这里插入图片描述


http://chatgpt.dhexx.cn/article/IZfpvmji.shtml

相关文章

C++中json解析开源库收集,支持json5

文章目录 zpl-c 库HJSONcJSONRapidJSON &#xff08;推荐&#xff09;DAW JSON Link v2JSON &#xff0c;这库稳定&#xff0c;文档齐全。(推荐)json-c &#xff08;c实现&#xff09;json_dto (一个小的头文件助手)json11 ( C11 的小型 JSON 库 )json_spirit (开发中&#xff…

SpringBoot之JWT令牌

目录 介绍 生成和校验 登录下发令牌 介绍 JWT全称&#xff1a;JSON Web Token &#xff08;官网&#xff1a;https://jwt.io/&#xff09; 定义了一种简洁的、自包含的格式&#xff0c;用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在&#xff0c;这些信…

七 微服务网关gateWay和Jwt令牌

之前写过一篇微服务网关Zuul&#xff0c;今天介绍gateWay&#xff0c;二者大同小异&#xff0c;但各有优势&#xff0c;大家可以都了解一下&#xff0c;拓展自己的知识面&#xff1b; 一 微服务网关 主要作用 整合各个微服务功能&#xff0c;形成一套系统在微服务网关中实现…

登录校验-会话技术/JWT令牌

登录校验 会话技术 会话&#xff1a; 用户打开浏览器&#xff0c;访问web资源的时候&#xff0c;会话建立。直到一方断开连接&#xff0c;会话结束&#xff0c;一次会话中包含多次响应 会话跟踪&#xff1a;一种维护浏览器状态的方法&#xff0c;服务器需要识别多次请求是否来…

服务的校验Content-Type,只接收application/json格式的CSRF绕过方法

如何在JSON端点上利用CSRF漏洞 转载自&#xff1a;https://www.freebuf.com/articles/web/164234.html Alpha_h4ck &#xff08;CSRF Flash HTTP 307&#xff09;别说了&#xff0c;你已经“死”了&#xff01; 如果你想通过第三方攻击者控制的服务器在JSON端点利用一个CS…

nginx 限流,以及nginx直接返回json格式数据

高并发系统有三把利器用来保护系统&#xff1a;缓存、降级和限流 今天我们这里说说限流。一般会在应用层配合redis做限流策略&#xff0c;这里我们聊聊nginx层限流。 限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统&#xff0c;一旦达…

JWT-JSON Web令牌的深入介绍

JWT-JSON Web令牌的深入介绍 从桌面应用程序到Web应用程序或移动应用程序&#xff0c;身份验证是几乎所有应用程序中最重要的部分之一。 本教程是JWT&#xff08;JSON Web令牌&#xff09;的深入介绍&#xff0c;可帮助您了解&#xff1a; 基于会话的身份验证与基于令牌的身份…

JSON Web Token原理深入理解

什么是JWT JWT全称Json Web Token&#xff0c;翻译为JSON格式的网络令牌&#xff0c;很多时候又简称为Token(JWT是Token的一种实现方式)。它要解决的问题&#xff0c;就是为多种终端设备&#xff0c;提供统一的、安全的令牌格式。因此&#xff0c;JWT只是一个令牌格式而已&…

【JWT】jwt令牌研究

一、JWT介绍 在介绍JWT之前先看一下传统校验令牌的方法&#xff0c;如下图&#xff1a; 问题&#xff1a; 传统授权方法的问题是用户每次请求资源服务&#xff0c;资源服务都需要携带令牌访问认证服务去校验令牌的合法性&#xff0c;并根据令牌获取用户的相关信息&#xff0c…

JWT令牌验证

JWT令牌验证 jwt的由来及解决的问题JWT的工作原理JWT组成重点&#xff1a;JWT实现验证&#xff1a;4.1 首先前后端跨域配置&#xff1a;4.2 jwt配置&#xff1a;4.3 web.xml配置&#xff1a;4.4 登录成功时生成jwt令牌前端NodeJs服务器配置拦截器&#xff0c;配置在http目录下4…

如何使用JSON Web令牌(JWT)保护您的文档

如何使用JSON Web令牌&#xff08;JWT&#xff09;保护您的文档 在本文中&#xff0c;我们讲解如何使用JSON网络令牌JWT来保护在线文档免受未经授权的访问&#xff0c;从而可以更安全的把在线文档编辑器开发集成进您自己的网络应用中去。 这里将集成开源的办公套件ONLYOFFICE …

day13 SpringBoot案例3 令牌技术、登录校验

登录校验的实现思路是怎样的&#xff1f; 项目中访问核心资源&#xff0c;通常都要进行登录校验&#xff0c;访问京东商城的订单&#xff0c;必须要先登录才能访问查询 实现思路: 可以在访问资源前进行访问的拦截&#xff0c;判断你当前会话是否有登录&#xff0c;如果没有登…

pythonjson数据解析失败_json解析失败是什么意思

因为代码的不美观等因素&#xff0c;我们会使用一些解析工具进行处理&#xff0c;有些人在解析时出现了报错。解析失败需要考虑多方面的因素&#xff0c;如格式、String类型、boolean类型等原因&#xff0c;在格式上分为格式错误和格式正确两种讨论。下面就json解析失败的原因为…

Java Web Token令牌校验

前言&#xff1a;本文只涉及JWT的理论部分&#xff0c;不涉及代码 传统的用户校验可以结合cookiesession来实现&#xff0c;但是校验信息存放在服务端&#xff0c;当用户过多时会给服务器造成太大的压力&#xff0c;所以我们可以使用token进行校验&#xff0c;将用户信息加以签…

JWT令牌生成与校验

目录 1 JWT介绍1.1 什么是JWT&#xff1f;1.2 JWT令牌结构 2 配置JWT令牌服务3 生成JWT令牌4 校验JWT令牌5 JWT整合Spring Security5.1 创建表 6 配置授权服务6.1 测试 1 JWT介绍 通过上边的测试我们发现&#xff0c;当资源服务和授权服务不在一起时资源服务使用RemoteTokenSe…

信息系统基础知识(笔记)

一、信息 1.1、信息的基本概念 信息就是信息&#xff0c;既不是物质们也不是论量&#xff0c;信息是能够用来消除不确定的东西 两个概念层次&#xff1a;本体论&#xff08;客观层&#xff0c;与课客体本身因素相关&#xff0c;与主题因素无关&#xff09; 认知论&#xff0…

计算机毕业论文内容参考|基于大数据的信息物理融合系统的分析与设计方法

文章目录 导文摘要前言绪论课题背景国内外现状与趋势:课题内容:相关技术与方法介绍:系统架构设计:数据采集与处理:数据存储与管理:数据分析与挖掘:系统优化与调试:应用场景:挑战与机遇:研究方向:系统分析:系统设计:系统实现:系统测试:总结与展望:

工业4.0中的人-信息-物理系统集成(HSI):设计与评估方法

于栖洋 译 摘要:本文概述了工业4.0中集成人和信息物理系统的设计和使用空间&#xff0c;特别关注分析、设计和评估方法和阶段的相互作用。本文首先介绍了工业4.0面临的挑战&#xff0c;综述了现有的系统设计方法&#xff0c;描述了方法模型的设计和使用空间&#xff0c;并以工…

信息系统基本知识(六)

大纲 信息系统与信息化信息系统开发方法常规信息系统集成技术软件工程新一代信息技术信息系统安全技术信息化发展与应用信息系统服务管理信息系统服务规划企业首席信息管及其责任 1.7 信息化发展与应用 我国在“十三五”规划纲要中&#xff0c;将培育人工智能、移动智能终端…

Unity物理系统(一)物理系统相关组件

一、物理系统相关组件 Unity中的物理系统涉及的组件分为如下几类&#xff1a; 刚体角色控制器碰撞体布料关节力场 二、刚体&#xff08;Rigidbody&#xff09; Rigidbody&#xff08;刚体&#xff09;组件可以使游戏对象在物理系统的控制下进行运动&#xff0c;Rigidbody …