Json and Go

栏目: Go · 发布时间: 5年前

内容简介:ReferenceEncode的基本用法是输出为:

Reference https://blog.go-zh.org/json-a...

Encoding

Encode的基本用法是

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type Message struct {
    Name string
    Body string
    Time int64
}

func main() {
    message := Message{"Tom", "Hello", 1294706395881547000}
    b, err := json.Marshal(message)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to Marshal!")
        os.Exit(1)
    }

    fmt.Printf("%s", b)
}

输出为:

{"Name":"Tom","Body":"Hello","Time":1294706395881547000}
func Marshal(v interface{}) ([]byte, error)

Only data structures that can be represented as valid JSON will be encoded:

  • JSON objects only support string as keys.
  • Channel , complex, and function types cannot be encoded.
  • Cyclic data structures are not supported.
  • Pointers will be encoded as the values they point to(or null if the pointer is nil)

json package 只能access the exportede fields. 也就是首字母大写的field. 也就是在data structure中的首字母大写的field才会present in JSON output

Decoding

// We must first create a place where the decoded data will be stored
var output Message
// Please note that passing the pointer to output
decodeErr := json.Unmarshal(b, &output)
if decodeErr != nil {
    fmt.Fprintf(os.Stderr, "Failed to Unmarshal json data!err:%s", err)
    os.Exit(1)
}

fmt.Printf("%+v\n", output)

Unmarshal是怎么确认json field与data structure的对应关系呢?,其实是通过以下来判断的(优先级从高到低).比如对于JSON Field "Foo"来说,

  • An exported field with a tag of "Foo".
  • An exported field named "Foo"
  • An exported field named "FOO" or "FoO" or some other case-insensitive match of "Foo"

总结下来是: Tag -> Foo -> FOO(case-insensitive match)

tag的判定规则如下

// Field appears in JSON as key "myName".
Field int `json:"myName"`

// Field appears in JSON as key "myName" and
// the field is omitted from the object if its value is empty,
// as defined above.
Field int `json:"myName,omitempty"`

// Field appears in JSON as key "Field" (the default), but
// the field is skipped if empty.
// Note the leading comma.
Field int `json:",omitempty"`

// Field is ignored by this package.
Field int `json:"-"`

// Field appears in JSON as key "-".
Field int `json:"-,"`

如果json data 与data structure中只有部分field匹配怎么办?

var unmatchedOutput UnmatchMessage
message1 := 
//` `代表原生字符串面值,没有转义操作,全是字符串的字面值
[]byte{`{"Name":"Tom","Body":"Hello","Time":1294706395881547000}`}
decodeErr1 := json.Unmarshal(b, &unmatchedOutput)
if decodeErr1 != nil {
    fmt.Fprintf(os.Stderr, "Failed to unmarshal json data! err:", err)
    os.Exit(1)
}
fmt.Printf("%+v\n", unmatchedOutput)

输出为

{Name:Tom Boy: Tim:0}

从上看出, Unmarshal只会decode符合上述3条件的field

This behavior is particularly useful when you wish to pick only a few specific fields out of a large JSON blob.

Generic JSON with interface{}

Decoding arbitrary data

以上2章先跳过去

Reference Types

Unmarshal会为Reference Types自动allocated a memory. 注意这里仅仅为在json 中存在的data allocate memory.

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type FamilyMember struct {
    Name    string
    Age     int
    Parents []string
}

func main() {
    family := FamilyMember{"Andy", 26, []string{"Tom", "Lucy"}}
    b, err := json.Marshal(family)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to Marshal family!err:%s", err)
        os.Exit(1)
    }

    fmt.Printf("%s\n", b)

       // 注意,此时Parents slice是nil. 在Unmarshal时,会自动为其allcated memory.
    var output FamilyMember
    decodeErr := json.Unmarshal(b, &output)
    if decodeErr != nil {
        fmt.Fprintf(os.Stderr, "Failed to unmarshal!err:%s", err.Error())
        os.Exit(1)
    }

    fmt.Printf("%+v\n", output)
}

对于指针也是一样的

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type Bar int
type Foo struct {
    Bar *Bar
}

func main() {
    b := []byte(`{"Bar":1234}`)
    var data Foo
    err := json.Unmarshal(b, &data)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to unmarshal!err:%s", err.Error())
        os.Exit(1)
    }
        fmt.Printf("%+v\n", data)
    fmt.Printf("%+v\n", *(data.Bar))
}

输出为:

{Bar:0xc42001a120} // 注意此时的地址不为nil了,因为在Unmarshal已经为其allocated了memory
1234

但是需要注意,Unmarshal只会为json data匹配的field 分配内存,对于没有匹配的,可能还是nil. 所以对于如下的structure,在使用之前还需要认为的判断是否为nil.

type IncomingMessage struct {
     Cmd *Command
    Msg *Message
}

Streaming Encoders and Decoders

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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

超预期

超预期

[美] 莱昂纳多·因基莱里、迈卡·所罗门 / 杨波 / 后浪丨江西人民出版社 / 2017-11 / 45.00元

用户体验决定产品成败,只有超预期才能赢得好口碑! 互联网大佬一致推崇的打造爆款产品及服务的核心理念 ................... ※编辑推荐※ ☆ 超预期,才有用户体验,互联网大佬一致推崇的打造爆款产品及服务的核心理念 - 周鸿祎:“什么叫用户体验?超过用户预期才叫 体验!” - 雷军:“口碑的真谛是超越用户的期望值。” - 马化腾:“用户体验,......一起来看看 《超预期》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换