文章目录

  • 1.解析 json
    • 1.1 map[string]interface{} 存储 json
    • 1.2 struct 存储 json
    • 1.3 []map[string]interface{} 解析 json 数组
  • 2.生成 JSON
    • 2.1 struct 序列化为 json
    • 2.2 map[string]interface{} 序列化为 json
    • 2.3 一个较为复杂的例子
      • 2.3.1 使用 struct + slice
      • 2.3.2 使用 map[string]interface{} + []interface{}
  • 参考文献

JSON(Javascript Object Notation)是一种轻量级的数据交换语言,以文字为基础,具有自我描述性且易于阅读。尽管 JSON 是 JavaScript 的一个子集,但 JSON 是独立于语言的文本格式,并且采用了类似于 C 语言家族的一些习惯。JSON 与 XML 最大的不同在于 XML 是一个完整的标记语言,而 JSON 不是。JSON由于比 XML 更小、更快,更易解析,以及浏览器的內建支持,使得其更适用于网络数据传输领域。

Golang 自带的 JSON 解析库 encoding/json,可以用来将结构化数据序列化成 json 字符串或从 json 字符串中解析出我们想要的数据。

1.解析 json

1.1 map[string]interface{} 存储 json

给一个较为复杂的 json 字符串,包含数组,数组的元素是 json 对象。我们需要取出数组第一个元素中的某一个字段值。其它的解析均可参考下面的代码。

package mainimport ("encoding/json""fmt"
)func main() {jsonStr := []byte(`{"uin":1589276509,"feedID":10000,"videos":[{"picture":"http://qqpublic.qpic.cn/avatar.jpg","duration":"839"}]}`)var jsonMap map[string]interface{}if err := json.Unmarshal(jsonStr, &jsonMap); err!=nil {fmt.Printf("json decode failed, err=%v", err)return}if  value, ok := jsonMap["videos"]; ok {fmt.Printf("value=%#v\n", value)if sliceValue, ok := value.([]interface{}); ok {if mapValue, ok := sliceValue[0].(map[string]interface{}); ok {if duration, ok := mapValue["duration"]; ok {fmt.Printf("d=%v,type=%T\n", duration, duration)}}}}
}

程序输出:

value=[]interface {}{map[string]interface {}{"picture":"http://qqpublic.qpic.cn/avatar.jpg", "duration":"839"}}
d=839,type=string

解析 json 字符串时,需要注意如下几点:
(1)Golang 类型和 JSON 类型的对应关系如下:

map[string]interface{} 代表 JSON 对象
[]interface{} 代表 JSON 数组
bool 代表 JSON boolean
float64 代表 JSON number
string 代表 JSON string
nil 代表 JSON null

1.2 struct 存储 json

如果我们事先知道 JSON 串,那么可以指定具体的 struct 来存储解析后的 json。可以通过在线工具Golang: Convert JSON to Struct快速将 JOSN 转为 Go struct。

package mainimport ("fmt""encoding/json"
)type FeedsItem struct {Title             string   `json:"string_title"`Score             int      `json:"uint32_score"`AiKongbuLevel     int      `json:"uint32_ai_kongbu_level"`AiDisuLevel       int      `json:"uint32_ai_disu_level"`AiBiaotidangLevel int      `json:"uint32_ai_biaotidang_level"`AiUnsocialLevel   int      `json:"uint32_ai_unsocial_level"`
}func main() {data:=`[{"uint32_feed_pos": 1,"string_title": "它才是“天然补血王”,女性隔三差五吃,美容驻颜,气色更红润","uint32_score": 4,"uint32_ai_kongbu_level": 0,"uint32_ai_disu_level": 0,"uint32_ai_biaotidang_level": 1,"uint32_ai_unsocial_level": 0}, {"uint32_feed_pos": 2,"string_title": "7岁的火星男孩,顺利通过测谎仪,现在为何消失不见了?","uint32_score": 4,"uint32_ai_kongbu_level": 0,"uint32_ai_disu_level": 0,"uint32_ai_biaotidang_level": 0,"uint32_ai_unsocial_level": 0}]`var feedsInfo []FeedsItem//第二个参数必须是指针,否则无法接收解析后的数据if err := json.Unmarshal([]byte(data), &feedsInfo); err != nil {fmt.Printf("json.Unmarshal() failed, err=%v data=%s\n", err, data)return}fmt.Printf("jsonMap=%#v\n", feedsInfo)
}

编译运行输出:

jsonMap=[]main.FeedsItem{main.FeedsItem{Title:"它才是“天然补血王”,女性隔三差五吃,美容驻颜,气色更红润", Score:4, AiKongbuLevel:0, AiDisuLevel:0, AiBiaotidangLevel:1, AiUnsocialLevel:0}, main.FeedsItem{Title:"7岁的火星男孩,顺利通过测谎仪,现在为何消失不见了?", Score:4, AiKongbuLevel:0, AiDisuLevel:0, AiBiaotidangLevel:0, AiUnsocialLevel:0}}

1.3 []map[string]interface{} 解析 json 数组

如果 json 字符串是一个 json 数组,除了可以使用 struct 来解析,也可以使用 []map[string]interface{} 来解析。

package mainimport ("fmt""encoding/json"
)func main() {s := `[{"id":300001,"exp_layer":"string","buckets":"1,2,3"},{"id":300002,"exp_layer":"test2","buckets":"4"}]`var jsonArray []map[string]interface{}if err := json.Unmarshal([]byte(s), &jsonArray); err!=nil {fmt.Printf("json decode failed, err=%v value=%v\n", err, s)return}   fmt.Printf("jsonArray=%+v\n", jsonArray)
}

输出结果:

jsonArray=[map[exp_layer:string buckets:1,2,3 id:300001] map[id:300002 exp_layer:test2 buckets:4]]

2.生成 JSON

解析 json 时,可以使用 map[string]interface{} 或者 struct 来存储解析后的数据。同样地,我们可以将任意 Golang 对象序列化为 JSON。

Golang 中,JSON 对象表示主要有两种方式,一种是 struct,另一种是 map[string]interface{}。在表示数组时,分别使用具体类型的切片和任意类型的切片 []interface{}。

2.1 struct 序列化为 json

假设我们有如下一个结构体 Student 及其一个实例对象 st,将其序列化为 json,具体实现如下:

package mainimport ("encoding/json""fmt"
)type Student struct {Name      string `json:"name"`Age         intgender       stringClass         *Class `json:"class"`
}type Class struct {Name  stringGrade int
}func main() {//实例化一个数据结构,用于生成 json 字符串st := Student{Name: "张三",Age:  18,gender:  "男",}//指针变量cla := new(Class)cla.Name = "1班"cla.Grade = 3st.Class=cla//Marshal失败时 err != niljsonStu, err := json.Marshal(st)if err != nil {fmt.Println("生成json字符串错误")}//jsonStu是[]byte类型,转化成string类型便于查看fmt.Println(string(jsonStu))
}

程序输出结果:

{"name":"张三","Age":18,"class":{"Name":"1班","Grade":3}}

阅读以上代码可以看出:
(1)只要是可导出成员(变量首字母大写),都可以转成 json。因成员变量 gender 是不可导出的,故无法转成 json;
(2)如果变量打上了 json 标签,如 Name 旁边的 json:"name" ,那么转化成的 json key 就用该标签 “name”,否则取字段名作为 key,如 “Age”;
(3)指针变量,编码时自动转换为它所指向的值,如 Class 变量;
(4)强调一句,序列化成功后的 json 字符串是纯粹的字符串。

2.2 map[string]interface{} 序列化为 json

package mainimport ("encoding/json""fmt"
)func main() {m := make(map[string]interface{})m["Name"]="张三"m["Age"]=18m["Gender"]="男"jsonObject := make(map[string]interface{})jsonObject["Name"]="1班"jsonObject["Grade"]=3m["Class"]=jsonObject//将 map[string]interface{} 转换为 jsonsJson, _ := json.Marshal(m)fmt.Printf("sJson=%v\n", string(sJson))
}

编译运行输出:

sJson={"Age":18,"Class":{"Grade":3,"Name":"1班"},"Gender":"男","Name":"张三"}

2.3 一个较为复杂的例子

假如需要生成如下一个较为复杂的 json:

{"requests": [{"positions": [{"ads": [{"bid_result": "1","ecpm": "1.1","view_id": "Y940raTWuc2bAbPtq1lEc"}, {"bid_result": "2","ecpm": "2.2","view_id": "L37Qw!KwBORErDPbViQ"}]}]}]
}

其中,requests 为一个数组,数组的元素是一个 json 对象,该对象只有一个成员 positions;positions 也是一个数组,数组的元素也是一个 json 对象,该对象也只有一个成员 ads;ads 同样还是数组,数组元素还是一个 json 对象。

2.3.1 使用 struct + slice

因为在 Golang 中,一个 json 对象可以使用 struct 表示,json 中的数组可以使用 slice 来表示,于是我们可以使用 struct 和 slice 来表示上面的 json。

package mainimport ("encoding/json""fmt"
)type Request struct{Requests []RequestValue    `json:"requests"`
}type RequestValue struct {Positions []PositionValue `json:"positions"`
}type PositionValue struct {Ads []AdsValue `json:"ads"`
}type AdsValue struct {Bid_result string       `json:"bid_result"`    Ecpm string             `json:"ecpm"`View_id string          `json:"view_id"`
}func main() {positionValue := PositionValue{Ads: []AdsValue{AdsValue{Bid_result:"1",Ecpm:"1.1",View_id:"Y940raTWuc2bAbPtq1lEc",},AdsValue{Bid_result:"2",Ecpm:"1.2",View_id:"L37Qw!KwBORErDPbViQ",},},}requestValue := RequestValue{Positions: []PositionValue{positionValue},}request := Request{Requests: []RequestValue{requestValue}}//将 struct 转换为 jsonsJson, _ := json.Marshal(request)fmt.Printf("sJson=%v\n", string(sJson))
}

编译运行输出:

sJson={"requests":[{"positions":[{"ads":[{"bid_result":"1","ecpm":"1.1","view_id":"Y940raTWuc2bAbPtq1lEc"},{"bid_result":"2","ecpm":"1.2","view_id":"L37Qw!KwBORErDPbViQ"}]}]}]}

2.3.2 使用 map[string]interface{} + []interface{}

同样地,可以使用 map[string]interface{} 来表示任意的 json,如果元素是数组,可以使用 []interface{}。

package mainimport ("encoding/json""fmt"
)func main() {//json 对象    adValue := make(map[string]interface{})adValue["bid_result"]="1"adValue["ecpm"]="1.1"adValue["view_id"]="Y940raTWuc2bAbPtq1lEc"adValue1 := make(map[string]interface{})adValue1["bid_result"]="2"adValue1["ecpm"]="1.2"adValue1["view_id"]="L37Qw!KwBORErDPbViQ"//json 对象,只有一个成员 ads,且 ads 是一个 json 对象数组ads := make(map[string]interface{})ads["ads"]=[]interface{}{adValue, adValue1}//json 对象,只有一个成员 positions,且 positions 是一个 json 对象数组positions := make(map[string]interface{})positions["positions"]=[]interface{}{ads}//json 对象,只有一个成员 requests,且 requests 是一个 json 对象数组requests := make(map[string]interface{})requests["requests"] = []interface{}{positions}//将 map[string]interface{} 转换为 jsonsJson, _ := json.Marshal(requests)fmt.Printf("sJson=%v\n", string(sJson))
}

编译运行输出:

sJson={"requests":[{"positions":[{"ads":[{"bid_result":"1","ecpm":"1.1","view_id":"Y940raTWuc2bAbPtq1lEc"},{"bid_result":"2","ecpm":"1.2","view_id":"L37Qw!KwBORErDPbViQ"}]}]}]}

输出结果与使用 struct 相同。相比于 struct,使用 map[string]interface{} 更加的简洁,因为省去了 struct 的定义。


参考文献

[1] Golang中文官网.Package json
[2] Go的json解析:Marshal与Unmarshal
[3] stackoverflow.panic: json: cannot unmarshal array into Go value of type main.Structure
[4] Introducing JSON

Golang json 解析与生成相关推荐

  1. json解析对应的value为null_解决golang json解析出现值为空的问题

    我是通过beego框架,将请求过来的json进行解析,并将值保存在结构体中 --------------------1--------------------- request := UpdateCo ...

  2. Swift - 使用原生库进行 JSON 解析和生成

    快速入门 JSON(JavaScript Object Notation)是应用在 JavaScript 语言上的数据格式,常用于网络数据交换和存储.Apple 在Foundation模块中集成了 J ...

  3. iOS json解析 和生成json串

    1.生成json字符串 NSData * jsonData = [NSJSONSerialization dataWithJSONObject:detailDic options:0 error:ni ...

  4. Golang json解析踩坑

    背景 众所周知,PHP是弱类型,Go是强类型,所以Go的json解析注定曲折. 有一段json如下: {"name":"Gopher","age&qu ...

  5. golang json解析

    前言 Go 语言自带的 encode/json 包提供了对 JSON 数据格式的编码和解码能力. 解析 JSON 的关键,其实在于如何声明存放解析后数据的变量的类型. 此外使用 json 编码还会有几 ...

  6. Go实战--golang中使用号称全世界最快的JSON解析器json-iterator(json-iterator/go)

    生命不止,继续go go go!!! 号外号外,差不一条广告,我的博客六月到十一月UV的地域分布: golang中的使用json一点也不陌生,golang为我们提供了官方的encoding/json: ...

  7. golang xml和json的解析与生成

    golang中解析xml时我们通常会创建与之对应的结构体,一层层嵌套,完成复杂的xml解析. package main;import ("encoding/xml""fm ...

  8. 细说Golang的JSON解析

    之前一直写一些动态语言,觉得解析JOSN还是很简单的,往往只需要几行代码就能拿到解析好的JSON对象.Go语言自带的json包可以让你在程序中方便的读取和写入 JSON 数据.生成JSON场景相对简单 ...

  9. Golang Json文件解析为结构体工具-json2go

    代码地址如下: http://www.demodashi.com/demo/14946.html 概述 json2go是一个基于Golang开发的轻量json文件解析.转换命令行工具,目前支持转换输出 ...

最新文章

  1. 9.2 图像类型(灰度图像、彩色图像、二值图像以及图像间的转换)
  2. GUN Make指南
  3. centos7花里胡哨之终端美化
  4. [shell进阶]——shell多线程
  5. rdb和aof优势劣势
  6. android 按钮点击声音,如何在Android中单击按钮时播放声音?
  7. Scikit-Learn库概述
  8. 文件管理类函数(1)
  9. Smart3D系列教程
  10. Zcurd与Eova对比,欢迎吐槽!
  11. ZedGraph _WINFORM中设置ZEDGRAPH的曲线符号SYMBOL以及对应关系
  12. 外贸常用术语_13个常用的国际贸易术语详解
  13. 专访王豫翔:编程道路上的“三少三多”
  14. [****ViewController scrollViewDidScroll:]: message sent to deallocated instance 0x12d6c22f0
  15. 还在用电脑多控手机?你out了,手机多控手机,全新神器
  16. win10电池图标不能调亮度_win10屏幕亮度无法调节?一招解决Win10电脑亮度调节失灵...
  17. Houdini学习笔记——【案例二】消散文字制作
  18. Vue3 项目遇到的问题
  19. matlab fpga 移植,使用MATLAB,Simulink以及基于模型的设计实现把电机控制算法移植到Zynq平台...
  20. 中国机械对流烘箱行业市场供需与战略研究报告

热门文章

  1. GitLab Elasticsearch 私密群组数据泄露 bug 值3000美元
  2. 【干货】无人机如何进行倾斜摄影的航线规划
  3. OPENCV用户手册之图像处理部分(之四):滤波器与色彩转换(中文翻译)
  4. 配置 Linux 的访问控制列表(ACL)
  5. php初学遇到的问题。
  6. JavaEE Tutorials (25) - 使用Java EE拦截器
  7. iOS截取视频预览图,截图方向错误的解决
  8. MongoDB集群——副本集
  9. 验证码识别服务提供商
  10. [转]JavaSE学习 Swing(二)