博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Json and Go
阅读量:7065 次
发布时间:2019-06-28

本文共 4554 字,大约阅读时间需要 15 分钟。

Reference

Encoding

Encode的基本用法是

package mainimport (    "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 storedvar output Message// Please note that passing the pointer to outputdecodeErr := 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 UnmatchMessagemessage1 := //` `代表原生字符串面值,没有转义操作,全是字符串的字面值[]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 mainimport (    "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 mainimport (    "encoding/json"    "fmt"    "os")type Bar inttype 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了memory1234

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

type IncomingMessage struct {     Cmd *Command    Msg *Message}

Streaming Encoders and Decoders

package mainimport (    "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)        }    }}

转载地址:http://pfill.baihongyu.com/

你可能感兴趣的文章
JavaScript之闭包
查看>>
互联网一线大厂都在用的Java架构师知识体系
查看>>
python之函数
查看>>
Android开发者之——做一个能服务自己的东西,好不好看都不重要
查看>>
终端代码重复率检测实践
查看>>
计算机程序的思维逻辑 (55) - 容器类总结
查看>>
远程入侵原装乘用车(上)
查看>>
「前端」尚妆 UI 组件库工程实践(weex vue)
查看>>
Vue.js 2.0实战精华梳理
查看>>
技术的成长曲线
查看>>
DOM常用操作
查看>>
【译】Cloudera Manager(CDH)入门系列之四 (管理员控制台)
查看>>
编程常用动词细微差别
查看>>
如何通过Dataworks禁止MaxCompute 子账号跨Project访问
查看>>
聊聊reactive streams的backpressure
查看>>
android studio 2 3 的maven坑
查看>>
来分享一个我自己写的HTML模板引擎,Leopard
查看>>
基于阿里云数加构建企业级数据分析平台
查看>>
React Native安卓模拟器调出Dev Setting菜单
查看>>
Laravel整合Bootstrap 4的完整方案
查看>>