# JSON katika Python: kusoma na kuandika faili, CSV, pathlib na usimbaji UTF-8

URL: https://skillaria.top/sw/guides/python/json-python

Kwa JSON katika Python kuna moduli ya kawaida json: json.load husoma data kutoka faili lililofunguliwa, json.dump huiandika kwenye faili, na json.loads na json.dumps hufanya hivyo hivyo kwa mifuatano. Faili hufunguliwa kwa with open(path, encoding="utf-8"), njia hujengwa kwa pathlib.Path, na jedwali husomwa kwa moduli ya csv.

Kufanya kazi na JSON katika Python hakuhitaji maktaba za nje: moduli `json` ipo katika maktaba ya kawaida na inageuza kamusi na orodha kuwa maandishi na kurudi tena. Karibu na hiyo mara nyingi unahitaji vitu vitatu zaidi: kazi `open` pamoja na muundo wa `with`, moduli `pathlib` kwa njia za faili, na moduli `csv` kwa majedwali. Hapa chini ni yote kwa mpangilio, pamoja na msimbo unaofanya kazi na mitego ambayo watu wengi hukwama nayo.

## Kazi ya open katika Python: njia na usimbaji

Faili lolote la maandishi hufunguliwa kwa kazi iliyojengwa ndani `open(path, mode, encoding=...)`. Inarudisha kitu cha faili chenye mbinu `read`, `readline` na `write`, na unaweza kukipitia kwa mzunguko mstari kwa mstari.

| Njia | Inafanya nini |
| --- | --- |

| `"r"` | Kusoma (chaguo-msingi). Faili lisipokuwepo — `FileNotFoundError` |

| `"w"` | Kuandika. Faili linaundwa au **linafutwa mara tu linapofunguliwa** |

| `"a"` | Kuongeza mwishoni, yaliyomo yaliyopo hayaguswi |

| `"x"` | Kuunda faili jipya; likiwepo tayari — `FileExistsError` |

| `"b"` | Nyongeza ya njia: kufanya kazi na baiti (`"rb"`, `"wb"`) |

### Kwa nini with inahitajika

Faili linapaswa kufungwa: vinginevyo data inaweza isifike diskini, na mfumo unaendelea kushikilia kipini cha faili. Muundo wa `with` hufunga faili kiotomatiki — hata kama kulitokea kosa ndani ya kizuizi.

```
with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("Mstari wa kwanza\n")
    f.write("Mstari wa pili\n")

with open("notes.txt", encoding="utf-8") as f:
    for line in f:
        print(line.rstrip("\n"))
```

Kupitia faili kwa mzunguko husoma mstari mmoja kwa wakati na hakupakii faili lote kwenye kumbukumbu, kwa hiyo hata logi za gigabaiti zinaweza kuchakatwa hivyo. Mbinu `f.read()` itarudisha maudhui yote kama mfuatano mmoja, na `f.readlines()` — orodha ya mistari.

### Jinsi ya kuandika mstari kwenye faili bila kufuta ya zamani

Kosa la kawaida la mwanzo ni kufungua faili kwa `"w"` ili "kuongeza" mstari. Hali `"w"` inafuta faili wakati wa kufunguliwa, kabla ya `write` ya kwanza. Ili kuongeza rekodi mwishoni tumia `"a"`, na ili kuhakikisha hautaandika juu ya faili la mtu mwingine — `"x"`.

```
with open("log.txt", "a", encoding="utf-8") as f:
    f.write("rekodi mpya\n")
```

Kumbuka kwamba `write` haiongezi mstari mpya yenyewe — `"\n"` inaandikwa waziwazi. Pia unaweza kutumia `print(..., file=f)`: itaweka mwisho wa mstari kwa ajili yako.

## Usimbaji UTF-8: kwa nini herufi zinaharibika

Kabla ya Python 3.15, kazi `open()` bila parameta `encoding` ilitumia usimbaji wa mfumo. Kwenye Linux na macOS hiyo ni UTF-8, lakini kwenye Windows inaweza kuwa cp1252 au nyingine. Skripti iliyofanya kazi vizuri kwenye seva, kwenye kompyuta ya mwenzako ilionyesha herufi zisizo sahihi (mojibake) au ilianguka kwa `UnicodeDecodeError`.

Katika Python 3.15, kwa PEP 686, hali ya UTF-8 imewashwa kwa chaguo-msingi: `open()` bila `encoding` inasoma na kuandika UTF-8 kwenye mifumo yote. Tabia ya zamani inaweza kurudishwa kwa kigezo cha mazingira `PYTHONUTF8=0` au bendera `-X utf8=0`, na kuomba waziwazi usimbaji wa mfumo — `encoding="locale"`.

```
import sys
print(sys.flags.utf8_mode)   # 1 katika Python 3.15

open("legacy.txt", encoding="locale")     # usimbaji wa mfumo
open("old_excel.csv", encoding="cp1252")  # faili lililohifadhiwa kwa cp1252
```

Upande wa pili: CSV ya zamani kutoka Excel au skripti ya Windows, iliyohifadhiwa kwa cp1252, sasa itasomwa kama UTF-8 na kusababisha `UnicodeDecodeError`. Suluhisho: lisome kwa `encoding="cp1252"` kisha liandike upya kwa UTF-8. Kanuni nzuri haibadiliki — taja `encoding` waziwazi, basi msimbo unafanya kazi vivyo hivyo kwenye toleo lolote.

## pathlib katika Python: njia kama vitu

Kuunganisha njia kwa mifuatano (`"data" + "/" + name`) ni ngumu na huvunjika kwenye mifumo tofauti. Moduli `pathlib` inatoa darasa `Path`, ambapo njia zinaunganishwa kwa opereta `/`, na kitu kina sifa zilizo wazi.

```
from pathlib import Path

data = Path("data")
csv_path = data / "expenses.csv"

print(csv_path.name)    # expenses.csv
print(csv_path.stem)    # expenses
print(csv_path.suffix)  # .csv
print(csv_path.parent)  # data
print(csv_path.exists())

data.mkdir(parents=True, exist_ok=True)
(data / "hello.txt").write_text("Habari", encoding="utf-8")
print((data / "hello.txt").read_text(encoding="utf-8"))

for p in data.glob("*.csv"):
    print(p)
```

Mbinu `read_text` na `write_text` zinachukua nafasi ya mchanganyiko wa `open` + `with` kwa faili ndogo. Kitu cha `Path` kinaweza kupitishwa kwa `open` ya kawaida, kwa `json` na kwa `csv` — zote zinakipokea. Njia inayohusiana na skripti yenyewe, si folda ya sasa, hupatikana hivi: `Path(__file__).parent / "data"`.

Katika Python 3.14 `Path` imepata mbinu `copy()` na `move()`, kwa hiyo kwa kunakili rahisi `shutil` haihitajiki tena. Katika toleo hilohilo maktaba ya kawaida imeongeza moduli `compression.zstd` kwa mbano ya Zstandard (PEP 784).

## JSON katika Python: load, dump, loads, dumps

JSON ni muundo wa maandishi wa kubadilishana data: API hutuma data kwa JSON, na mipangilio na ripoti huhifadhiwa humo. Moduli `json` inafanya shughuli mbili: serialization (kitu cha Python → maandishi ya JSON) na deserialization (maandishi → kitu). Mbinu ni nne, na kuchanganyikiwa kati yake ni swali la kawaida.

| Kazi | Inafanya nini |
| --- | --- |

| `json.dumps(obj)` | Kitu → mfuatano wa JSON |

| `json.loads(s)` | Mfuatano wa JSON → kitu |

| `json.dump(obj, f)` | Kitu → kuandika kwenye faili lililofunguliwa |

| `json.load(f)` | Kusoma JSON kutoka faili lililofunguliwa |

Ni rahisi kukumbuka: herufi `s` mwishoni inamaanisha string — kazi na mfuatano; bila hiyo — kazi na faili.

### Ulinganifu wa aina

| Python | JSON |
| --- | --- |

| `dict` | kitu `{}` |

| `list`, `tuple` | safu `[]` |

| `str` | mfuatano |

| `int`, `float` | namba |

| `True` / `False` | `true` / `false` |

| `None` | `null` |

Tuple ikisomwa tena itakuwa orodha, lakini seti, tarehe na `Decimal` moduli haizijui na itatoa `TypeError: Object of type ... is not JSON serializable`.

### Jinsi ya kuhifadhi JSON kwenye faili

```
import json
from pathlib import Path

report = {
    "month": "2026-10",
    "total": 15230.5,
    "categories": {"chakula": 8200, "usafiri": 2100},
    "tags": ["nyumbani", "kazi"],
}

path = Path("data/report.json")
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w", encoding="utf-8") as f:
    json.dump(report, f, ensure_ascii=False, indent=2)
```

Parameta `ensure_ascii=False` huhifadhi herufi za lugha yako kama zilivyo. Bila hiyo, badala ya "chakula" faili litakuwa na `"c..."` — JSON sahihi, lakini ni vigumu kwa binadamu kuisoma. `indent=2` hupanga muundo kwa mikunjo.

### Jinsi ya kusoma JSON kutoka faili

```
with open("data/report.json", encoding="utf-8") as f:
    data = json.load(f)

print(data["total"])               # 15230.5
print(data["categories"]["chakula"])   # 8200
```

Matokeo ni kamusi au orodha ya kawaida, na unaifanyia kazi kwa zana za kawaida. Faili lisilo JSON au lililokatika litasababisha `json.JSONDecodeError` yenye namba ya mstari na nafasi — inafaa kuikamata pale data inapotoka nje.

### Kuchambua mfuatano wa JSON na uchapishaji mzuri

```
import json

raw = '{"name": "Amina", "skills": ["python", "sql"], "active": true}'
user = json.loads(raw)
print(user["skills"][0])   # python

print(json.dumps(user, ensure_ascii=False, indent=2, sort_keys=True))
```

`sort_keys=True` hupanga funguo wakati wa kutoa matokeo — ni muhimu ili kulinganisha faili kwenye git. Kwa kupanga faili haraka kutoka terminal kuna zana iliyojengwa ndani: `python -m json.tool data/report.json`.

Jibu la HTTP API pia ni mfuatano wa JSON. Maktaba ya `requests` huichambua kwa mbinu `response.json()`, na ndani yake ni `json.loads` ile ile.

### Mtego: funguo za JSON daima ni mifuatano

```
d = {1: "januari", 2: "februari"}
back = json.loads(json.dumps(d))
print(back == d)   # False
print(back)        # {'1': 'januari', '2': 'februari'}
# back[1] -> KeyError, inahitajika back["1"]

fixed = {int(k): v for k, v in back.items()}
```

Katika JSON funguo za kitu zinaweza kuwa mifuatano tu, kwa hiyo funguo za namba baada ya mzunguko wa serialization zinageuka kuwa mifuatano. Zirejeshe kuwa namba unaposoma.

### Aina zako mwenyewe: tarehe na Decimal

```
import json
from datetime import date

def default(obj):
    if isinstance(obj, date):
        return obj.isoformat()
    raise TypeError(f"siwezi kuweka {type(obj).__name__} kwenye mfuatano")

print(json.dumps({"day": date(2026, 10, 1)}, default=default))
# {"day": "2026-10-01"}
```

Kazi iliyo kwenye parameta `default` huitwa kwa kila kitu kisichojulikana. Kwa visa tata unaweza kurithi kutoka `json.JSONEncoder` na kubadilisha mbinu `default`.

### Jinsi ya kuongeza kipengele kwenye safu ya JSON

JSON haiwezi kuongezwa mwishoni kama logi ya maandishi: faili linapaswa kusomwa, kubadilishwa na kuandikwa upya kwa ujumla.

```
path = Path("data/items.json")
items = json.loads(path.read_text(encoding="utf-8")) if path.exists() else []
items.append({"id": len(items) + 1, "title": "mpya"})
path.write_text(json.dumps(items, ensure_ascii=False, indent=2), encoding="utf-8")
```

Ikiwa rekodi ni nyingi na zinaongezwa kila mara, muundo wa JSON Lines ni rahisi zaidi: kitu kimoja cha JSON kwa mstari, na faili linafunguliwa kwa hali `"a"`.

## CSV katika Python: moduli csv

CSV ni jedwali katika faili la maandishi: mistari ni rekodi, thamani zimetenganishwa kwa koma. Moduli `csv` inashughulikia nukuu, koma ndani ya thamani na mivunjo ya mistari kwa usahihi, jambo ambalo `split(",")` ya kawaida haliwezi kufanya.

```
import csv

with open("data/expenses.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    total = 0.0
    for row in reader:
        total += float(row["amount"])
        print(row["date"], row["category"], row["amount"])
print("Jumla:", total)
```

`csv.DictReader` hugeuza kila mstari kuwa kamusi kwa kichwa cha faili. Thamani zote ni mifuatano: namba na tarehe zibadilishwe mwenyewe (`float`, `int`, `date.fromisoformat`). Faili lenye kitenganishi ";" (ambacho Excel ya Ulaya huhifadhi) husomwa kwa parameta `delimiter=";"`.

```
rows = [
    {"date": "2026-10-01", "category": "chakula", "amount": 450},
    {"date": "2026-10-02", "category": "usafiri", "amount": 60},
]
with open("data/out.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["date", "category", "amount"])
    writer.writeheader()
    writer.writerows(rows)
```

Wakati wa kuandika `newline=""` ni lazima: bila hiyo, kwenye Windows, mistari tupu itaonekana kati ya mistari. Ikiwa faili litafunguliwa kwenye Excel, tumia `encoding="utf-8-sig"` — alama ya BOM inasaidia Excel kutambua UTF-8.

## Kutoka CSV hadi JSON: mfano kamili

```
import csv
import json
from collections import defaultdict
from pathlib import Path

src = Path("data/expenses.csv")
dst = Path("data/report.json")

by_category = defaultdict(float)
with src.open(newline="", encoding="utf-8") as f:
    for row in csv.DictReader(f):
        by_category[row["category"]] += float(row["amount"])

report = {"total": sum(by_category.values()), "categories": dict(by_category)}
dst.write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8")
print(dst.read_text(encoding="utf-8"))
```

Huu ndio msingi wa skripti yoyote ya ripoti: ingizo kutoka CSV, mkusanyiko kwenye kamusi, na pato kwa JSON.

## Makosa ya kawaida

- `FileNotFoundError` — njia ni ya jamaa na inahesabiwa kutoka folda ya kuendesha, si kutoka skripti. Tumia `Path(__file__).parent`.
- Faili limefutwa — lilifunguliwa kwa `"w"` badala ya `"a"`.
- `UnicodeDecodeError` — faili lina usimbaji mwingine; itaje waziwazi (`cp1252`, `utf-8-sig`).
- `TypeError: Object of type set is not JSON serializable` — badilisha kuwa orodha au pitisha `default`.
- `KeyError` baada ya kupakia JSON — funguo za namba zimekuwa mifuatano.
- Faili lako limeitwa `json.py` au `csv.py` — linafunika moduli ya kawaida, na `import json` itaingiza faili lako.

## Hitimisho

Kwa JSON katika Python maktaba ya kawaida inatosha: `json.load`/`json.dump` kwa faili, `loads`/`dumps` kwa mifuatano, `ensure_ascii=False` na `indent` kwa matokeo yanayosomeka. Fungua faili kwa `with` pamoja na usimbaji ulio wazi, jenga njia kwa `pathlib`, na soma majedwali kwa `csv.DictReader`. Katika kozi ya Python mada hii inafundishwa kwa vitendo: kifuatiliaji cha matumizi kinasoma matumizi kutoka CSV na kuhifadhi ripoti kwenye JSON.

## FAQ

**json.load inatofautianaje na json.loads?**

json.load husoma JSON kutoka kitu cha faili kilichofunguliwa, na json.loads huchambua mfuatano. Vivyo hivyo json.dump huandika kwenye faili, na json.dumps hurudisha mfuatano.

**Ninawezaje kuhifadhi herufi za lugha yangu kwenye JSON bila mfuatano wa \u?**

Pitisha ensure_ascii=False kwenye json.dump au json.dumps, na ufungue faili kwa encoding="utf-8".

**Je, ni lazima kusakinisha maktaba ili kufanya kazi na JSON katika Python?**

Hapana, moduli json imejengwa ndani ya maktaba ya kawaida; inatosha kuandika import json.

**Je, naweza kuhifadhi tarehe au seti kwenye JSON?**

Moja kwa moja hapana: zinahitaji kubadilishwa, kwa mfano tarehe kuwa mfuatano wa ISO kwa isoformat, na seti kuwa orodha, au kupitisha kazi kwenye parameta default.

**Ninawezaje kusoma JSON kubwa isiyoingia kwenye kumbukumbu?**

json.load ya kawaida inasoma faili lote; kwa data kubwa hifadhi katika muundo wa JSON Lines na uchambue kwa mstari kwa json.loads.


---
Source: Skillaria.Top (https://skillaria.top)
