Tarkibga o'tish

Go’da JSON bilan ishlash

JSON matn ko‘rinishidagi ma’lumot almashish formatidir. Go’da encoding/json paketi JSON’ni Go qiymatiga dekodlaydi va Go qiymatini JSON ko‘rinishiga kodlaydi.

JSON va Go turlari

JSON qiymatlari odatda quyidagicha mos keladi:

JSON Go’da odatiy tur
string string
number int, float64 yoki boshqa son turi
boolean bool
array slice yoki array
object struct yoki map
null pointer, slice, map yoki interface uchun nil

Struct orqali dekodlashda faqat eksport qilinadigan, ya’ni katta harf bilan boshlangan fieldlar ishlatiladi.

Struct tag

type User struct {
    Name     string   `json:"name"`
    Email    string   `json:"email,omitempty"`
    Password string   `json:"-"`
    Roles    []string `json:"roles"`
}

json:"name" JSON kalitini belgilaydi. omitempty qiymat bo‘sh bo‘lsa fieldni kodlangan natijadan chiqaradi. json:"-" fieldni JSON kodlash va dekodlashdan butunlay chetlatadi.

Marshal va Unmarshal

json.Marshal() xotiradagi qiymatni []bytega kodlaydi, json.Unmarshal() esa to‘liq []byteni qiymatga dekodlaydi:

data, err := json.Marshal(User{Name: "Ali", Roles: []string{"editor"}})
if err != nil {
    return err
}

var user User
if err := json.Unmarshal(data, &user); err != nil {
    return err
}

Unmarshalga qiymatning o‘zi emas, yozish mumkin bo‘lgan pointer uzatiladi. Kichik va to‘liq xotirada mavjud JSON uchun bu funksiyalar qulay.

Encoder va Decoder

json.NewEncoder(w) natijani io.Writerga, json.NewDecoder(r) esa io.Readerdan oqim tarzida ishlaydi:

if err := json.NewEncoder(os.Stdout).Encode(user); err != nil {
    return err
}

Fayl, terminal yoki tarmoq ulanishi kabi oqim bilan ishlaganda Encoder va Decoder ortiqcha oraliq []byte yaratmaslikka yordam beradi. Encode natija oxiriga yangi qator ham qo‘shadi.

Qat’iy dekodlash

Konfiguratsiyada noto‘g‘ri yozilgan fieldni jim e’tiborsiz qoldirish xavfli. DisallowUnknownFields() noma’lum fieldni xato qiladi. Bitta JSON qiymatidan keyingi ortiqcha qiymatni ham tekshirish kerak:

func decodeConfig(r io.Reader) (Config, error) {
    var cfg Config
    dec := json.NewDecoder(r)
    dec.DisallowUnknownFields()

    if err := dec.Decode(&cfg); err != nil {
        return Config{}, fmt.Errorf("JSON o‘qilmadi: %w", err)
    }
    if err := dec.Decode(&struct{}{}); err != io.EOF {
        if err == nil {
            return Config{}, errors.New("faqat bitta JSON qiymati kutilgan")
        }
        return Config{}, fmt.Errorf("ortiqcha JSON qiymati: %w", err)
    }
    return cfg, nil
}

Bu funksiya uchun encoding/json, errors, fmt va io import qilinadi. Ikkinchi Decode io.EOF qaytarsa, oqimda boshqa qiymat yo‘q.

Xato turlari

Noto‘g‘ri JSON sintaksisi *json.SyntaxError, JSON qiymati Go field turiga mos kelmasligi esa *json.UnmarshalTypeError bo‘lishi mumkin:

var syntaxErr *json.SyntaxError
var typeErr *json.UnmarshalTypeError

switch {
case errors.As(err, &syntaxErr):
    fmt.Printf("JSON sintaksisi xato, offset: %d\n", syntaxErr.Offset)
case errors.As(err, &typeErr):
    fmt.Printf("%s field uchun tur noto‘g‘ri\n", typeErr.Field)
default:
    fmt.Println("JSON o‘qilmadi")
}

Ichki xato diagnostikasini logda saqlash mumkin. Tashqi foydalanuvchiga fayl yo‘li, maxfiy qiymat yoki ichki implementatsiyani oshkor qilmaydigan qisqa xabar qaytaring.

Konfiguratsiya misoli

main.go
package main

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

type Config struct {
    Address string `json:"address"`
    Debug   bool   `json:"debug"`
}

func main() {
    input := `{"address":"localhost:8080","debug":true}`
    var cfg Config
    dec := json.NewDecoder(strings.NewReader(input))
    dec.DisallowUnknownFields()
    if err := dec.Decode(&cfg); err != nil {
        log.Fatal("konfiguratsiya o‘qilmadi: ", err)
    }

    fmt.Printf("Manzil: %s, debug: %t\n", cfg.Address, cfg.Debug)
}

Bu misol JSON’ni fayl yoki HTTP’ga bog‘lamaydi. strings.Reader matnni io.Reader sifatida beradi, decoder esa uni Config structiga yozadi.

Xulosa

Marshal va Unmarshal tayyor baytlar, Encoder va Decoder esa oqimlar uchun qulay. Struct fieldlari eksport qilinishi kerak. Ishonchli konfiguratsiyada noma’lum field va ortiqcha JSON qiymatlarini rad eting, xato tafsilotlarini esa xavfsiz ko‘rsating.