json.Decoder.More

Метод json.Decoder.More возвращает true, если после текущей позиции в входном потоке есть еще JSON-токены для чтения, и false - в противном случае. Этот метод часто используется вместе с json.Decoder.Token для итеративного разбора JSON-массивов или потоков данных.

Синтаксис

godec.More() bool

Пример с массивом JSON

Давайте разберем JSON-массив и проверим наличие следующих элементов:

gopackage main

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

func main() {
  data := `["a", "b", "c", "d", "e"]`
  dec := json.NewDecoder(strings.NewReader(data))

  t, err := dec.Token()
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  fmt.Printf("Token: %v\n", t)

  for dec.More() {
    var value string
    err := dec.Decode(&value)
    if err != nil {
      fmt.Println("Error:", err)
      return
    }
    fmt.Println("Value:", value)
  }

  t, err = dec.Token()
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  fmt.Printf("Token: %v\n", t)
}

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

go"Token: ["
"Value: a"
"Value: b"
"Value: c"
"Value: d"
"Value: e"
"Token: ]"

В этом примере мы сначала читаем открывающую скобку массива, затем в цикле читаем все элементы, пока dec.More возвращает true, и наконец читаем закрывающую скобку.

Пример с потоком JSON-объектов

Рассмотрим случай, когда входной поток содержит несколько JSON-объектов, следующих друг за другом:

gopackage main

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

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

  for dec.More() {
    var obj map[string]int
    err := dec.Decode(&obj)
    if err != nil {
      fmt.Println("Error:", err)
      return
    }
    fmt.Printf("Object: %v\n", obj)
  }
}

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

go"Object: map[x:1]"
"Object: map[y:2]"
"Object: map[z:3]"

Здесь dec.More используется для проверки наличия следующего объекта в потоке, что позволяет читать несколько корневых JSON-элементов последовательно.

Пример с вложенными структурами

Покажем, как dec.More работает при разборе вложенных JSON-объектов:

gopackage main

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

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

  t, err := dec.Token()
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  fmt.Printf("First token: %v\n", t)

  for dec.More() {
    key, err := dec.Token()
    if err != nil {
      fmt.Println("Error:", err)
      return
    }
    fmt.Printf("Key: %v\n", key)

    if key == "person" {
      t, err := dec.Token()
      if err != nil {
        fmt.Println("Error:", err)
        return
      }
      fmt.Printf("Start object: %v\n", t)

      for dec.More() {
        subKey, err := dec.Token()
        if err != nil {
          fmt.Println("Error:", err)
          return
        }
        fmt.Printf("  SubKey: %v\n", subKey)

        var value interface{}
        err = dec.Decode(&value)
        if err != nil {
          fmt.Println("Error:", err)
          return
        }
        fmt.Printf("  Value: %v\n", value)
      }

      t, err = dec.Token()
      if err != nil {
        fmt.Println("Error:", err)
        return
      }
      fmt.Printf("End object: %v\n", t)
    } else {
      var value bool
      err := dec.Decode(&value)
      if err != nil {
        fmt.Println("Error:", err)
        return
      }
      fmt.Printf("Value: %v\n", value)
    }
  }

  t, err = dec.Token()
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  fmt.Printf("Last token: %v\n", t)
}

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

go"First token: {"
"Key: person"
"Start object: {"
"  SubKey: name"
"  Value: John"
"  SubKey: age"
"  Value: 30"
"End object: }"
"Key: active"
"Value: true"
"Last token: }"

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

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