zoukankan      html  css  js  c++  java
  • golang的json序列化

    json就是简单的数据交换格式,语法类似javascript的对象和列表,是最常见的后端和运行在网页上的js之间的通信格式。

    encoding:

    编码json数据需要使用到Marshal()函数。

    func Marshal(v interface{}) ([]byte, error)
    type Message struct {
        Name string
        Body string
        Time int64
    }
    m := Message{"Alice", "Hello", 1294706395881547000}
    b, err := json.Marshal(m)
    b == []byte(`{"Name":"Alice","Body":"Hello","Time":1294706395881547000}`)

    上面的代码就是讲一个Message对象编码成json的格式。json格式的显示是[]byte类型的。

    decoding:

    解码json格式的数据使用到的是Unmarshal()函数。

    func Unmarshal(data []byte, v interface{}) error
    var m Message
    err := json.Unmarshal(b, &m)

    Unmarshal()接受的是[]byte类型的json数据,和这个数据要返回的结构体的指针。

    在Unmarshal()函数中。只能识别在m这个结构体中所拥有的属性字段。不存在的将会被忽略。

    通用的json接口:interface{}

    任意的go类型都实现了空接口interface{}

    var i interface{}
    i = "a string"
    i = 2011
    i = 2.777

    可以使用断言来判断它的实现类型

    r := i.(float64)
    fmt.Println("the circle's area", math.Pi*r*r)

    如果不知道实现的类型,可以使用swtich case来片判断

    switch v := i.(type) {
    case int:
        fmt.Println("twice i is", v*2)
    case float64:
        fmt.Println("the reciprocal of i is", 1/v)
    case string:
        h := len(v) / 2
        fmt.Println("i swapped by halves is", v[h:]+v[:h])
    default:
        // i isn't one of the types above
    }

    json包使用map[string]interface{}和[]interface{}来存储任意的json对象和数组。go的类型和json的类型对应如下:

    • bool for JSON booleans,
    • float64 for JSON numbers,
    • string for JSON strings,
    • nil for JSON null.

    解码任意数据data

    假设b中存储的书json数据

    b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)

    当不知道这个数据的结构体的时候,可以使用Unmarshal()来将它解码成一个interface{}的值。

    var f interface{}
    err := json.Unmarshal(b, &f)

    f现在的数据结构就是一个map[string]interface{}

    f = map[string]interface{}{
        "Name": "Wednesday",
        "Age":  6,
        "Parents": []interface{}{
            "Gomez",
            "Morticia",
        },
    }

    可以使用断言f的底层接口来访问这些数据

    m := f.(map[string]interface{})

    然后遍历这个map,利用switch case来断言底层的类型

    for k, v := range m {
        switch vv := v.(type) {
        case string:
            fmt.Println(k, "is string", vv)
        case int:
            fmt.Println(k, "is int", vv)
        case []interface{}:
            fmt.Println(k, "is an array:")
            for i, u := range vv {
                fmt.Println(i, u)
            }
        default:
            fmt.Println(k, "is of a type I don't know how to handle")
        }
    }

    Reference Types:

    type FamilyMember struct {
        Name    string
        Age     int
        Parents []string
    }
    
        var m FamilyMember
        err := json.Unmarshal(b, &m)

    将b中的[]byte数据编码到FamilyMember结构体中去,首先给FamilyMember 分配内存,然后传入一个指针到Unmarshal中去。但是属性Parents是一个nil空值,unmarshal给这个slice分配一个新的块。

    Let's define a Go type to contain the data from the previous example:

    type FamilyMember struct {
        Name    string
        Age     int
        Parents []string
    }
    
        var m FamilyMember
        err := json.Unmarshal(b, &m)

    Unmarshaling that data into a FamilyMember value works as expected, but if we look closely we can see a remarkable thing has happened. With the var statement we allocated a FamilyMember struct, and then provided a pointer to that value toUnmarshal, but at that time the Parents field was a nil slice value. To populate the Parents field, Unmarshal allocated a new slice behind the scenes. This is typical of how Unmarshal works with the supported reference types (pointers, slices, and maps).

    Consider unmarshaling into this data structure:

    type Foo struct {
        Bar *Bar
    }

    If there were a Bar field in the JSON object, Unmarshal would allocate a new Bar and populate it. If not, Bar would be left as a nil pointer.

    From this a useful pattern arises: if you have an application that receives a few distinct message types, you might define "receiver" structure like

    type IncomingMessage struct {
        Cmd *Command
        Msg *Message
    }

    and the sending party can populate the Cmd field and/or the Msg field of the top-level JSON object, depending on the type of message they want to communicate. Unmarshal, when decoding the JSON into an IncomingMessage struct, will only allocate the data structures present in the JSON data. To know which messages to process, the programmer need simply test that either Cmd or Msg is not nil.

    Streaming Encoders and Decoders

    The json package provides Decoder and Encoder types to support the common operation of reading and writing streams of JSON data. The NewDecoder and NewEncoder functions wrap the io.Reader and io.Writer interface types.

    func NewDecoder(r io.Reader) *Decoder
    func NewEncoder(w io.Writer) *Encoder

    Here's an example program that reads a series of JSON objects from standard input, removes all but the Name field from each object, and then writes the objects to standard output:

    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)
            }
        }
    }

    Due to the ubiquity of Readers and Writers, these Encoder and Decoder types can be used in a broad range of scenarios, such as reading and writing to HTTP connections, WebSockets, or files.

  • 相关阅读:
    无法识别的属性“targetFramework”。请注意属性名称区分大写和小写。错误解决的方法
    OpenGL 4 : 一个漂亮的心 For you, My Love
    request.getParameterValues与request.getParameter的差别
    Mac下搭建quick cocos2d-x编译环境
    【Github教程】史上最全github用法:github入门到精通
    OSI七层模型具体解释
    Android Service 服务(一)—— Service
    几种更新(Update语句)查询的方法
    epoll使用具体解释(精髓)
    SSL连接建立过程分析(1)
  • 原文地址:https://www.cnblogs.com/guhao123/p/4070852.html
Copyright © 2011-2022 走看看