JSON: ma'lumotni saqlash va almashish
Bu bobda
- JSON nima va u Python dagi lug'at/ro'yxatga qanchalik o'xshashligini
json.dump/json.loadbilan faylga yozish va o'qishnijson.dumps/json.loadsbilan satrga o'girishni- o'zbekcha matn uchun
ensure_ascii=Falseni - "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:
{
"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
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))
[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:
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())
{"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:
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))
{"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:
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))
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
import json oylar = {1: "yanvar", 2: "fevral"} qayta = json.loads(json.dumps(oylar)) print(qayta) print(qayta.get(1), qayta.get("1"))
{'1': 'yanvar', '2': 'fevral'}
None yanvarJSON 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
import json json.loads("{'ism': 'Ali'}")
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:
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}!")
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:
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}!")
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.
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()
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.
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"))
[
{
"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:
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)
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:
import json from dataclasses import dataclass @dataclass class Talaba: ism: str ball: int json.dumps(Talaba("Ali", 78))
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):
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)
[{"ism": "Ali", "ball": 78}, {"ism": "Sarvinoz", "ball": 91}]
[Talaba(ism='Ali', ball=78), Talaba(ism='Sarvinoz', ball=91)]
True22-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.
JSON ro'yxat berilgan, masalan [3, 5, 8]. Elementlar yig'indisi va o'rtachasini chiqaring.
| Kirish | Kutilgan natija |
|---|---|
| [3, 5, 8] | 16 5.333333333333333 |
| [10] | 10 10 |
| [1, 2, 3, 4] | 10 2.5 |
Yechimni ko'rish
import json r = json.loads(input()) print(sum(r), sum(r) / len(r))
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.
| Kirish | Kutilgan natija |
|---|---|
| {"Sarvinoz": [5, 5, 4], "Ali": [3, 4]} | Ali 3.50 Sarvinoz 4.67 |
| {"Vali": [5]} | Vali 5.00 |
Yechimni ko'rish
import json d = json.loads(input()) for ism in sorted(d): print(ism, f"{sum(d[ism]) / len(d[ism]):.2f}")
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).
| Kirish | Kutilgan natija |
|---|---|
| 2, olma 3, anor 5 | {"anor": 5, "olma": 3} |
| 1, x 0 | {"x": 0} |
Yechimni ko'rish
import json d = {} for _ in range(int(input())): k, v = input().split() d[k] = int(v) print(json.dumps(d, sort_keys=True))
JSON satr berilgan. U to'g'ri JSON bo'lsa, uning turini chiqaring: obyekt, massiv, satr, son yoki boshqa; buzilgan bo'lsa — Buzilgan JSON.
| Kirish | Kutilgan natija |
|---|---|
| {"a": 1} | obyekt |
| [1, 2] | massiv |
| 42 | son |
Yechimni ko'rish
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")
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.
| Kirish | Kutilgan natija |
|---|---|
| 3, Ali 78, Sarvinoz 91, Otabek 85 | Sarvinoz |
| 1, Vali 10 | Vali |
Yechimni ko'rish
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.