Разбор API-ответов
В этом руководстве показано, как разбирать типичные JSON-ответы HTTP API с помощью CyberGo JSON: извлечение статуса и метаданных пагинации, срезы массивов через выражения пути и десериализация в структуры.
Разбор постраничного API-ответа
Имитируется постраничный REST API-ответ: извлекаются статус и метаданные пагинации, срез items[0:2] получает подмножество, затем перебираются поля каждого элемента.
package main
import (
"fmt"
"github.com/cybergodev/json"
)
func main() {
// Имитация постраничного API-ответа
apiResponse := `{
"status": "success",
"data": {
"page": 2,
"per_page": 5,
"total": 48,
"items": [
{"id": 6, "name": "Проект 6", "stars": 120},
{"id": 7, "name": "Проект 7", "stars": 89},
{"id": 8, "name": "Проект 8", "stars": 245},
{"id": 9, "name": "Проект 9", "stars": 56},
{"id": 10, "name": "Проект 10", "stars": 312}
]
}
}`
// 1. Извлекаем статус и метаданные пагинации
status := json.GetString(apiResponse, "status")
page := json.GetInt(apiResponse, "data.page")
total := json.GetInt(apiResponse, "data.total")
fmt.Printf("Статус: %s, страница %d, всего %d\n", status, page, total)
// 2. Получаем весь массив данных
items := json.GetArray(apiResponse, "data.items")
fmt.Printf("Элементов на странице: %d\n", len(items))
// 3. Получаем подмножество через срез пути (первые 2 элемента)
firstTwo, err := json.Get(apiResponse, "data.items[0:2]")
if err != nil {
panic(err)
}
fmt.Printf("Первые два: %v\n", firstTwo)
// 4. Перебираем массив, извлекая поля каждого элемента
for i := 0; i < len(items); i++ {
name := json.GetString(apiResponse, fmt.Sprintf("data.items.%d.name", i))
stars := json.GetInt(apiResponse, fmt.Sprintf("data.items.%d.stars", i))
fmt.Printf(" - %s (%d stars)\n", name, stars)
}
}
// Вывод:
// Статус: success, страница 2, всего 48
// Элементов на странице: 5
// Первые два: [map[id:6 name:Проект 6 stars:120] map[id:7 name:Проект 7 stars:89]]
// - Проект 6 (120 stars)
// - Проект 7 (89 stars)
// - Проект 8 (245 stars)
// - Проект 9 (56 stars)
// - Проект 10 (312 stars)Подсказка
Синтаксис среза пути [start:end] возвращает подмножество массива. Также можно использовать [start:end:step] для среза с шагом, [-1] для последнего элемента и [*] как подстановку по всем элементам. Полный синтаксис см. в Синтаксисе пути.
Десериализация в структуры
Используйте GetTyped[T] для десериализации всего ответа или любого вложенного подобъекта в строго типизированную структуру; используйте ParseAny для получения значения any (удобно при неизвестной структуре).
package main
import (
"fmt"
"github.com/cybergodev/json"
)
// Repository представляет структуру репозитория в API-ответе
type Repository struct {
ID int `json:"id"`
Name string `json:"name"`
Stars int `json:"stars"`
}
// APIResponse представляет весь API-ответ
type APIResponse struct {
Status string `json:"status"`
Data struct {
Page int `json:"page"`
Total int `json:"total"`
Items []Repository `json:"items"`
} `json:"data"`
}
func main() {
apiResponse := `{
"status": "success",
"data": {
"page": 1,
"total": 3,
"items": [
{"id": 1, "name": "cybergo-json", "stars": 500},
{"id": 2, "name": "cybergo-jwt", "stars": 320},
{"id": 3, "name": "cybergo-httpc", "stars": 280}
]
}
}`
// 1. Десериализуем весь ответ в структуру (путь "." означает корневой объект)
resp := json.GetTyped[APIResponse](apiResponse, ".")
fmt.Printf("Статус: %s, репозиториев: %d\n", resp.Status, resp.Data.Total)
for _, repo := range resp.Data.Items {
fmt.Printf(" #%d %s (%d stars)\n", repo.ID, repo.Name, repo.Stars)
}
// 2. GetTyped для одного вложенного объекта (декодирование подобъекта в структуру)
firstRepo := json.GetTyped[Repository](apiResponse, "data.items.0")
fmt.Printf("Первый репозиторий: %+v\n", firstRepo)
// 3. ParseAny для произвольного значения (когда структура ответа неизвестна)
parsed, err := json.ParseAny(apiResponse)
if err != nil {
panic(err)
}
fmt.Printf("Тип результата: %T\n", parsed)
}
// Вывод:
// Статус: success, репозиториев: 3
// #1 cybergo-json (500 stars)
// #2 cybergo-jwt (320 stars)
// #3 cybergo-httpc (280 stars)
// Первый репозиторий: {ID:1 Name:cybergo-json Stars:500}
// Тип результата: map[string]interface {}Следующие шаги
- Базовые примеры — запросы по пути, основы кодирования структур
- Продвинутые примеры — SafeGet, пакетные операции и др.
- Шпаргалка — быстрый справочник по API
- Синтаксис пути — срезы, подстановки, извлечение полей