127 lines
5.1 KiB
Go
127 lines
5.1 KiB
Go
// Go предлагает встроенную поддержку кодирования и
|
||
// декодирования JSON, в том числе встроенных и
|
||
// пользовательских типов данных.
|
||
|
||
package main
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"os"
|
||
)
|
||
|
||
// Мы будем использовать эти две структуры, для демонстрации
|
||
// кодирования и декодирования.
|
||
type response1 struct {
|
||
Page int
|
||
Fruits []string
|
||
}
|
||
|
||
// Только экспортируемые поля могут быть кодированы и
|
||
// декодированы в JSON. Поля должны начинаться с
|
||
// заглавной буквы.
|
||
type response2 struct {
|
||
Page int `json:"page"`
|
||
Fruits []string `json:"fruits"`
|
||
}
|
||
|
||
func main() {
|
||
|
||
// Для начала мы рассмотрим кодирование данных в
|
||
// JSON строку. Вот несколько примеров для простых
|
||
// типов данных.
|
||
bolB, _ := json.Marshal(true)
|
||
fmt.Println(string(bolB))
|
||
|
||
intB, _ := json.Marshal(1)
|
||
fmt.Println(string(intB))
|
||
|
||
fltB, _ := json.Marshal(2.34)
|
||
fmt.Println(string(fltB))
|
||
|
||
strB, _ := json.Marshal("gopher")
|
||
fmt.Println(string(strB))
|
||
|
||
// А вот примеры для срезов и карт, которые кодируются
|
||
// в JSON массивы и объекты, как мы и ожидаем.
|
||
slcD := []string{"apple", "peach", "pear"}
|
||
slcB, _ := json.Marshal(slcD)
|
||
fmt.Println(string(slcB))
|
||
|
||
mapD := map[string]int{"apple": 5, "lettuce": 7}
|
||
mapB, _ := json.Marshal(mapD)
|
||
fmt.Println(string(mapB))
|
||
|
||
// Пакет JSON может автоматически кодировать ваши
|
||
// пользовательские типы данных. Он будет включать
|
||
// только экспортируемые поля в закодированный
|
||
// вывод и по умолчанию будет использовать эти
|
||
// имена в качестве ключей JSON.
|
||
res1D := &response1{
|
||
Page: 1,
|
||
Fruits: []string{"apple", "peach", "pear"}}
|
||
res1B, _ := json.Marshal(res1D)
|
||
fmt.Println(string(res1B))
|
||
|
||
// Вы можете использовать теги в объявлениях
|
||
// структурных полей для настройки кодированных имен
|
||
// ключей JSON. Проверьте определение `response2`
|
||
// выше, чтобы увидеть пример таких тегов.
|
||
res2D := &response2{
|
||
Page: 1,
|
||
Fruits: []string{"apple", "peach", "pear"}}
|
||
res2B, _ := json.Marshal(res2D)
|
||
fmt.Println(string(res2B))
|
||
|
||
// Теперь давайте рассмотрим декодирование данных
|
||
// JSON в значения Go. Вот пример для общей
|
||
// структуры данных.
|
||
byt := []byte(`{"num":6.13,"strs":["a","b"]}`)
|
||
|
||
// Нам нужно предоставить переменную, в которую пакет
|
||
// JSON может поместить декодированные данные.
|
||
// `map[string]interface{} будет содержать карту
|
||
// строк для произвольных типов данных.
|
||
var dat map[string]interface{}
|
||
|
||
// Вот фактическое декодирование и проверка на наличие
|
||
// ошибок.
|
||
if err := json.Unmarshal(byt, &dat); err != nil {
|
||
panic(err)
|
||
}
|
||
fmt.Println(dat)
|
||
|
||
// Чтобы использовать значения в декодированной карте,
|
||
// нам нужно преобразовать их в соответствующий тип.
|
||
// Например, здесь мы конвертируем значение из `num`
|
||
// в ожидаемый тип `float64`.
|
||
num := dat["num"].(float64)
|
||
fmt.Println(num)
|
||
|
||
// Доступ к вложенным данным требует ряда преобразований.
|
||
strs := dat["strs"].([]interface{})
|
||
str1 := strs[0].(string)
|
||
fmt.Println(str1)
|
||
|
||
// Мы также можем декодировать JSON в пользовательские
|
||
// типы данных. Это дает преимущество добавления
|
||
// дополнительной безопасности типов в наши программы
|
||
// и устранения необходимости в определении типрв
|
||
// при доступе к декодированным данным.
|
||
str := `{"page": 1, "fruits": ["apple", "peach"]}`
|
||
res := response2{}
|
||
json.Unmarshal([]byte(str), &res)
|
||
fmt.Println(res)
|
||
fmt.Println(res.Fruits[0])
|
||
|
||
// В приведенных выше примерах мы всегда использовали
|
||
// байты и строки в качестве промежуточных звеньев между
|
||
// данными и представлением JSON на стандартном выходе.
|
||
// Мы также можем транслировать JSON-кодировки напрямую
|
||
// в `os.Writer`, такие как `os.Stdout` или даже HTTP-тела
|
||
// ответа.
|
||
enc := json.NewEncoder(os.Stdout)
|
||
d := map[string]int{"apple": 5, "lettuce": 7}
|
||
enc.Encode(d)
|
||
}
|