JSON {.en}

JSON {.zh}

::: {.en} Go offers built-in support for JSON encoding and decoding, including to and from built-in and custom data types. :::

::: {.zh}

Go提供对JSON编码和解码的内置支持,包括内置和自定义数据类型。

:::

  1. package main
  2. import "encoding/json"
  3. import "fmt"
  4. import "os"

::: {.en} We’ll use these two structs to demonstrate encoding and decoding of custom types below. :::

::: {.zh}

我们将使用这两个结构来演示下面的自定义类型的编码和解码。

:::

  1. type response1 struct {
  2. Page int
  3. Fruits []string
  4. }
  5. type response2 struct {
  6. Page int `json:"page"`
  7. Fruits []string `json:"fruits"`
  8. }
  9. func main() {

::: {.en} First we’ll look at encoding basic data types to JSON strings. Here are some examples for atomic values. :::

::: {.zh}

首先,我们将研究将基本数据类型编码为JSON字符串。以下是原子值的一些示例。

:::

  1. bolB, _ := json.Marshal(true)
  2. fmt.Println(string(bolB))
  3. intB, _ := json.Marshal(1)
  4. fmt.Println(string(intB))
  5. fltB, _ := json.Marshal(2.34)
  6. fmt.Println(string(fltB))
  7. strB, _ := json.Marshal("gopher")
  8. fmt.Println(string(strB))

::: {.en} And here are some for slices and maps, which encode to JSON arrays and objects as you’d expect. :::

::: {.zh}

这里有一些切片和贴图,它们按照您的预期编码为JSON数组和对象。

:::

  1. slcD := []string{"apple", "peach", "pear"}
  2. slcB, _ := json.Marshal(slcD)
  3. fmt.Println(string(slcB))
  4. mapD := map[string]int{"apple": 5, "lettuce": 7}
  5. mapB, _ := json.Marshal(mapD)
  6. fmt.Println(string(mapB))

::: {.en} The JSON package can automatically encode your custom data types. It will only include exported fields in the encoded output and will by default use those names as the JSON keys. :::

::: {.zh}

JSON包可以自动编码您的自定义数据类型。它只会在编码输出中包含导出的字段,并且默认情况下会将这些名称用作JSON键。

:::

  1. res1D := &response1{
  2. Page: 1,
  3. Fruits: []string{"apple", "peach", "pear"}}
  4. res1B, _ := json.Marshal(res1D)
  5. fmt.Println(string(res1B))

::: {.en} You can use tags on struct field declarations to customize the encoded JSON key names. Check the definition of response2 above to see an example of such tags. :::

::: {.zh}

您可以在struct field declaration上使用标记来自定义编码的JSON密钥名称。检查上面的response2的定义,看看这样的标签的例子。

:::

  1. res2D := &response2{
  2. Page: 1,
  3. Fruits: []string{"apple", "peach", "pear"}}
  4. res2B, _ := json.Marshal(res2D)
  5. fmt.Println(string(res2B))

::: {.en} Now let’s look at decoding JSON data into Go values. Here’s an example for a generic data structure. :::

::: {.zh}

现在让我们看看将JSON数据解码为Govalues。以下是通用数据结构的示例。

:::

  1. byt := []byte(`{"num":6.13,"strs":["a","b"]}`)

::: {.en} We need to provide a variable where the JSON package can put the decoded data. This map[string]interface{} will hold a map of strings to arbitrary data types. :::

::: {.zh}

我们需要提供一个变量,JSON包可以放置解码数据。这个map [string] interface {}将保存stringsto任意数据类型的映射。

:::

  1. var dat map[string]interface{}

::: {.en} Here’s the actual decoding, and a check for associated errors. :::

::: {.zh}

这是实际的解码,以及检查伪造的错误。

:::

  1. if err := json.Unmarshal(byt, &dat); err != nil {
  2. panic(err)
  3. }
  4. fmt.Println(dat)

::: {.en} In order to use the values in the decoded map, we’ll need to convert them to their appropriate type. For example here we convert the value in num to the expected float64 type. :::

::: {.zh}

为了使用解码映射中的值,我们需要将它们转换为适当的类型。例如,我们将num中的值转换为预期的float64类型。

:::

  1. num := dat["num"].(float64)
  2. fmt.Println(num)

::: {.en} Accessing nested data requires a series of conversions. :::

::: {.zh}

访问嵌套数据需要一系列转换。

:::

  1. strs := dat["strs"].([]interface{})
  2. str1 := strs[0].(string)
  3. fmt.Println(str1)

::: {.en} We can also decode JSON into custom data types. This has the advantages of adding additional type-safety to our programs and eliminating the need for type assertions when accessing the decoded data. :::

::: {.zh}

我们还可以将JSON解码为自定义数据类型。这样做的好处是可以为我们的程序添加额外的类型安全性,并在访问解码数据时消除类型断言的需要。

:::

  1. str := `{"page": 1, "fruits": ["apple", "peach"]}`
  2. res := response2{}
  3. json.Unmarshal([]byte(str), &res)
  4. fmt.Println(res)
  5. fmt.Println(res.Fruits[0])

::: {.en} In the examples above we always used bytes and strings as intermediates between the data and JSON representation on standard out. We can also stream JSON encodings directly to os.Writers like os.Stdout or even HTTP response bodies. :::

::: {.zh}

在上面的例子中,我们总是使用字节和字符串作为标准输出上的数据和JSON表示之间的中介。我们可以将JSON编码直接转换为os.Writer,就像s.S.Soutout`甚至是HTTP响应体。

:::

  1. enc := json.NewEncoder(os.Stdout)
  2. d := map[string]int{"apple": 5, "lettuce": 7}
  3. enc.Encode(d)
  4. }
  1. $ go run json.go
  2. true
  3. 1
  4. 2.34
  5. "gopher"
  6. ["apple","peach","pear"]
  7. {"apple":5,"lettuce":7}
  8. {"Page":1,"Fruits":["apple","peach","pear"]}
  9. {"page":1,"fruits":["apple","peach","pear"]}
  10. map[num:6.13 strs:[a b]]
  11. 6.13
  12. a
  13. {1 [apple peach]}
  14. apple
  15. {"apple":5,"lettuce":7}

::: {.en} We’ve covered the basic of JSON in Go here, but check out the JSON and Go blog post and JSON package docs for more. :::

::: {.zh}

我们已经在Go中介绍了JSON的基本知识,但请查看[JSON and Go](http://blog.golang.org/2011/01/json-and-go.html)博客文章和[JSON包文档](http://golang.org/pkg/encoding/json/)了解更多。

:::