Asosiy qismga o'tish

JSON: ma'lumotni saqlash va almashish

21-bob 19 kod bloki 2293 so'z

Bu bobda

  • JSON nima va u Python dagi lug'at/ro'yxatga qanchalik o'xshashligini
  • json.dump / json.load bilan faylga yozish va o'qishni
  • json.dumps / json.loads bilan satrga o'girishni
  • o'zbekcha matn uchun ensure_ascii=False ni
  • "eslab qoladigan" dastur yozishni

JSON nima?

19-bobda ma'lumotni Ali,78 kabi qatorlarda saqladik. Ichma-ich ma'lumot uchun (talaba → baholar ro'yxati → har bir baho fani bilan) bu usul noqulay. JSON (JavaScript Object Notation) — ma'lumotni matn ko'rinishida saqlashning dunyo bo'yicha eng mashhur formati. Veb-saytlar, mobil ilovalar, Telegram botlar, sun'iy intellekt API lari — hammasi bir-biri bilan JSON da gaplashadi.

JSON 11-bobdagi lug'atlar ro'yxatiga juda o'xshaydi:

json7 qator
{
  "ism": "Sarvinoz",
  "yosh": 19,
  "talaba": true,
  "baholar": [5, 4, 5],
  "manzil": null
}
Python JSON
dict obyekt { }
list, tuple massiv [ ]
str satr — faqat qo'shtirnoq "..."
int, float son
True / False true / false
None null

Faylga yozish va o'qish: dump / load

python10 qator
import json

sonlar = [2, 3, 5, 7, 11, 13]
with open("sonlar.json", "w", encoding="utf-8") as f:
    json.dump(sonlar, f)

with open("sonlar.json", encoding="utf-8") as f:
    oqilgan = json.load(f)
print(oqilgan)
print(type(oqilgan), sum(oqilgan))
Natija
[2, 3, 5, 7, 11, 13]
<class 'list'> 41

19-bobdagi matnli fayldan farqi: o'qiganda satr emas, haqiqiy Python ro'yxati qaytdi. int() yoki split() kerak emas — turlar saqlanib qoladi.

Lug'at ham xuddi shunday:

python8 qator
import json

talaba = {"ism": "Sarvinoz", "yosh": 19, "baholar": [5, 4, 5], "manzil": None}
with open("talaba.json", "w", encoding="utf-8") as f:
    json.dump(talaba, f)

with open("talaba.json", encoding="utf-8") as f:
    print(f.read())
Natija
{"ism": "Sarvinoz", "yosh": 19, "baholar": [5, 4, 5], "manzil": null}

Faylning ichida None — null ga aylandi.

Chiroyli va o'zbekcha: indent va ensure_ascii

Fayl bitta uzun qatorda yozildi — kompyuter uchun bu yaxshi, odam uchun emas. O'zbek lotin alifbosidagi rasmiy ʻ belgisi esa bunday chiqadi:

python5 qator
import json

shahar = {"nomi": "Gʻijduvon", "viloyat": "Buxoro", "tumanlar": ["markaz", "Oʻrta"]}
print(json.dumps(shahar))
print(json.dumps(shahar, ensure_ascii=False, indent=2))
Natija
{"nomi": "G\u02bbijduvon", "viloyat": "Buxoro", "tumanlar": ["markaz", "O\u02bbrta"]}
{
  "nomi": "Gʻijduvon",
  "viloyat": "Buxoro",
  "tumanlar": [
    "markaz",
    "Oʻrta"
  ]
}
  • ensure_ascii=False — o'zbekcha, ruscha va boshqa harflarni ʻ ko'rinishiga o'girmasdan, o'zicha yozadi.
  • indent=2 — har bir darajani 2 probel bilan suradi, fayl o'qishga qulay bo'ladi.

Faylga yozishda ham xuddi shunday: json.dump(malumot, f, ensure_ascii=False, indent=2).

Satr bilan ishlash: dumps / loads

Oxirida s bo'lgan variantlar (string) fayl o'rniga satr bilan ishlaydi. Internetdan kelgan javob yoki ma'lumotlar bazasidagi maydon ko'pincha JSON satr bo'ladi:

python9 qator
import json

javob = '{"shahar": "Toshkent", "harorat": 18.5, "yomgir": false}'
obhavo = json.loads(javob)
print(obhavo["shahar"], obhavo["harorat"], obhavo["yomgir"])
print(type(obhavo))

matn = json.dumps({"ok": True, "xato": None})
print(matn, type(matn))
Natija
Toshkent 18.5 False
<class 'dict'>
{"ok": true, "xato": null} <class 'str'>
Funksiya Nimadan Nimaga
json.dump(obj, f) Python faylga
json.load(f) fayldan Python
json.dumps(obj) Python satrga
json.loads(s) satrdan Python

JSON da kalitlar faqat satr

python6 qator
import json

oylar = {1: "yanvar", 2: "fevral"}
qayta = json.loads(json.dumps(oylar))
print(qayta)
print(qayta.get(1), qayta.get("1"))
Natija
{'1': 'yanvar', '2': 'fevral'}
None yanvar

JSON obyektining kalitlari faqat satr bo'ladi, shuning uchun 1 kaliti "1" ga aylandi va qayta[1] endi ishlamaydi. Kortejlar ham ro'yxatga aylanadi. Saqlab qaytarganda turlar o'zgarishi mumkin joylarni tekshiring.

JSON ni qo'lda yozganda

python3 qator
import json

json.loads("{'ism': 'Ali'}")
Xato xabari
JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

JSON da satrlar faqat qo'shtirnoqda bo'ladi. 'Ali' — Python da to'g'ri, JSON da xato. Oxirgi elementdan keyingi vergul ([1, 2, ]) ham JSON da taqiqlangan.

Eslab qoladigan dastur

Foydalanuvchining ismini birinchi kirganda so'raydi, keyingi safar esa taniydi:

python13 qator
import json

fayl = "foydalanuvchi.json"
try:
    with open(fayl, encoding="utf-8") as f:
        ism = json.load(f)
except FileNotFoundError:
    ism = input("Ismingiz nima? ")
    with open(fayl, "w", encoding="utf-8") as f:
        json.dump(ism, f, ensure_ascii=False)
    print(f"Eslab qoldim, {ism}! Keyingi safar taniyman.")
else:
    print(f"Qaytganingizdan xursandmiz, {ism}!")
Natija
Ismingiz nima? Abulqosim
Eslab qoldim, Abulqosim! Keyingi safar taniyman.

Birinchi ishga tushishda fayl yo'q edi — ism so'raldi va saqlandi. Xuddi shu katakni yana bir bor ishga tushiramiz:

python13 qator
import json

fayl = "foydalanuvchi.json"
try:
    with open(fayl, encoding="utf-8") as f:
        ism = json.load(f)
except FileNotFoundError:
    ism = input("Ismingiz nima? ")
    with open(fayl, "w", encoding="utf-8") as f:
        json.dump(ism, f, ensure_ascii=False)
    print(f"Eslab qoldim, {ism}! Keyingi safar taniyman.")
else:
    print(f"Qaytganingizdan xursandmiz, {ism}!")
Natija
Qaytganingizdan xursandmiz, Abulqosim!

Endi u hech narsa so'ramadi — ismni fayldan oldi. Dasturni yopib, kompyuterni o'chirib yoqsangiz ham eslab turadi.

Funksiyalarga ajratish (refactoring)

Kod ishlaydi, lekin hamma narsa bitta joyda. Uni har biri bitta ish qiladigan funksiyalarga ajratamiz. Bu — "refactoring": ishlashini o'zgartirmasdan tuzilishini yaxshilash.

python32 qator
import json
from pathlib import Path

FAYL = Path("foydalanuvchi2.json")


def saqlangan_ism():
    """Saqlangan ismni qaytaradi; bo'lmasa — None."""
    try:
        return json.loads(FAYL.read_text(encoding="utf-8"))
    except FileNotFoundError:
        return None


def yangi_ism():
    """Ismni so'raydi va saqlaydi."""
    ism = input("Ismingiz nima? ").strip()
    FAYL.write_text(json.dumps(ism, ensure_ascii=False), encoding="utf-8")
    return ism


def salomlash():
    ism = saqlangan_ism()
    if ism:
        print(f"Qaytganingizdan xursandmiz, {ism}!")
    else:
        ism = yangi_ism()
        print(f"Eslab qoldim, {ism}!")


salomlash()
salomlash()
Natija
Ismingiz nima? Sarvinoz
Eslab qoldim, Sarvinoz!
Qaytganingizdan xursandmiz, Sarvinoz!

salomlash() ikki marta chaqirildi: birinchisida ism so'raldi, ikkinchisida tanildi. Har bir funksiyani alohida tushunish, tekshirish va o'zgartirish oson.

Ma'lumotni yangilash: o'qi → o'zgartir → yoz

JSON faylni "ichidan" o'zgartirib bo'lmaydi. Andoza doim bir xil: butunligicha o'qing, Python da o'zgartiring, butunligicha qayta yozing.

python17 qator
import json
from pathlib import Path

fayl = Path("jurnal.json")
fayl.write_text(json.dumps([
    {"ism": "Ali", "baholar": [5, 4]},
    {"ism": "Sarvinoz", "baholar": [5, 5]},
], ensure_ascii=False, indent=2), encoding="utf-8")

jurnal = json.loads(fayl.read_text(encoding="utf-8"))
for t in jurnal:
    if t["ism"] == "Ali":
        t["baholar"].append(5)
jurnal.append({"ism": "Otabek", "baholar": [4]})
fayl.write_text(json.dumps(jurnal, ensure_ascii=False, indent=2), encoding="utf-8")

print(fayl.read_text(encoding="utf-8"))
Natija
[
  {
    "ism": "Ali",
    "baholar": [
      5,
      4,
      5
    ]
  },
  {
    "ism": "Sarvinoz",
    "baholar": [
      5,
      5
    ]
  },
  {
    "ism": "Otabek",
    "baholar": [
      4
    ]
  }
]

Buzilgan fayl

Fayl bor, lekin ichi JSON emas (yarim yozilgan, qo'lda buzilgan) bo'lsa, json.load json.JSONDecodeError beradi. Ishonchli dastur buni ham ushlaydi:

python10 qator
import json
from pathlib import Path

Path("buzilgan.json").write_text('{"ism": "Ali", ', encoding="utf-8")
try:
    malumot = json.loads(Path("buzilgan.json").read_text(encoding="utf-8"))
except json.JSONDecodeError as e:
    print("Fayl buzilgan:", e)
    malumot = {}
print(malumot)
Natija
Fayl buzilgan: Expecting property name enclosed in double quotes: line 1 column 16 (char 15)
{}

Obyektlarni saqlash

json.dump o'z klassingiz obyektini to'g'ridan-to'g'ri tushunmaydi:

python11 qator
import json
from dataclasses import dataclass


@dataclass
class Talaba:
    ism: str
    ball: int


json.dumps(Talaba("Ali", 78))
Xato xabari
TypeError: Object of type Talaba is not JSON serializable

Yechim: saqlashda obyektni lug'atga, o'qishda lug'atni obyektga aylantirish. dataclass uchun asdict() tayyor, qaytarish uchun — ** (14-bob):

python17 qator
import json
from dataclasses import dataclass, asdict


@dataclass
class Talaba:
    ism: str
    ball: int


talabalar = [Talaba("Ali", 78), Talaba("Sarvinoz", 91)]
matn = json.dumps([asdict(t) for t in talabalar], ensure_ascii=False)
print(matn)

qayta = [Talaba(**d) for d in json.loads(matn)]
print(qayta)
print(qayta == talabalar)
Natija
[{"ism": "Ali", "ball": 78}, {"ism": "Sarvinoz", "ball": 91}]
[Talaba(ism='Ali', ball=78), Talaba(ism='Sarvinoz', ball=91)]
True

22-bobdagi loyiha aynan shu usulda ishlaydi.

Kitoblarda

  • Python asoslari: JSON bu kitobda yo'q; fayllar 88–91-betlar.
  • Python Crash Course: 10-bob, Storing Data 202–207-betlar (json.dump(), json.load(), Saving and Reading User-Generated Data, Refactoring — greet_user()).

Xulosa

  • JSON — ma'lumot almashishning umumiy tili: dict ↔ obyekt, list ↔ massiv, None ↔ null.
  • dump/load — fayl bilan, dumps/loads — satr bilan.
  • O'zbekcha uchun: ensure_ascii=False, o'qish uchun: indent=2, fayl uchun: encoding="utf-8".
  • Kalitlar satrga aylanadi; satrlar faqat qo'shtirnoqda.
  • Yangilash: o'qi → o'zgartir → qayta yoz. Fayl yo'q — FileNotFoundError, buzilgan — json.JSONDecodeError.
  • Obyektlar: asdict(obj) bilan saqlash, Klass(**d) bilan tiklash.

Mashqlar

Kirish ko'pincha JSON satr ko'rinishida beriladi — uni json.loads(input()) bilan o'qing.

21.1

JSON ro'yxat berilgan, masalan [3, 5, 8]. Elementlar yig'indisi va o'rtachasini chiqaring.

KirishKutilgan natija
[3, 5, 8]16 5.333333333333333
[10]10 10
[1, 2, 3, 4]10 2.5
Yechimni ko'rish
python3 qator
import json
r = json.loads(input())
print(sum(r), sum(r) / len(r))
21.2

JSON obyekt berilgan: kalitlari — talabalar ismlari, qiymatlari — baholar ro'yxati. Har bir talabaning o'rtacha bahosini, ismlar alifbo tartibida, ism o'rtacha ko'rinishida (2 xona bilan) chiqaring.

KirishKutilgan natija
{"Sarvinoz": [5, 5, 4], "Ali": [3, 4]}Ali 3.50 Sarvinoz 4.67
{"Vali": [5]}Vali 5.00
Yechimni ko'rish
python4 qator
import json
d = json.loads(input())
for ism in sorted(d):
    print(ism, f"{sum(d[ism]) / len(d[ism]):.2f}")
21.3

Birinchi qatorda N, keyingi N qatorda kalit qiymat berilgan (qiymat butun son). Ulardan lug'at yasab, uni JSON satr ko'rinishida, kalitlarni alifbo tartibida chiqaring. Maslahat: json.dumps(d, sort_keys=True).

KirishKutilgan natija
2, olma 3, anor 5{"anor": 5, "olma": 3}
1, x 0{"x": 0}
Yechimni ko'rish
python6 qator
import json
d = {}
for _ in range(int(input())):
    k, v = input().split()
    d[k] = int(v)
print(json.dumps(d, sort_keys=True))
21.4

JSON satr berilgan. U to'g'ri JSON bo'lsa, uning turini chiqaring: obyekt, massiv, satr, son yoki boshqa; buzilgan bo'lsa — Buzilgan JSON.

KirishKutilgan natija
{"a": 1}obyekt
[1, 2]massiv
42son
Yechimni ko'rish
python16 qator
import json
try:
    q = json.loads(input())
except json.JSONDecodeError:
    print("Buzilgan JSON")
else:
    if isinstance(q, dict):
        print("obyekt")
    elif isinstance(q, list):
        print("massiv")
    elif isinstance(q, str):
        print("satr")
    elif isinstance(q, (int, float)) and not isinstance(q, bool):
        print("son")
    else:
        print("boshqa")
21.5

Birinchi qatorda N, keyingi N qatorda ism ball. Ularni [{"ism": ..., "ball": ...}, ...] ko'rinishida natija.json ga yozing. Keyin faylni o'qib, eng yuqori ball olganning ismini chiqaring.

KirishKutilgan natija
3, Ali 78, Sarvinoz 91, Otabek 85Sarvinoz
1, Vali 10Vali
Yechimni ko'rish
python10 qator
import json
royxat = []
for _ in range(int(input())):
    ism, ball = input().split()
    royxat.append({"ism": ism, "ball": int(ball)})
with open("natija.json", "w", encoding="utf-8") as f:
    json.dump(royxat, f, ensure_ascii=False)
with open("natija.json", encoding="utf-8") as f:
    oqilgan = json.load(f)
print(max(oqilgan, key=lambda t: t["ball"])["ism"])

Bu bobni bepul o'qidingiz.

Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.

Telegramda yozish Narxlar