• 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"]}
    

    从输出可以看出:

    1. 结构体中以小写字母开头的类型(id)不会被编码。
    2. 结构体中指针类型在编码时将转换为指针所指向的值。

    更多编码规则可看 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>}
    

    从输出可以看出:

    1. 指针类型的值在解码时将转换为值的地址。
    2. 对于无法解码的值,将转换为该值的零值,如指针类型变量 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"}
    

  • 相关阅读:
    Codeforces Round #277 (Div. 2) D. Valid Sets 暴力
    Codeforces Round #277 (Div. 2) B. OR in Matrix 贪心
    Codeforces Round #277 (Div. 2) A. Calculating Function 水题
    套题 Codeforces Round #277 (Div. 2)
    模板 读入挂
    Codeforces Round #276 (Div. 1) B. Maximum Value 筛倍数
    Codeforces Round #276 (Div. 1) A. Bits 二进制 贪心
    json转字符串 —— jsonObj.toJSONString()与JSON.stringify(jsonObj)
    JSONP跨域提交表单
    jquery ajaxSubmit
  • 原文地址:https://www.cnblogs.com/xingzheanan/p/15902792.html
Copyright © 2020-2023  润新知