Тип json.Decoder

Тип json.Decoder предоставляет методы для чтения JSON-данных из потока ввода. В отличие от функции json.Unmarshal, работающей с байтовыми срезами, Decoder позволяет обрабатывать данные по мере их поступления, что особенно важно при чтении больших JSON-файлов или данных из сетевых соединений. Основной метод типа - Decode, который читает следующее JSON-значение из потока и сохраняет его в переданную переменную.

Создание декодера

Для создания экземпляра json.Decoder используется функция json.NewDecoder, которая принимает интерфейс io.Reader в качестве аргумента. Это может быть файл, сетевое соединение, HTTP-тело запроса или любой другой объект, реализующий чтение данных.

gofile, err := os.Open("data.json")
if err != nil {
  log.Fatal(err)
}
defer file.Close()

decoder := json.NewDecoder(file)

Синтаксис

godecoder.Decode(v interface{}) error

Метод Decode принимает указатель на переменную, в которую будет декодировано JSON-значение. При успешном завершении возвращает nil, иначе - ошибку. Если поток достиг конца, возвращается ошибка io.EOF.

Пример

Декодируем простой JSON-объект из строки:

gopackage 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)
}

Результат выполнения кода:

go"Name: John, Age: 30"

Пример

Декодируем массив JSON-объектов с использованием цикла:

gopackage 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)
  }
}

Результат выполнения кода:

go"ID: 1, Value: first"
"ID: 2, Value: second"
"ID: 3, Value: third"

Метод More проверяет, есть ли в потоке еще данные для чтения, что удобно для итеративной обработки массивов и больших наборов данных.

Пример

Декодируем вложенный JSON-объект:

gopackage 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)
}

Результат выполнения кода:

go"User: Alice (alice@example.com), Active: true"

Обработка ошибок

При работе с json.Decoder важно корректно обрабатывать ошибки. Метод Decode может возвращать ошибки синтаксического разбора, несоответствия типов или ошибки ввода-вывода. Особое внимание стоит уделить ошибке io.EOF, которая сигнализирует о достижении конца потока данных.

gopackage 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)
}

Результат выполнения кода:

go"Data: map[valid:json]"

Смотрите также

  • функцию json.NewDecoder,
    которая создает новый экземпляр json.Decoder
  • метод json.Decoder.Decode,
    который декодирует следующее JSON-значение из потока
  • метод json.Decoder.More,
    который проверяет наличие данных в потоке
  • функцию json.Unmarshal,
    которая декодирует JSON из байтового среза