分类: Web开发
2013-02-03 22:55:52
JSON(javascript object Notation)是轻量级的数据交换格式 它和Javascript中的对象和数组语法上类似 JSON目前广泛用于前后台数据交互 json.org提供了更多的介绍 有兴趣的可以移步至JSON的官网
With the it's a snap to read and write JSON data from your Go programs.
Go自带的json包可以轻松地帮你在Go程序中搞定JSON
Encoding
To encode JSON data we use the function.
使用Marshal函数来将数据编码成JSON数据
func Marshal(v interface{}) ([]byte, error)
Given the Go data structure, Message,
下面这个例子展示了一个Go的数据结构Message,
type Message struct { Name string Body string Time int64 }
and an instance of Message
以及Message的一个实例
m := Message{"Alice", "Hello", 1294706395881547000}
we can marshal a JSON-encoded version of m using json.Marshal:
可以使用json.Marshal来编码成JSON,
b, err := json.Marshal(m)
If all is well, err will be nil and b will be a []byte containing this JSON data:
一切顺利的话,err是nil,b是[]byte类型的JSON数据
b == []byte(`{"Name":"Alice","Body":"Hello","Time":1294706395881547000}`)
Only data structures that can be represented as valid JSON will be encoded:
只有可以被编码成JSON的数据结构才可以被编码成相应的JSON:
The json package only accesses the exported fields of struct types (those that begin with an uppercase letter). Therefore only the exported fields of a struct will be present in the JSON output.
json包只能将结构体中 可以被外部直接访问的字段编码 也就是那些以大写开头的字段
Decoding
To decode JSON data we use the function.
可以使用Unmarshal来decode JSON数据
func Unmarshal(data []byte, v interface{}) error
We must first create a place where the decoded data will be stored
首先创建一个变量 decode后的JSON数据将被存到这个变量中去
var m Message
and call json.Unmarshal, passing it a []byte of JSON data and a pointer to m
接着调用json.Unmarshal []byte的JSON数据 和指向m的指针作为参数传递给它
err := json.Unmarshal(b, &m)
If b contains valid JSON that fits in m, after the call err will be nil and the data from b will have been stored in the struct m, as if by an assignment like:
如果b是符合m定义的,合法的JSON err就是nil b中的JSON数据就被存到了m
m = Message{ Name: "Alice", Body: "Hello", Time: 1294706395881547000, }
How does Unmarshal identify the fields in which to store the decoded data? For a given JSON key "Foo", Unmarshal will look through the destination struct's fields to find (in order of preference):
Unmarshal是如何正确地把JSON数据存到结构体中对于的字段的呢? 给定一个JSON的键Foo Unmarshal会遍历结构的域:
What happens when the structure of the JSON data doesn't exactly match the Go type?
如果JSON的结构不符合Go的类型 会出现什么样的状况呢?
b := []byte(`{"Name":"Bob","Food":"Pickle"}`) var m Message err := json.Unmarshal(b, &m)
Unmarshal will decode only the fields that it can find in the destination type. In this case, only the Name field of m will be populated, and the Food field will be ignored. This behavior is particularly useful when you wish to pick only a few specific fields out of a large JSON blob. It also means that any unexported fields in the destination struct will be unaffected by Unmarshal.
Unmarshal只会把它可以识别出来的那些字段给解码 存放到m 想上面代码中Food字段就会被忽略 当我们只需要几个特定的字段时 这个行为非常游泳 当然了那些不能被外部访问的字段肯定是彻底被无视了
But what if you don't know the structure of your JSON data beforehand?
很多时候 事先我们并不知道JSON的结构是怎么样的
Generic JSON with interface{}
The interface{} (empty interface) type describes an interface with zero methods. Every Go type implements at least zero methods and therefore satisfies the empty interface.
空接口类型interface{} 定义了一个没有任何方法的接口 任何一个Go类型都实现了至少0个方法(废话)所以说它满足空接口的要求
The empty interface serves as a general container type:
空接口可以被当做是通用的类型容器:
var i interface{} i = "a string" i = 2011 i = 2.777
A type assertion accesses the underlying concrete type:
类型断言可以访问到底层具体的类型:
r := i.(float64) fmt.Println("the circle's area", math.Pi*r*r)
Or, if the underlying type is unknown, a type switch determines the type:
或者 如果底层的类型未知 会通过leixing switch类去顶它的类型:
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 }
The json package uses map[string]interface{} and []interface{} values to store arbitrary JSON objects and arrays; it will happily unmarshal any valid JSON blob into a plain interface{} value. The default concrete Go types are:
json包使用map[string]interface{}和[]interface{}来存任意的JSON对象或者数组 它会傻不愣登地解开所有合法的JSON 存到interface{}
Decoding arbitrary data
Consider this JSON data, stored in the variable b:
考虑这个JSON数据
b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
Without knowing this data's structure, we can decode it into an interface{} value with Unmarshal:
在不知道它的具体结构的情况下 我们decode到一个interface{}值
var f interface{} err := json.Unmarshal(b, &f)
At this point the Go value in f would be a map whose keys are strings and whose values are themselves stored as empty interface values:
调用Unmarshal decode后 被保存在f 结构如下:
f = map[string]interface{}{ "Name": "Wednesday", "Age": 6, "Parents": []interface{}{ "Gomez", "Morticia", }, }
To access this data we can use a type assertion to access f's underlying map[string]interface{}:
要访问这个数据 我们可以使用类型断言:
m := f.(map[string]interface{})
We can then iterate through the map with a range statement and use a type switch to access its values as their concrete types:
之后 可以使用range来遍历它 使用类型断言来访问底层的数据:
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") } }
In this way you can work with unknown JSON data while still enjoying the benefits of type safety.
啊 春暖花开啊 你可以用这招来搞定各种未知的JSON妞
Reference Types
Let's define a Go type to contain the data from the previous example:
重新定义前面例子中的Go类型
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 to Unmarshal, but at that time the Parents field was a nil slice value. To populate the Parentsfield, Unmarshal allocated a new slice behind the scenes. This is typical of how Unmarshal works with the supported reference types (pointers, slices, and maps).
调用Unmarshal 它会和之前一样乖乖地decode JSON数据 并且结果存到m 但是 仔细观察 我们会发现奇迹发生了啊 var m FamilyMember定义了一个FamliyMember结构体实例 同时Parents这个与的值是slice nil 体冲这个Parents字段 Unmarshal默默地创建了一个slice
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.
如果JSON对象包括Bar字段 Unmarshal会分配一个新的Bar 并且给它初始化 如果没有 Bar就是指针nil
From this a useful pattern arises: if you have an application that receives a few distinct message types, you might define "receiver" structure like
如果你的应用接受很多不同类型的值 你可以定义receiver结构体:
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.
数据的船体放 可以给Cmd 或者Msg字段赋值 Unmarshal在decode JSON到IncomingMessage结构体时 只会分配那些在JSON中存在的字段
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.
json包提供了Decoder和Encode类型 支持常见的读写JSON数据流的操作
The NewDecoder and NewEncoderfunctions wrap the and interface types.
NewDecoder和NewEncoder函数对io.Reader和io.Writer做了包装:
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:
下面这个示例 从标准输入读一系列的JSON对象 剔除除了Name外的所有字段 并写到标准输出
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.