go标准库的学习-encoding/json
参考https://studygolang.com/pkgdoc
导入方式:
- import "encoding/json"
json包实现了json对象的编解码,参见RFC 4627。Json对象和go类型的映射关系请参见Marshal和Unmarshal函数的文档。
参见"JSON and Go"获取本包的一个介绍:http://golang.org/doc/articles/json_and_go.html
func Unmarshal
- func Unmarshal(data []byte, v interface{}) error
Unmarshal函数解析json编码的数据并将结果存入v指向的值。
Unmarshal和Marshal做相反的操作,必要时申请映射、切片或指针,有如下的附加规则:
要将json数据解码写入一个指针,Unmarshal函数首先处理json数据是json字面值null的情况。此时,函数将指针设为nil;否则,函数将json数据解码写入指针指向的值;如果指针本身是nil,函数会先申请一个值并使指针指向它。
要将json数据解码写入一个结构体,函数会匹配输入对象的键和Marshal使用的键(结构体字段名或者它的标签指定的键名),优先选择精确的匹配,但也接受大小写不敏感的匹配。
要将json数据解码写入一个接口类型值,函数会将数据解码为如下类型写入接口:
- Bool 对应JSON布尔类型
- float64 对应JSON数字类型
- string 对应JSON字符串类型
- []interface{} 对应JSON数组
- map[string]interface{} 对应JSON对象
- nil 对应JSON的null
如果一个JSON值不匹配给出的目标类型,或者如果一个json数字写入目标类型时溢出,Unmarshal函数会跳过该字段并尽量完成其余的解码操作。如果没有出现更加严重的错误,本函数会返回一个描述第一个此类错误的详细信息的UnmarshalTypeError。
JSON的null值解码为go的接口、指针、切片时会将它们设为nil,因为null在json里一般表示“不存在”。 解码json的null值到其他go类型时,不会造成任何改变,也不会产生错误。
当解码字符串时,不合法的utf-8或utf-16代理(字符)对不视为错误,而是将非法字符替换为unicode字符U+FFFD。
举例:通过interface{} 与 type assert的配合,这样就能够解析未知结构的JSON数了
- package main
- import(
- "fmt"
- "encoding/json"
- )
- func main() {
- var s interface{}
- str := `
- {
- "name" : "testJSON",
- "servers" : [
- {
- "serverName" : "Shanghai_VPN",
- "serverIP" : "127.0.0.1"
- },
- {
- "serverName" : "Beijing_VPN",
- "serverIP" : "127.0.0.2"
- }
- ],
- "status" : false
- }`
- json.Unmarshal([]byte(str), &s)
- fmt.Println(s)
- //然后需要通过断言来将其从interface{}类型转成map[string]interface{}类型
- m := s.(map[string]interface{})
- for key, value := range m {
- switch v := value.(type){//得到s的类型
- case string :
- fmt.Println(key , " is string ", v)
- case int :
- fmt.Println(key, "is int", v)
- case []interface{}:
- fmt.Println(key, "is an array")
- for i, vv := range v{
- fmt.Println(i, vv)
- }
- default:
- fmt.Println(key, "is of a type i don't know how to handle")
- }
- }
- }
返回:
- userdeMBP:go-learning user$ go run test.go
- map[name:testJSON servers:[map[serverName:Shanghai_VPN serverIP:127.0.0.1] map[serverName:Beijing_VPN serverIP:127.0.0.2]] status:false]
- name is string testJSON
- servers is an array
- 0 map[serverName:Shanghai_VPN serverIP:127.0.0.1]
- 1 map[serverIP:127.0.0.2 serverName:Beijing_VPN]
- status is of a type i don't know how to handle
func Marshal
- func Marshal(v interface{}) ([]byte, error)
Marshal函数返回v的json编码。
Marshal函数会递归的处理值。如果一个值实现了Marshaler接口切非nil指针,会调用其MarshalJSON方法来生成json编码。nil指针异常并不是严格必需的,但会模拟与UnmarshalJSON的行为类似的必需的异常。
否则,Marshal函数使用下面的基于类型的默认编码格式:
布尔类型编码为json布尔类型。
浮点数、整数和Number类型的值编码为json数字类型。
字符串编码为json字符串。角括号"<"和">"会转义为"\u003c"和"\u003e"以避免某些浏览器吧json输出错误理解为HTML。基于同样的原因,"&"转义为"\u0026"。
数组和切片类型的值编码为json数组,但[]byte编码为base64编码字符串,nil切片编码为null。
结构体的值编码为json对象。每一个导出字段变成该对象的一个成员,除非:
- - 字段的标签是"-"
- - 字段是空值,而其标签指定了omitempty选项
空值是false、0、""、nil指针、nil接口、长度为0的数组、切片、映射。对象默认键字符串是结构体的字段名,但可以在结构体字段的标签里指定。结构体标签值里的"json"键为键名,后跟可选的逗号和选项,举例如下:
- // 字段被本包忽略
- Field int `json:"-"`
- // 字段在json里的键为"myName"
- Field int `json:"myName"`
- // 字段在json里的键为"myName"且如果字段为空值将在对象中省略掉
- Field int `json:"myName,omitempty"`
- // 字段在json里的键为"Field"(默认值),但如果字段为空值会跳过;注意前导的逗号
- Field int `json:",omitempty"`
"string"选项标记一个字段在编码json时应编码为字符串。它只适用于字符串、浮点数、整数类型的字段。这个额外水平的编码选项有时候会用于和javascript程序交互:
- Int64String int64 `json:",string"`
如果键名是只含有unicode字符、数字、美元符号、百分号、连字符、下划线和斜杠的非空字符串,将使用它代替字段名。
匿名的结构体字段一般序列化为他们内部的导出字段就好像位于外层结构体中一样。如果一个匿名结构体字段的标签给其提供了键名,则会使用键名代替字段名,而不视为匿名。
Go结构体字段的可视性规则用于供json决定那个字段应该序列化或反序列化时是经过修正了的。如果同一层次有多个(匿名)字段且该层次是最小嵌套的(嵌套层次则使用默认go规则),会应用如下额外规则:
1)json标签为"-"的匿名字段强行忽略,不作考虑;
2)json标签提供了键名的匿名字段,视为非匿名字段;
3)其余字段中如果只有一个匿名字段,则使用该字段;
4)其余字段中如果有多个匿名字段,但压平后不会出现冲突,所有匿名字段压平;
5)其余字段中如果有多个匿名字段,但压平后出现冲突,全部忽略,不产生错误。
对匿名结构体字段的管理是从go1.1开始的,在之前的版本,匿名字段会直接忽略掉。
映射类型的值编码为json对象。映射的键必须是字符串,对象的键直接使用映射的键。
指针类型的值编码为其指向的值(的json编码)。nil指针编码为null。
接口类型的值编码为接口内保持的具体类型的值(的json编码)。nil接口编码为null。
通道、复数、函数类型的值不能编码进json。尝试编码它们会导致Marshal函数返回UnsupportedTypeError。
Json不能表示循环的数据结构,将一个循环的结构提供给Marshal函数会导致无休止的循环。
func MarshalIndent
- func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
MarshalIndent类似Marshal但会使用缩进将输出格式化。其可读性更高
- package main
- import(
- "fmt"
- "encoding/json"
- "os"
- )
- type Address struct {
- City, State string
- }
- type Person struct {
- Id int `json:"id"` //id作为该JSON字段的key值
- FirstName string //不设置标签则默认使用FirstName为字段key值
- LastName string `json:"-"` //字段被本包忽略,即使有值也不输出
- Age int `json:",omitempty"` //含omitempty选项的字段如果为空值会省略,如果存在Age作为该JSON字段的key值
- Height float32 `json:"height,omitempty"` //含omitempty选项的字段如果为空值会省略,如果存在height作为该JSON字段的key值
- Address //匿名字段(其标签无效)会被处理为其字段是外层结构体的字段,所以没有Address这个元素,而是直接显示City, State这两个元素
- }
- func main() {
- v := &Person{Id: , FirstName: "John", LastName: "Doe", Age: }
- v.Address = Address{"Hanga Roa", "Easter Island"}
- output, err := json.MarshalIndent(v, "&", " ")//每行以&作为前缀,并缩进四个空格
- if err != nil {
- fmt.Printf("error: %v\n", err)
- }
- os.Stdout.Write(output)
- }
返回:
- userdeMBP:go-learning user$ go run test.go
- {
- & "id": ,
- & "FirstName": "John",
- & "Age": ,
- & "City": "Hanga Roa",
- & "State": "Easter Island"
- &}
如果使用的是Marshal,则返回:
- userdeMBP:go-learning user$ go run test.go
- {"id":,"FirstName":"John","Age":,"City":"Hanga Roa","State":"Easter Island"}
未完待续
go标准库的学习-encoding/json的更多相关文章
- go标准库的学习-encoding/base64
参考:https://studygolang.com/pkgdoc 导入方式: import "encoding/base64" base64实现了RFC 4648规定的base6 ...
- go标准库的学习-encoding/xml
参考:https://studygolang.com/pkgdoc 导入方式: import "encoding/xml" 实现的简单的理解XML命名空间的XML 1.0编译器 f ...
- go标准库的学习-net/http
参考:https://studygolang.com/pkgdoc 概念解释: request:用户请求的信息,用来解析用户的请求信息,包括post.get.cookie.url等信息 respons ...
- go标准库的学习-database/sql
参考:https://studygolang.com/pkgdoc 导入方式: import "database/sql" sql包提供了保证SQL或类SQL数据库的泛用接口. 使 ...
- go标准库的学习-crypto/md5
参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/md5" md5包实现了MD5哈希算法,参见RFC 1321. Con ...
- go标准库的学习-crypto/sha1
参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/sha1" sha1包实现了SHA1哈希算法,参见RFC 3174. ...
- go标准库的学习-crypto/sha256
参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/sha256" sha256包实现了SHA224和SHA256哈希算法 ...
- python 标准库基础学习之开发工具部分1学习
#2个标准库模块放一起学习,这样减少占用地方和空间#标准库之compileall字节编译源文件import compileall,re,sys#作用是查找到python文件,并把它们编译成字节码表示, ...
- python calendar标准库基础学习
# -*- coding: utf-8 -*-# 作者:新手__author__ = 'Administrator'#标准库:日期时间基础学习:calendar:处理日期#例1import calen ...
随机推荐
- MVC中子页面如何引用模板页中的jquery脚本
MVC中子页面如何引用模板页中的jquery脚本 最近在学习mvc,遇到了一个问题:在html页面中写js代码,都是引用mvc5自带的jquery脚本,虽然一拖(将指定的jquery脚本如 jquer ...
- sql特殊语法
MYSQL --判断非空select ifnull(null,'666');--666select ifnull(null,null);--null--合并字段select CONCAT('666', ...
- 同源策略与CORS
同源策略 同源策略是浏览器保护用户安全上网的重要措施,协议.域名.端口号三者相同即为同源. 不同源下,浏览器不允许js操作Cookie.LocalStorage.DOM等数据或页面元素,也不允许发送a ...
- X问题(中国剩余定理+不互质版应用)hdu1573
X问题 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- javascript如何操作数组
说明 如需求:后台返回一个用户列表数组,该数组可能为空,最多只可能会有10个用户, 页面中A,B两处展示用户列表,B处不管如何都会展示返回的所有用户,A处需要展示10个用户,不足10个展示默认用户, ...
- Harbor 搭建
环境:centos7.4 docker-ce 18.06.0-ce docker-compose version 1.18.0 harbor 版本: 1.5.2 harbor 安装参考 https:/ ...
- Installing Fonts programatically C#
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- 从零开始学习html(八)CSS选择器——下
六.子选择器 <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" ...
- ionic3 细节注意
一.图标和splash大小不一样 icon图标的大小尽量为1024*1024,并且不能为圆角. splash图片的大小尽量为2732*2732,ionic1的大小为2208*2208
- [Spark] Spark 安装配置
原文地址:https://www.cnblogs.com/memento/p/9148732.html Windows 上的单机版安装 下载地址:http://spark.apache.org/dow ...