Menu

JSON ב-Python: קריאה, כתיבה ופענוח JSON עם המודול json

איך קוראים וכותבים JSON ב-Python: loads, dumps, קריאה מקבצים, הדפסה מעוצבת וטיפול במקרי הקצה שצצים עם נתונים אמיתיים.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

JSON ו-Python מדברים באותן צורות

JSON הוא פורמט ברירת המחדל עבור APIs, קובצי הגדרות והעברת נתונים ברשת. למזלם של מתכנתי Python, אובייקט JSON ממופה ישירות ל-dict של Python, מערך JSON ל-list, ומחרוזת JSON ל-str. ההתאמה הקרובה הזו היא הסיבה שקריאה וכתיבה של JSON ב-Python הן פעולה של שתי שורות.

המודול json מהספרייה הסטנדרטית מטפל בשני הכיוונים.

פענוח מחרוזת JSON

json.loads(text), כלומר "load string", מקבלת מחרוזת בפורמט JSON ומחזירה את אובייקט ה-Python שהיא מייצגת:

התוצאה היא dict רגיל. ניגשים למפתחות שלו כמו בכל dict: אין עטיפת JSON מיוחדת ואין מתודת .parse() על התוצאה.

אם המחרוזת אינה JSON תקין, json.loads זורקת json.JSONDecodeError. הודעת השגיאה כוללת את השורה והעמודה של הבעיה, ובדרך כלל זה מספיק כדי לזהות פסיק חסר או מירכאה שלא עברה escape.

כתיבת JSON כמחרוזת

json.dumps(data), כלומר "dump string", עושה את ההפך: היא מקבלת אובייקט Python ומחזירה מחרוזת JSON:

True, False ו-None של Python מתורגמים אוטומטית ל-true, false ו-null של JSON. מספרים ומחרוזות עוברים כמו שהם. רשימות הופכות למערכים, ו-dicts הופכים לאובייקטים.

הדפסה מעוצבת

פלט ברירת המחדל של json.dumps דחוס: מתאים להעברה ברשת, קשה לקריאה לבני אדם. העבירו indent=2 כדי לקבל משהו קריא יותר:

עוד כמה אפשרויות של dumps שכדאי להכיר:

  • sort_keys=True: ממיינת את מפתחות האובייקט לפי סדר אלפביתי. שימושי לפלט דטרמיניסטי (קובצי הגדרות, fixtures לבדיקות, diffs).
  • ensure_ascii=False: כותבת תווים שאינם ASCII (é, ü, 中) כמו שהם, במקום רצפי \u. בדרך כלל הבחירה הנכונה לקובצי UTF-8.
  • separators=(",", ":"): הפלט הצפוף ביותר האפשרי. בשילוב עם ensure_ascii=False מתקבל ה-JSON הקומפקטי ביותר ב-UTF-8 שאפשר להפיק.

קריאת JSON מקובץ

json.load(file), בלי s, קוראת ישירות מאובייקט קובץ. הדפוס הנפוץ משלב אותה עם with open:

import json

with open("config.json") as f:
    config = json.load(f)

print(config["version"])

אין צורך לקרוא קודם את כל הקובץ למחרוזת: json.load עוברת על אובייקט הקובץ בעצמה.

כתיבת JSON לקובץ

json.dump(data, file) היא המקבילה לכתיבה לקובץ:

import json

data = {"created": "2026-01-01", "items": [1, 2, 3]}

with open("state.json", "w") as f:
    json.dump(data, f, indent=2)

האפשרות indent עובדת גם כאן. פתחו את הקובץ שנוצר ותראו מסמך JSON מעוצב יפה.

קריאת תגובת JSON מ-API

רוב ספריות ה-HTTP מחזירות bytes או טקסט, ואתם קוראים ל-json.loads כדי להפוך אותם לנתונים שאפשר לעבוד איתם:

import json
import urllib.request

with urllib.request.urlopen("https://api.example.com/users/1") as response:
    text = response.read().decode("utf-8")

user = json.loads(text)
print(user["name"])

הספרייה requests (שמוסברת בנפרד) חוסכת צעד: יש לתגובה שלה מתודת .json() שקוראת ל-json.loads בשבילכם.

מה JSON יכול ומה לא יכול לייצג

מערכת הטיפוסים של JSON מצומצמת יותר מזו של Python. המיפוי בשני הכיוונים:

PythonJSON
dictאובייקט
list, tupleמערך
strמחרוזת
int, floatמספר
Truetrue
Falsefalse
Nonenull

tuples חוזרים מהמעבר הלוך ושוב כרשימות, והעובדה שהם היו tuple הולכת לאיבוד. sets, מחלקות מותאמות ואובייקטי datetime אינם ניתנים לסריאליזציה כברירת מחדל, ותקבלו TypeError: Object of type X is not JSON serializable.

טיפול ב-datetime ובאובייקטים מותאמים

שתי גישות נפוצות.

המירו קודם למבנה בטוח ל-JSON. בצעו את ההמרה בקוד שלכם, ואז בצעו סריאליזציה ל-dict רגיל:

העבירו פונקציית default=. json.dumps קוראת לה עבור כל ערך שהיא לא יודעת איך לבצע לו סריאליזציה:

כשקוראים את הנתונים בחזרה, צריך להמיר בעצמכם את מחרוזות ה-ISO ל-datetime: JSON לא זוכר מה הם היו במקור.

מעבר הלוך ושוב של dict דרך JSON

בדיקה מהירה ש-dicts שורדים את המעבר:

הערכים שווים, אבל אלה אובייקטים שונים. לרוב זה בדיוק מה שרוצים: json.dumps ואחריה json.loads הן דרך זולה ליצור עותק עמוק של כל מבנה שתואם ל-JSON.

דוגמה מציאותית

סקריפט קטן שטוען קובץ הגדרות JSON, מעדכן שדה ושומר אותו בחזרה:

import json
from pathlib import Path

config_path = Path("settings.json")

# טעינה (עם ברירת מחדל אם הקובץ לא קיים).
if config_path.exists():
    config = json.loads(config_path.read_text())
else:
    config = {"theme": "dark", "last_opened": None}

# עדכון.
config["last_opened"] = "2026-01-15"

# שמירה, בפורמט מעוצב.
config_path.write_text(json.dumps(config, indent=2, ensure_ascii=False))

זה מחזור שלם של "קריאה, שינוי, כתיבה" של JSON בתריסר שורות.

כמה הרגלים

  • השתמשו ב-with open(...) לקבצים, תמיד. JSON הוא בסך הכול טקסט, וכל הכללים של עבודה עם קבצים חלים עליו.
  • העדיפו indent=2 לקבצים שבני אדם קוראים: הגדרות, fixtures, נתונים מיוצאים. וותרו עליו בתעבורת רשת, שבה חשובה הקומפקטיות.
  • הגדירו ensure_ascii=False לפלט UTF-8 כדי ששמות עם ניקוד, אותיות מוטעמות או תווים שאינם לטיניים יישארו קריאים.
  • אמתו עם try/except json.JSONDecodeError כשאתם מפענחים נתונים שלא אתם יצרתם.

הצעד הבא

JSON מטפל בנתוני מפתח-ערך. הכלי הבא באותו פרק הוא CSV: התמיכה המובנית של Python בפורמט הטבלאי שמאחורי רוב קובצי הייצוא מגיליונות אלקטרוניים שתיתקלו בהם.

שאלות נפוצות

איך מפענחים JSON ב-Python?

השתמשו ב-json.loads(text) עבור מחרוזת JSON או ב-json.load(file) עבור אובייקט קובץ. שניהם מחזירים dict של Python (או list, תלוי ב-JSON). לדוגמה: data = json.loads('{"name": "Rosa"}'), ואז data['name'] הוא 'Rosa'.

איך ממירים dictionary של Python ל-JSON?

json.dumps(my_dict) מחזירה מחרוזת JSON. json.dump(my_dict, file) כותבת ישירות לאובייקט קובץ. העבירו indent=2 כדי לקבל פלט מעוצב: json.dumps(data, indent=2).

מה ההבדל בין json.loads ל-json.load?

loads (עם s) מקבלת מחרוזת. load (בלי s) מקבלת אובייקט קובץ. אותו דבר לגבי dumps מול dump. ה-s מסמנת string, וזו הדרך הקלה ביותר לזכור מה זה מה.

איך מטפלים בתאריכים ובאובייקטים מותאמים ב-JSON?

ל-JSON אין טיפוס תאריך, אז העבירו תאריכים כמחרוזות ISO-8601 ופענחו אותם בחזרה ידנית. עבור מחלקות מותאמות, אפשר להעביר ל-json.dumps פונקציית default= שמחזירה ייצוג בטוח ל-JSON, או להמיר בעצמכם ל-dict לפני הסריאליזציה.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל