Тип json.Decoder
Тип json.Decoder предоставляет методы для чтения JSON-данных из потока ввода.
В отличие от функции json.Unmarshal, работающей с байтовыми срезами,
Decoder позволяет обрабатывать данные по мере их поступления,
что особенно важно при чтении больших JSON-файлов или данных из сетевых соединений.
Основной метод типа - Decode, который читает следующее JSON-значение из потока
и сохраняет его в переданную переменную.
Создание декодера
Для создания экземпляра json.Decoder используется функция
json.NewDecoder, которая принимает интерфейс io.Reader
в качестве аргумента. Это может быть файл, сетевое соединение, HTTP-тело
запроса или любой другой объект, реализующий чтение данных.
file, err := os.Open("data.json")
if err != nil {
log.Fatal(err)
}
defer file.Close()
decoder := json.NewDecoder(file)
Синтаксис
decoder.Decode(v interface{}) error
Метод Decode принимает указатель на переменную, в которую
будет декодировано JSON-значение. При успешном завершении возвращает nil,
иначе - ошибку. Если поток достиг конца, возвращается ошибка io.EOF.
Пример
Декодируем простой JSON-объект из строки:
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
jsonData := `{"name": "John", "age": 30}`
reader := strings.NewReader(jsonData)
decoder := json.NewDecoder(reader)
var person struct {
Name string `json:"name"`
Age int `json:"age"`
}
err := decoder.Decode(&person)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("Name: %s, Age: %d\n", person.Name, person.Age)
}
Результат выполнения кода:
"Name: John, Age: 30"
Пример
Декодируем массив JSON-объектов с использованием цикла:
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
jsonData := `[
{"id": 1, "value": "first"},
{"id": 2, "value": "second"},
{"id": 3, "value": "third"}
]`
reader := strings.NewReader(jsonData)
decoder := json.NewDecoder(reader)
var item struct {
ID int `json:"id"`
Value string `json:"value"`
}
for decoder.More() {
err := decoder.Decode(&item)
if err != nil {
fmt.Println("Error:", err)
break
}
fmt.Printf("ID: %d, Value: %s\n", item.ID, item.Value)
}
}
Результат выполнения кода:
"ID: 1, Value: first"
"ID: 2, Value: second"
"ID: 3, Value: third"
Метод More проверяет, есть ли в потоке еще данные для чтения,
что удобно для итеративной обработки массивов и больших наборов данных.
Пример
Декодируем вложенный JSON-объект:
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
jsonData := `{
"user": {
"name": "Alice",
"email": "alice@example.com"
},
"active": true
}`
reader := strings.NewReader(jsonData)
decoder := json.NewDecoder(reader)
var data struct {
User struct {
Name string `json:"name"`
Email string `json:"email"`
} `json:"user"`
Active bool `json:"active"`
}
err := decoder.Decode(&data)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("User: %s (%s), Active: %t\n",
data.User.Name, data.User.Email, data.Active)
}
Результат выполнения кода:
"User: Alice (alice@example.com), Active: true"
Обработка ошибок
При работе с json.Decoder важно корректно обрабатывать ошибки.
Метод Decode может возвращать ошибки синтаксического разбора,
несоответствия типов или ошибки ввода-вывода. Особое внимание стоит
уделить ошибке io.EOF, которая сигнализирует о достижении
конца потока данных.
package main
import (
"encoding/json"
"fmt"
"io"
"strings"
)
func main() {
reader := strings.NewReader(`{"valid": "json"}`)
decoder := json.NewDecoder(reader)
var result map[string]interface{}
err := decoder.Decode(&result)
if err != nil {
if err == io.EOF {
fmt.Println("End of data stream")
} else {
fmt.Println("Decode error:", err)
}
return
}
fmt.Printf("Data: %v\n", result)
}
Результат выполнения кода:
"Data: map[valid:json]"
Смотрите также
-
функцию
json.NewDecoder,
которая создает новый экземплярjson.Decoder -
метод
json.Decoder.Decode,
который декодирует следующее JSON-значение из потока -
метод
json.Decoder.More,
который проверяет наличие данных в потоке -
функцию
json.Unmarshal,
которая декодирует JSON из байтового среза