golang-Json编码解码
- 作者: 拿作业借我抄抄
- 来源: 51数据库
- 2021-08-28
目录
- 七. bson编码
在线工具:
一. 类型映射
- golang和json的数据类型不一致,在编码或解码的过程中必然需要做类型映射。
1.从golang到json:
| golang | json |
|---|---|
| bool | boolean |
| int、float等数字 | number |
| string | string |
| []byte(base64编码) | string |
| struct | object,再递归打包 |
| array/slice | array |
| map | object |
| interface{} | 按实际类型转换 |
| nil | null |
| channel,func | unsupportedtypeerror |
2.从json到golang:
| json | golang |
|---|---|
| boolean | bool |
| number | float64 |
| string | string |
| array | []interface{} |
| object | map[string]interface{} |
| null | nil |
二. 输出控制
- 第一个标签为别名,后面控制标签可叠加。
- 编码或解码的
中间数据状态为字节数组。
type user struct {
name string `json:"user_name"` //修改别名
age uint8 `json:",string"` //修改类型
addr string `json:"-"` //忽略字段
vip bool `json:",omitempty"` //排除缺省值
asset int64 `json:"amount,string,omitempty"` //标签叠加
skill []string `json:"skill"` //复杂类型
}
func main() {
obj :=user{name:"tom",age:18,addr:"bj",vip:false,asset:888,skill:[]string{"golang","python"}}
bts, _ := json.marshalindent(obj,"","\t") //缩进
fmt.println(string(bts))
}
三. 类型编码
1.结构体/结构体指针: 映射为object
func main() {
obj := struct {a string;b int64}{"a", 1}
bts, _ := json.marshal(obj) //结构体
fmt.println(string(bts))
ptr := &obj //结构体指针
bts, _ = json.marshal(ptr)
fmt.println(string(bts))
}
2.数组/切片: 映射为array
func main() {
arr := []string{"a","b","c"}
bts, _ := json.marshal(arr)
fmt.println(string(bts))
}
3.字典: 映射为object
func main() {
mp := map[int]string{1:"a",2:"b",3:"c"}
bts, _ := json.marshal(mp)
fmt.println(string(bts))
}
四. 类型解码
1.对象解码
func main() {
str := `{"a":"a","b":1}`
obj := new(struct {a string;b int64})
_ = json.unmarshal([]byte(str), &obj )
fmt.println(obj)
}
2.数组解码
func main() {
arr := `["a","b","c"]`
slise:=make([]string,0)
_ = json.unmarshal([]byte(arr),&slise)
fmt.println(slise)
}
3.字典解码
func main() {
str := `{"1":"a","2":"b","3":"c"}`
mp := make(map[int]string)
_ = json.unmarshal([]byte(str), &mp)
fmt.println(mp)
}
五. 输出重写
marshal函数将会递归遍历整个对象,并根据类型数据的marshaljson方法打印输出格式。
//自定义的json时间格式
type jtime time.time
//实现了encoding/json/encode.go的marshaler接口
func (p jtime) marshaljson() ([]byte, error) {
var stamp = fmt.sprintf("%d", time.time(p).unix())
//var stamp = fmt.sprintf("\"%s\"", time.time(p).format("2006-01-02 15:04:05"))
return []byte(stamp), nil
}
func main() {
obj := struct {
name string `json:"nick_name"`
date jtime `json:"create_at"`
}{"jack", jtime(time.date(2018, 1, 1, 00, 00, 00, 00, time.local))}
//编码
bts, _ := json.marshalindent(obj, "", "\t")
fmt.println(string(bts))
//解码
_ = json.unmarshal(bts, obj)
fmt.printf("%s %q", obj.name, time.time(obj.date))
}
六. 扩展功能
1. json格式验证:json.valid()
func main() {
str := `{"nick_name":"lucy","user_age":28}` //object
str = `["a","b"]` //array
ok := json.valid([]byte(str))
fmt.println(ok)
}
2. 自定义编码器:json.newencoder()
func main() {
obj := struct {
name string `json:"nick_name"`
age uint `json:"user_age"`
}{"lucy", 28}
outer, _ := os.create("json.txt") //文件输出
outer = os.stdout //标准输出
encoder := json.newencoder(outer)
encoder.setindent("", "\t")
encoder.encode(obj)
}
3. 缩进处理:json.indent(),对已编码对字节数组进行缩进
func main() {
obj := struct {name string;age uint}{"lucy", 28}
bts, _ := json.marshal(obj)
var buf bytes.buffer
_=json.indent(&buf,bts,"","\t")
buf.writeto(os.stdout)
}
4. json字符串压缩:json.compact()
func main() {
str := `
{
"nick_name": "lucy",
"user_age": 28
}`
var buf bytes.buffer
_ = json.compact(&buf, []byte(str)) //压缩
buf.writeto(os.stdout)
}
5. html编码处理:json.htmlescape()
func main() {
str := `{"content": "<a src=\"http://www.xxx.com\">link</a>"}`
var buf bytes.buffer
json.htmlescape(&buf, []byte(str))
buf.writeto(os.stdout)
}
6. 二次解码:json.rawmessage,根据json数据包的某个标识,分别解码成不同类型的对象。
type student struct {
sno string //学号
name string //姓名
major string //专业
}
type teacher struct {
name string //姓名
subject string //学科
}
// 任何对象都能装的数据容器,具体类型根据type字段区分
type jsonobject struct {
type int //对象类型
obj interface{} //对象数据
}
func main() {
user := `{"type":1,"obj":{"sno":"s001","name":"tom","major":"computer"}}` //student
user = `{"type":2,"obj":{"name":"bob","subject":"quantum mechanics"}}` //teacher
var obj json.rawmessage
pkg := jsonobject{obj: &obj}
//第一次解码: 先解码外部包装数据对象,获取类型依据
if err := json.unmarshal([]byte(user), &pkg); err != nil {
panic(err)
}
//第二次解码: 根据第一次的解码结果,再次对内部对象obj进行解码
switch pkg.type {
case 1:
var stu = student{}
_ = json.unmarshal(obj, &stu)
fmt.println(stu)
case 2:
var tch = teacher{}
_ = json.unmarshal(obj, &tch)
fmt.println(tch)
}
}
七. bson编码
- bson基于json格式,是mongodb的数据存储格式。
- 1.速度快:json以字符串形式存储,需要文件扫描,结构匹配。bson是按结构存储,可以精准定位,高效读写。
- 2.操作简单:json无数据类型,是基于字符的操作,面临很大的操作开销。bson可以指定数据类型。
- 3.字节数组:二进制的存储不再需要先base64转换后再存成json,大大减少了计算开销和数据大小。
import "gopkg.in/mgo.v2/bson"
type person struct {
name string `bson:"nick_name"`
age int32 `bson:"-"`
phone string `bson:",omitempty"`
}
func main() {
p := &person{"bob", 18, ""}
bytes, _ := bson.marshal(p) //bson编码
fmt.printf("%q\n", bytes)
um := &person{}
bson.unmarshal(bytes, &um) //strust解码
fmt.println(um)
mp := bson.m{}
bson.unmarshal(bytes, mp) //map解码
fmt.println(mp)
}
参考:
推荐阅读
