内容简介: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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。