Golang json

作者: 大漠狼道 | 来源:发表于2015-09-01 18:07 被阅读2112次

    Json实例

    简介

    人懒,直接从网上扒了篇文档 《Go by Example: JSON》并稍加修改。
    golang有内置json相关处理的包"encoding/json",支持内置类型和用户自定类型。这篇文章主要介绍简单的使用。

    接口:

    编码:
    func Marshal(v interface{}) ([]byte, error)
    func NewEncoder(w io.Writer) *Encoder
    [func (enc *Encoder) Encode(v interface{}) error

    解码:
    func Unmarshal(data []byte, v interface{}) error
    func NewDecoder(r io.Reader) *Decoder
    func (dec *Decoder) Decode(v interface{}) error

    正文

    内置简单类型没有什么好说的,直接上coding:

    bolB, _ := json.Marshal(true)  
    fmt.Println(string(bolB))
    
    intB, _ := json.Marshal(1)  
    fmt.Println(string(intB))
    
    fltB, _ := json.Marshal(2.34) 
    fmt.Println(string(fltB))
    
    strB, _ := json.Marshal("gopher") 
    fmt.Println(string(strB))
    
    slcD := []string{"apple", "peach", "pear"} slcB, _ := json.Marshal(slcD) 
    fmt.Println(string(slcB))
    
    mapD := map[string]int{"apple": 5, "lettuce": 7} mapB, _ := json.Marshal(mapD) 
    fmt.Println(string(mapB))
    

    结果:

    true
    1
    2.34
    "gopher"
    ["apple","peach","pear"]
    {"apple":5,"lettuce":7}
    

    自定义类型:
    默认情况下,转义所有公开的成员(大写字母开头的),私有成员(小写字母开头的)不转义:

    type Name struct {
        First, Last string
    }
    
    n := Name{First: "Ta", Last: "SY"}
    
    if r, e := json.Marshal(n); e == nil {
        fmt.Println("name is ", string(r))
    } else {
        fmt.Println("err ", e)
    }
    
    结果:
    name is  {"First":"Ta","Last":"SY"}
    

    可以通过tag来自定义json关键字;也可以直接转义到其他流中去例如标准输入输出、文件、网络:

    这个是带tag自定义json关键字,注意”user“是小写的
    type TagName struct {
        Name string `json:"nm"`
        Book string `json:"b"`
        user string
    }
    
    enc := json.NewEncoder(os.Stdout)
    
    tags := []TagName{
        {"hello", "Joson", "weter"},
        {"world", "Nano", "jober"},
    }
    if e := enc.Encode(tags); e != nil {
        fmt.Println("e ", e)
    }
    输出结果,注意上面私有成员user是没有被转义的:
    [{"nm":"hello","b":"Joson"},{"nm":"world","b":"Nano"}]
    
    

    下面这个是网络的简单完整示例:

    package main
    
    import (
        "encoding/json" 
        "net/http"
    )
    
    var s store
    
    type bigTask struct {
        ID     int
        Status string
        Data   map[string]string
    }
    
    type store struct {
        task []bigTask
    }
    
    
    var bigTasks []bigTask
    
    func init() {   
    
        bigTasks = []bigTask{
            {0, "wait", map[string]string{"data": "http://localhost/0/data"}},
            {1, "done", map[string]string{"data": "http://localhost/1/data"}},
            {2, "dead", map[string]string{"data": "http://localhost/2/data"}},
        }
    }
    func main() {
        http.HandleFunc("/big_task", bigtask)
    
        http.ListenAndServe(":10004", nil)
    }
    
    func bigtask(w http.ResponseWriter, r *http.Request) {
        enc := json.NewEncoder(w)
        if e := enc.Encode(bigTasks); e != nil {
            http.Error(w, e.Error(), http.StatusInternalServerError)
    
        }
    
    }
    运行后,访问:"http://localhost:10004/big_task",输出为:
    [{"ID":0,"Status":"wait","Data":{"data":"http://localhost/0/data"}},{"ID":1,"Status":"done","Data":{"data":"http://localhost/1/data"}},{"ID":2,"Status":"dead","Data":{"data":"http://localhost/2/data"}}]
    

    有几个需要注意的地方

    • json类型仅支持string作为关键字,因而转义map时,map[int]T类型会报错(T为任意类型)
    • Channel, complex, and function types不能被转义
    • 不支持循环类型的数据,因为这会导致Marshal死循环
    • 指针会被转义为其所指向的值

    解码

    还是比较懒,又扒了篇: 《JSON and Go》by Andrew Gerrand,链接为golang官网中的博客,要翻墙哦

    用Unmarshal函数来解码:

    func Unmarshal(data []byte, v interface{}) error
    

    首先要有个变量来存放解码结果

    var m Message
    

    调用json.Unmarshal,参数为[]byte类型的json数据和指向m的指针

    err := json.Unmarshal(b, &m)
    

    如果成功,err为nil,同时m会被填充,类似如下赋值

    m = Message{
        Name: "Alice",
        Body: "Hello",
        Time: 1294706395881547000,
    }
    

    Unmarshal是如何进行的呢?假定json关键字为"Foo",流程如下:

    • 先找tag为"Foo"的公开成员
    • 再找名字为"Foo"的公开成员
    • 最后再查找"FOO","FoO"等大小写不敏感的公开成员

    如果json数据没有匹配到Go类型会出现什么结果?

    type Message struct {
        Name string
        Body string
        Time int64
    }
    
    b := []byte(`{"Name":"Bob","Food":"Pickle"}`)
    var m Message
    err := json.Unmarshal(b, &m)
    
    

    Unmarshal仅仅解析匹配到的结果。上例中,只有Name会被解析,而"Food"则被忽略掉。当你想从非常大的json数据中解析特定数据时,这个技巧会非常有用

    相关文章

      网友评论

        本文标题:Golang json

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