美文网首页
数据格式操作(json等)

数据格式操作(json等)

作者: 强某某 | 来源:发表于2020-08-04 16:33 被阅读0次

    json

    以下分别是切片json互转和map,json互转两种,后者比较麻烦,取值的时候需要进行接口类型断言

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type Class struct {
        //结构体转json,成员必须首字母大写,否则转换之后该字段会被忽略
        Subject  string
        Students []string
        Price    float64
        
        //注意:如果结构体字段是大写(一般都是大写)但是提交字段是小写,则需要特殊处理:如下
        // Age int `json:"age"`
    }
    
    func main01() {
        cl := Class{"go语言", []string{"呵呵", "哈哈"}, 10}
        // slice, err := json.Marshal(cl)
        // if err != nil {
        //  fmt.Println(err)
        //  return
        // }
        //不转换的话是字符切片,肉眼不可分辨实际内容
        // fmt.Println(string(slice)) //{"Subject":"go语言","Students":["呵呵","哈哈"],"Price":10}
    
        //格式化输出,一般没啥用处
        slice, err := json.MarshalIndent(cl, "", "    ")
        if err != nil {
            return
        }
        fmt.Println(string(slice))
    }
    
    func main02() {
        slice := []byte(`{"Subject":"go语言","Students":["呵呵","哈哈"],"Price":10}`)
    
        var cl Class
        //本质上传递的是指针,所以也可以new(Class)返回值传递也可
        err := json.Unmarshal(slice, &cl)
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Println(cl)       //{go语言 [呵呵 哈哈] 10}
        fmt.Println(cl.Price) //10  可以这样分开打印
    }
    
    func main03() {
        // 创建⼀个保存键值对的映射
        t1 := make(map[string]interface{})
        t1["company"] = "Lianshi"
        t1["subjects "] = []string{"Go", "Web", "Python", "C++"}
        t1["isok"] = true
        t1["price"] = 8980.88
        b, err := json.Marshal(t1)
        //json.MarshalIndent(t1, "", " ")
        if err != nil {
            fmt.Println("json err:", err)
        }
        fmt.Println(string(b)) //{"company":"Lianshi","isok":true,"price":8980.88,"subjects ":["Go","Web","Python","C++"]}
    }
    
    func main() {
        b := []byte(`{
            "company": "Lianshi",
            "subjects": [
             "Go",
             "Web",
             "Python",
             "C++"
            ],
            "isok": true,
            "price": 8980.88
            }`)
        //默认返回值类型为interface类型 以map类型进⾏格式存储
        //可以理解为:json的key为map的key json的value为map的value
        //格式:map[string]interface{}
        // var t interface{}
        // err := json.Unmarshal(b, &t)
        // if err != nil {
        //  fmt.Println("json err:", err)
        // }
        // fmt.Println(t)
    
        //使⽤断⾔判断类型
        // m := t.(map[string]interface{})
    
        //或者上面用下面几行替换
        m := make(map[string]interface{})
        err := json.Unmarshal(b, &m)
        if err != nil {
            fmt.Println("json err:", err)
        }
    
        for k, v := range m {
            switch val := v.(type) {
            case string:
                fmt.Println(k, "is string", val)
            case int:
                fmt.Println(k, "is int", val)
            case float64:
                fmt.Println(k, "is float64", val)
            case bool:
                fmt.Println(k, "is bool", val)
            case []interface{}:
                fmt.Println(k, "is an array:")
                for i, u := range val {
                    fmt.Println(i, u)
                }
            default:
                fmt.Println(k, "is of a type I don't know how to handle")
            }
        }
    }
    

    xml

    <?xml version="1.0" encoding="utf-8"?>
    <servers version="1">
        <server>
            <serverName>Shanghai_VPN</serverName>
            <serverIP>127.0.0.1</serverIP>
        </server>
        <server>
            <serverName>Beijing_VPN</serverName>
            <serverIP>127.0.0.2</serverIP>
        </server>
    </servers>
    
    package main
    
    import (
        "encoding/xml"
        "fmt"
        "io/ioutil"
    )
    
    type Servers struct {
        Name    xml.Name `xml:"servers"`
        Version string   `xml:"version,attr"`
        Servers []Server `xml:"server"`
    }
    
    type Server struct {
        ServerName string `xml:"serverName"`
        ServerIP   string `xml:"serverIP"`
    }
    
    func main() {
        data, err := ioutil.ReadFile("./config.xml")
        if err != nil {
            fmt.Printf("read config.xml failed, err:%v\n", err)
            return
        }
        var servers Servers
        err = xml.Unmarshal(data, &servers)
        if err != nil {
            fmt.Printf("unmarshal failed, err:%v\n", err)
            return
        }
        fmt.Printf("xml: %#v\n", servers)
    }
    

    msgpack数据格式

    二进制形式的json协议

    1. 性能更快
    2. 更省空间
    3. 安装 go get github.com/vmihailenco/msgpack
    4. 官网:https://msgpack.org/
    5. 有通用js库可以解析,顾可以再前端后台node使用
    package main
    
    import (
        "fmt"
        "io/ioutil"
        "math/rand"
    
        "github.com/vmihailenco/msgpack"
    )
    
    type Person struct {
        Name string
        Age  int
        Sex  string
    }
    
    func writeJson(filename string) (err error) {
        var persons []*Person
        for i := 0; i < 10; i++ {
            p := &Person{
                Name: fmt.Sprintf("name%d", i),
                Age:  rand.Intn(100),
                Sex:  "Man",
            }
    
            persons = append(persons, p)
        }
    
        data, err := msgpack.Marshal(persons)
        if err != nil {
            fmt.Printf("=marshal failed, err:%v\n", err)
            return
        }
    
        err = ioutil.WriteFile(filename, data, 0755)
        if err != nil {
            fmt.Printf("write file failed, err:%v\n", err)
            return
        }
    
        return
    }
    
    func readJson(filename string) (err error) {
        var persons []*Person
        data, err := ioutil.ReadFile(filename)
        if err != nil {
            return
        }
    
        err = msgpack.Unmarshal(data, &persons)
        if err != nil {
            return
        }
    
        for _, v := range persons {
            fmt.Printf("%#v\n", v)
        }
        return
    }
    
    func main() {
        filename := "C:/tmp/person.dat"
        err := writeJson(filename)
        if err != nil {
            fmt.Printf("write json failed, err:%v\n", err)
            return
        }
    
        err = readJson(filename)
        if err != nil {
            fmt.Printf("read json failed, err:%v\n", err)
            return
        }
    }
    

    Protobuf

    • google推出的数据交换格式
    • 二进制
    • 基于代码自动生成

    开发流程

    • IDL编写
    • 生成指定语言的代码
    • 序列化和反序列化

    IDL编写

    1.jpg
    • 枚举类型
    enum EnumAllowingAlias { 
    UNKNOWN = 0; 
    STARTED = 1; 
    RUNNING = 2; 
    }
    
    • 结构体类型
    message Person {
    //后面的数字表示标识号,就是序号,是给proto内部使用的
    int32 id = 1;
    string name = 2;
    //repeated表示可重复
    //可以有多个手机
    repeated Phone phones = 3;
    }
    

    Golang应用

    2.jpg
    • 安装golang代码插件, go get -u github.com/golang/protobuf/protoc-gen-go
    • 生成代码, protoc --go_out=. *.proto
      • protoc --go_out=./address .\person.proto
      • 通过当前目录下的person.proto文件生成go代码到address目录(必须存在)下,默认生成文件名是person.pb.go
      • 注意:如果protoc --go_out没有配置环境变量需要配置下
    //指定版本
    //注意proto3与proto2的写法有些不同
    syntax = "proto3";
     
    //包名,通过protoc生成时go文件时
    package address;
     
    //手机类型
    //枚举类型第一个字段必须为0
    enum PhoneType {
        HOME = 0;
        WORK = 1;
    }
     
    //手机
    message Phone {
        PhoneType type = 1;
        string number = 2;
    }
     
    //人
    message Person {
        //后面的数字表示标识号
        int32 id = 1;
        string name = 2;
        //repeated表示可重复
        //可以有多个手机
        repeated Phone phones = 3;
    }
     
    //联系簿
    message ContactBook {
        repeated Person persons = 1;
    }
    
    package main
    
    import (
        "fmt"
        "io/ioutil"
    
        "github.com/golang/protobuf/proto"
        //此处引入的就是生成的proto对应go文件
        "github.com/pingguoxueyuan/gostudy/listen24/protobuf/address"
    )
    
    func writeProto(filename string) (err error) {
        var contactBook address.ContactBook
        for i := 0; i < 64; i++ {
            p := &address.Person{
                Id:   int32(i),
                //Sprintf返回字符串
                Name: fmt.Sprintf("陈%d", i),
            }
    
            phone := &address.Phone{
                Type:   address.PhoneType_HOME,
                Number: "15910624165",
            }
    
            p.Phones = append(p.Phones, phone)
            contactBook.Persons = append(contactBook.Persons, p)
        }
    
        data, err := proto.Marshal(&contactBook)
        if err != nil {
            fmt.Printf("marshal proto buf failed, err:%v\n", err)
            return
        }
    
        err = ioutil.WriteFile(filename, data, 0755)
        if err != nil {
            fmt.Printf("write file failed, err:%v\n", err)
            return
        }
        return
    }
    
    func readProto(filename string) (err error) {
        var contactBook address.ContactBook
        data, err := ioutil.ReadFile(filename)
        if err != nil {
            return
        }
        err = proto.Unmarshal(data, &contactBook)
        if err != nil {
            return
        }
    
        fmt.Printf("proto:%#v\n", contactBook)
        return
    }
    
    func main() {
        filename := "c:/tmp/contactbook.dat"
        err := writeProto(filename)
        if err != nil {
            fmt.Printf("write proto failed, err:%v\n", err)
            return
        }
        err = readProto(filename)
        if err != nil {
            fmt.Printf("read proto failed, err:%v\n", err)
            return
        }
    }
    

    相关文章

      网友评论

          本文标题:数据格式操作(json等)

          本文链接:https://www.haomeiwen.com/subject/dtmwrktx.html