json 解析:marshal 和 unmarshal
Posted lubanseven
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了json 解析:marshal 和 unmarshal相关的知识,希望对你有一定的参考价值。
Go 使用 encoding/json 包的 marshal 和 unmarshal 实现 json 数据的编解码。分别记录如下:
1. marshal
定义结构体:
type OCP struct
Name string `json:"name"`
ImageRegistry *ImageRegistry `json:"imageRegistry"`
Status string `json:"status"`
Events []string `json:"events"`
id *int
type ImageRegistry struct
Addr string `json:"addr"`
User string `json:"user"`
Password string `json:"password"`
将结构体 OCP 类型值编码成 json 格式:
func main()
imageRegistry := ImageRegistry
Addr: "x.x.x.x",
User: "admin",
Password: "admin",
ocp := OCP
Name: "lubanseven",
ImageRegistry: &imageRegistry,
Status: "running",
Events: []string"normal", "normal", "normal",
data, err := json.Marshal(ocp)
if err != nil
fmt.Println(err)
fmt.Println(string(data))
输出:
"name":"lubanseven","imageRegistry":"addr":"x.x.x.x","user":"admin","password":"admin","status":"running","events":["normal","normal","normal"]
从输出可以看出:
- 结构体中以小写字母开头的类型(id)不会被编码。
- 结构体中指针类型在编码时将转换为指针所指向的值。
更多编码规则可看 JSON and Go
2. unmarshal
类似的将 data 解码为结构体类型 OCP 的值:
var lubanseven OCP
err = json.Unmarshal(data, &lubanseven)
if err != nil
fmt.Println(err)
fmt.Println(lubanseven)
输出:
lubanseven 0xc00020e360 running [normal normal normal] <nil>
从输出可以看出:
- 指针类型的值在解码时将转换为值的地址。
- 对于无法解码的值,将转换为该值的零值,如指针类型变量 id 解码为 nil。
更多编码规则可看 JSON and Go
对于第二点,将 id 类型定义成 int,查看解码后的结构体值:
type OCP struct
Name string `json:"name"`
ImageRegistry *ImageRegistry `json:"imageRegistry"`
Status string `json:"status"`
Events []string `json:"events"`
id int
输出:
lubanseven 0xc0000cc4b0 running [normal normal normal] 0
这点在解码的时候要注意。
上例中解码的结构体类型是已知的,如果结构体未知该如何确定结构体类型呢?这在实际场景中是会发生的,比如传输的数据流,事先不知道其结构体类型。
可以通过类型断言的方式,确定结构体类型,如下:
var lubanunknown interface
err = json.Unmarshal(data, &lubanunknown)
if err != nil
fmt.Println(err)
fmt.Println(lubanunknown)
if value, ok := lubanunknown.(map[string]interface); ok
fmt.Println(value)
输出:
map[events:[normal normal normal] imageRegistry:map[addr:x.x.x.x password:admin user:admin] name:lubanseven status:running]
map[events:[normal normal normal] imageRegistry:map[addr:x.x.x.x password:admin user:admin] name:lubanseven status:running]
输出类型是 map[string]interface,key 是 string,value 是 interface,可以对 value 进行类型断言确定 interface 的实质类型(直接看输出也能看出来...):
value := lubanunknown.(map[string]interface)
for k, v := range value
switch vv := v.(type)
case int:
fmt.Println(k, "is int: ", vv)
case string:
fmt.Println(k, "is string: ", vv)
case []interface:
fmt.Println(k, "is slice: ", vv)
for _, v := range vv
fmt.Println(v)
case map[string]interface:
fmt.Println(k, "is struct: ", vv)
default:
fmt.Println(k, "unexpect type of ", reflect.TypeOf(vv))
输出:
imageRegistry is struct: map[addr:x.x.x.x password:admin user:admin]
status is string: running
events is slice: [normal normal normal]
normal
normal
normal
name is string: lubanseven
3. 数据流的 json 编解码
对数据流的编解码,如下:
package main
import (
"encoding/json"
"log"
"os"
)
func main()
dec := json.NewDecoder(os.Stdin)
enc := json.NewEncoder(os.Stdout)
for
var v map[string]interface
if err := dec.Decode(&v); err != nil
log.Println(err)
return
for k := range v
if k != "Name"
delete(v, k)
if err := enc.Encode(&v); err != nil
log.Println(err)
示例来自 JSON and Go
运行示例:
$ go run main.go
"name":"lubanseven","imageRegistry":"addr":"x.x.x.x","user":"admin","password":"admin","status":"running","events":["normal","normal","normal"]
"Name":"lubanseven","imageRegistry":"addr":"x.x.x.x","user":"admin","password":"admin","status":"running","events":["normal","normal","normal"]
"Name":"lubanseven"
以上是关于json 解析:marshal 和 unmarshal的主要内容,如果未能解决你的问题,请参考以下文章
详解golang的json解析方法Marshal跟 Unmarshal(复杂的对象直接用神器生成对象)
markdown Golang json processing.md中的marshal和unmarshal问题
golang Marshal和Unmarshal处理json数据