Метод json.Decoder.Token

Метод json.Decoder.Token читает следующий JSON-токен из входного потока. Он возвращает токен в виде пустого интерфейса any, а также ошибку, если она возникла. Токен может быть одним из следующих типов: json.Delim (для скобок [, ], {, }), string, float64, bool, nil или json.Number (если включён режим UseNumber). Этот метод полезен, когда нужно обрабатывать JSON-данные потоково, без полной распаковки в структуру. Первый вызов Token начинает чтение с самого начала документа, а каждый последующий вызов перемещает курсор на следующий токен.

Синтаксис

gofunc (dec *json.Decoder) Token() (any, error)

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

Пример ⁅n="sect"⁆

Давайте последовательно прочитаем все токены из простого JSON-объекта:

gopackage main

import (
  "encoding/json"
  "fmt"
  "strings"
)

func main() {
  data := `{"name": "John", "age": 30, "active": true}`
  dec := json.NewDecoder(strings.NewReader(data))

  for {
    token, err := dec.Token()
    if err != nil {
      break
    }
    fmt.Printf("Token: %v (%T)\n", token, token)
  }
}

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

goToken: { (json.Delim)
Token: name (string)
Token: John (string)
Token: age (string)
Token: 30 (float64)
Token: active (string)
Token: true (bool)
Token: } (json.Delim)

Пример ⁅n="sect"⁆

Обработаем массив с числами, используя Token и проверяя тип каждого токена:

gopackage main

import (
  "encoding/json"
  "fmt"
  "strings"
)

func main() {
  data := `[10, 20.5, 30]`
  dec := json.NewDecoder(strings.NewReader(data))

  for {
    token, err := dec.Token()
    if err != nil {
      break
    }

    switch v := token.(type) {
    case json.Delim:
      fmt.Printf("Delimiter: %s\n", v)
    case float64:
      fmt.Printf("Number: %.1f\n", v)
    default:
      fmt.Printf("Other: %v\n", v)
    }
  }
}

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

goDelimiter: [
Number: 10.0
Number: 20.5
Number: 30.0
Delimiter: ]

Пример ⁅n="sect"⁆

Используем Token для проверки наличия следующего токена без его чтения — для этого применяем метод More:

gopackage main

import (
  "encoding/json"
  "fmt"
  "strings"
)

func main() {
  data := `{"x": 1, "y": 2}`
  dec := json.NewDecoder(strings.NewReader(data))

  // Пропускаем открывающую скобку
  dec.Token()

  for dec.More() {
    key, _ := dec.Token()
    value, _ := dec.Token()
    fmt.Printf("%s: %v\n", key, value)
  }
}

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

gox: 1
y: 2

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

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