参考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的更多相关文章

  1. go标准库的学习-encoding/base64

    参考:https://studygolang.com/pkgdoc 导入方式: import "encoding/base64" base64实现了RFC 4648规定的base6 ...

  2. go标准库的学习-encoding/xml

    参考:https://studygolang.com/pkgdoc 导入方式: import "encoding/xml" 实现的简单的理解XML命名空间的XML 1.0编译器 f ...

  3. go标准库的学习-net/http

    参考:https://studygolang.com/pkgdoc 概念解释: request:用户请求的信息,用来解析用户的请求信息,包括post.get.cookie.url等信息 respons ...

  4. go标准库的学习-database/sql

    参考:https://studygolang.com/pkgdoc 导入方式: import "database/sql" sql包提供了保证SQL或类SQL数据库的泛用接口. 使 ...

  5. go标准库的学习-crypto/md5

    参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/md5" md5包实现了MD5哈希算法,参见RFC 1321. Con ...

  6. go标准库的学习-crypto/sha1

    参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/sha1" sha1包实现了SHA1哈希算法,参见RFC 3174. ...

  7. go标准库的学习-crypto/sha256

    参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/sha256" sha256包实现了SHA224和SHA256哈希算法 ...

  8. python 标准库基础学习之开发工具部分1学习

    #2个标准库模块放一起学习,这样减少占用地方和空间#标准库之compileall字节编译源文件import compileall,re,sys#作用是查找到python文件,并把它们编译成字节码表示, ...

  9. python calendar标准库基础学习

    # -*- coding: utf-8 -*-# 作者:新手__author__ = 'Administrator'#标准库:日期时间基础学习:calendar:处理日期#例1import calen ...

随机推荐

  1. git入门(廖雪峰老师)

    根据廖雪峰老师的git教程进行学习总结: 1.之前上班用的都是svn进行管理,那么svn和git有什么区别呢? svn是集中式的版本控制系统,而git是分布式版本控制系统,那么集中式和分布式版本控制系 ...

  2. ASP.NET Identity 二 (转载)

    来源:http://www.cnblogs.com/r01cn/p/5180892.html#undefined 推荐看原文,这里转载是怕好文章消失了. 注:本文是[ASP.NET Identity系 ...

  3. 【操作系统】二、JVM线程与Linux内核线程的映射

    Linux从内核2.6开始使用NPTL (Native POSIX Thread Library)支持,但这时线程本质上还轻量级进程. Java里的线程是由JVM来管理的,它如何对应到操作系统的线程是 ...

  4. java_有秒计时的数字时钟

    题目内容: 这一周的编程题是需要你在课程所给的时钟程序的基础上修改而成.但是我们并不直接给你时钟程序的代码,请根据视频自己输入时钟程序的Display和Clock类的代码,然后来做这个题目. 我们需要 ...

  5. PATH、CLASSPATH、CLASSPATH

    PATH: 说明: 环境变量中的path,意在在向计算机发出指令时的一个指向路径,如 一般会在path里加上:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin 其中:%JAVA_ ...

  6. mysql之数据备份与还原

    mysql数据备份 #1. 物理备份: 直接复制数据库文件,适用于大型数据库环境.但不能恢复到异构系统中如Windows. #2. 逻辑备份: 备份的是建表.建库.插入等操作所执行SQL语句,适用于中 ...

  7. 【代码笔记】Web-HTML-框架

    一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  8. TortoiseSVN 1.9.5安装 与 Eclipse4.4.2及以上版本中安装SVN插件

    引自: http://blog.csdn.net/chenchunlin526/article/details/54631458 TortoiseSVN 1.9.5安装 与 Eclipse4.4.2及 ...

  9. Kafka初入门简单配置与使用

    一 Kafka概述 1.1 Kafka是什么 在流式计算中,Kafka一般用来缓存数据,Storm通过消费Kafka的数据进行计算. 1)Apache Kafka是一个开源消息系统,由Scala写成. ...

  10. CSS字体超出两行省略

    text-overflow: -o-ellipsis-lastline;overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-w ...