目录
- 七. 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) }
参考: