Golang的Json encode/decode以及[]byte和string的转换
使用了太长时间的python,对于强类型的Golang适应起来稍微有点费力,不过操作一次之后发现,只有这么严格的类型规定,才能让数据尽量减少在传输和解析过程中的错误。我尝试使用Golang创建了一个公司的OpenAPI的demo,记录一下中间遇到的问题。
编码(Encode)Json:
首先来看下如何将字典编码成Json:
// 首先使用字面量来申明和初始化一个字典
param := map[string]int{"page_no": 1, "page_size": 40}
paramJson, err := json.Marshal(param)
使用json.Marshal接收需要json.encode的变量。而json.Marshal接收的是interface{}接口变量,该接口变量可以接收任何类型的数据。
[]byte转String以及String转[]byte:
通常我在python里面使用json.dumps来对字典进行序列化的时候,我通常认为出来的值是一个string,可以将其作为string进行操作。但是这里很明显返回的不是字符串(string)类型,而是一个[]byte类型。所以如果有需要,我们可以将[]byte类型,转换回string进行操作。这里有几种方法可供选择:
直接使用:
string([]byte) 或使用:
String([]byte[:])
ps:现在这两个得到的结果会是一样的,我现在使用的版本是1.8。1.8以前好像会是不同的表现。
同时我们也会遇到想要将string转换回[]byte的时候。方法如下:
[]byte(string)
Http包的post请求来实践对Json的序列化反序列化:
当我们把json编码好之后我们需要将信息传递给服务器。所以用到了http包。
在使用了之后我觉得go的http包真的非常方便,的确如传言中描述的强大和人性化,方便实用。
resp , err := http.PostForm(requestUrl, url.Values{"api_key": {ApiKey}, "api_sign": {apiSign},
"param": {string(param)}, "time": {now_time}, "version": {version}})
这里我使用http.PostForm方法使用带参数传递的post方法请求服务器。url.Values后面可以跟key[string][]string的形式传递参数。返回一个http.response结构体指针和一个error类型。
http.response具体带有哪些属性可以详细查看一下包,这里我们会去解析他的Body字段,里面存储着返回的内容:
// The Body is automatically dechunked if the server replied
// with a "chunked" Transfer-Encoding.
Body io.ReadCloser
这里Body是一个有io.ReadCloser接口的值。io.ReadCloser接口实现了Read()和Write()方法。
我会用json的Decoder去解析它:
var response openApiResponse
resp := request.RequestHeader(paramJson, version, SyncUrl)
err1 := json.NewDecoder(resp.Body).Decode(&response)
if err1 != nil {
log.Println(err1)
}
return resp
这里json.NewDecoder接收一个有Reader方法的变量,之后我们调用了Decoder的方法decode将里面的内容都存入事先申请好的response结构体变量中。这个变量初始化了我们通过文档了解到的返回的结构体字段类型。
openApiResponse struct {
Success bool `json:"success"`
ResultCode int `json:"result_code"`
ResultMsg string `json:"result_msg"`
// 接收JSON字段
Result GoodsSyncResult `json:"result"`
}
这样一级一级解析下去,在构造接收返回回来数据的结构体的时候,注意到后面的json字段。他是一个tag,可以在解析json的时候将对应名字的tag解析到对应的变量中。
这样就相当于你做好了数据结构,然后将对应的数据放到对应的字段里面去。
当然还有一种办法,当你不知道你所接收数据的数据结构的时候,你是没有办法提前申明好这些数据结构然后来接收的。这时我们可以申明一个空接口interface{},让空接口的指针来接收这组数据,可以查看这组数据的数据结构。
var hahaha interface{}
resp := request.RequestHeader(paramJson, version, SyncUrl)
err1 := json.NewDecoder(resp.Body).Decode(&hahaha)
if err1 != nil {
log.Println(err1)
}
上面的hahaha可以接收并decodejson,来接收这组数据。并且可以直接使用fmt.Print之类函数直接打印接收到的数据。如果想直接使用,我们可以使用类型断言但是更推荐的方法是,我们可以根据这组数据来写对应的结构体,然后将数据接收到结构体上进行操作。就像上面一样。
同样的我们还可以使用一个map[string]interface{}来接收这个Json以方便对其进行后续操作,避免不需要的多余的反射。
var hahaha map[string]interface{}
resp := request.RequestHeader(paramJson, version, SyncUrl)
err1 := json.NewDecoder(resp.Body).Decode(&hahaha)
return hahaha
除了实现一个decoder来处理数据,我们往往有Json序列化之后就立即需要序列化的操作,这个同样很容易使用:
json.Unmarshal([]byte, &xx)
来处理就好了。参数一是需要decode的Json数据, 参数二是用于接收这组数据的结构体字段。同样的我们也可以使用一个空接口来接收数据,也可以使用一一对应的结构体来放置数据。
看了上面的一堆介绍有一个感觉,就处理Json数据和类型转换来说。。python真是简单到爆炸,一个dumps一个loads轻松搞定。但是Golang严格的参数类型缺可以保证解析过来的数据一定是对应的数据结构和数据类型。不会在类型上报错更为严谨。个人觉得这很有趣,也很喜欢。
Reference:
http://stackoverflow.com/questions/3371714/go-string-to-ascii-byte-array go-string-to-ascii-byte-array
http://stackoverflow.com/questions/24377907/golang-issue-with-accessing-nested-json-array-after-unmarshalling golang-issue-with-accessing-nested-json-array-after-unmarshalling
http://blog.csdn.net/tiaotiaoyly/article/details/38942311 在Go语言中使用JSON
Golang的Json encode/decode以及[]byte和string的转换的更多相关文章
- Java - byte[] 和 String互相转换
通过用例学习Java中的byte数组和String互相转换,这种转换可能在很多情况需要,比如IO操作,生成加密hash码等等. 除非觉得必要,否则不要将它们互相转换,他们分别代表了不同的数据,专门服务 ...
- C# Byte[] 转String 无损转换
C# Byte[] 转String 无损转换 转载请注明出处 http://www.cnblogs.com/Huerye/ /// <summary> /// string 转成byte[ ...
- [转]关于网络通信,byte[]和String的转换问题
最近的项目中要使用到把byte[]类型转换成String字符串然后通过网络发送,但发现发现出去的字符串和获取的字符串虽然是一样的,但当用String的getBytes()的方法得到的byte[]跟原来 ...
- JSON和Map,List,String互相转换
1)Map 和 JSON 互相转换 Map 转成 JSON Map<String, List> map = new HashMap<>(); map.put("xAx ...
- C#中byte[]与string的转换
1. System.Text.UnicodeEncoding converter = new System.Text.UnicodeEncoding(); byte[] i ...
- golang []byte和string的高性能转换
golang []byte和string的高性能转换 在fasthttp的最佳实践中有这么一句话: Avoid conversion between []byte and string, since ...
- C#图像处理:Stream 与 byte[] 相互转换,byte[]与string,Stream 与 File 相互转换等
C# Stream 和 byte[] 之间的转换 一. 二进制转换成图片 MemoryStream ms = new MemoryStream(bytes); ms.Position = 0; Ima ...
- golang的json操作
package main import ( "encoding/json" "fmt" "os" ) type ConfigStruct s ...
- node_nibbler:自定义Base32/base64 encode/decode库
https://github.com/mattrobenolt/node_nibbler 可以将本源码复制到自己需要的JS文件中,比如下面这个文件,一个基于BASE64加密请求参数的REST工具: [ ...
随机推荐
- [Python] Python 100例
题目1:有四个数字:1.2.3.4,能组成多少个互不相同且无重复数字的三位数?各是多少? 程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. #程序源 ...
- Can 't connect to local MySQL server through socket '/tmp/mysql.sock '(2) "
安装了mysql, 使用命令mysql -u root -p 弹出Can 't connect to local MySQL server through socket '/tmp/mysql.soc ...
- oracle impdp将导出用户的所有对象导入至另一个用户下,生成的触发器语句问题处理
问题产生的操作步骤及详细说明: 1)操作的数据库是oracle 11g,先通过命令将用户GAS_NEW的数据导出,命令语句如下: expdp GAS_NEW/GAS_NEW@ORCL schemas= ...
- Numpy数组的保存与读取
1. 数组以二进制格式保存 np.save和np.load是读写磁盘数组数据的两个主要函数.默认情况下,数组以未压缩的原始二进制格式保存在扩展名为npy的文件中,以数组a为例 np.save(&quo ...
- Java多线程学习(三)---线程的生命周期
线程生命周期 摘要: 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态.在线程的生命周期中,它要经过新建(New).就绪(Runnable).运行(Running).阻塞 ...
- Java获取Window和Linux系统的项目ClassPath路径
不啰嗦,直接复制工具类 /** * 在windows和linux系统下均可正常使用 * Create by yster@foxmail.com 2018/6/6/006 14:51 */ public ...
- .NET Core Community 第三个千星项目诞生:爬虫 DotnetSpider
本文所有打赏将全数捐赠于 NCC(NCC 的资金目前由 倾竹大人 负责管理),请注明捐赠于 NCC.捐赠情况将由倾竹大人在此处公示. DotnetSpider 至力于打造一个轻量化.高效率.易开发.可 ...
- for 循环 以及基本的数据类型
for 循环: for 关键字 i 变量(此处可以更改 更改规则参考变量命名规则) in 关键字 可迭代对象 (想要循环谁就放谁,注意:数字除外 因为数字不可迭代) for 循环内可以进行任意操作,可 ...
- Python—os模块介绍
OS模块 我们平时工作中很常用到的一个模块,通过os模块调用系统命令,获得路径,获取操作系统的类型等都是使用该模块.os 模块提供了很多允许你的程序与操作系统直接交互的功能 得到当前工作目录,即当前P ...
- Python入门-函数
定义:将一组语句的集合通过一个名字(函数名)封装起来,要先执行这个函数,只需要调用其函数名即可.特性:1.减少重复代码2.使程序变的可扩展3.使程序变的易维护 函数参数:形参和实参形参:位置参数,关键 ...