JSON از زمان آغاز به کار به سرعت به استانداردی برای تبادل اطلاعات تبدیل شده است. چه در حال انتقال داده از طریق یک API باشید و یا در حال ذخیره آن در پایگاه داده باشید، احتمالاً با JSON مواجه خواهید شد. خوشبختانه، پایتون ابزارهای قدرتمندی را برای ساده‌سازی این فرآیند و مدیریت مؤثر داده‌های JSON ارائه می‌کند.

معرفی JSON

JSON که مخفف عبارت JavaScript Object Notation است، از جاوا اسکریپت سرچشمه گرفته و اکنون استانداردی برای تبادل داده محسوب می شود.

محبوبیت آن ناشی از پشتیبانی بومی در جاوا اسکریپت است که منجر به عملکرد تجزیه و استخراج داده عالی در مرورگرهای وب می شود. علاوه بر این، سینتکس ساده JSON خواندن و نوشتن را برای انسان و رایانه آسان می کند.

برای اولین مواجهه با JSON، این کد نمونه را مشاهده کنید:

{
"website": "Karakit"
}

در قسمت بعدی این آموزش به طور عمیق‌تر به سینتکس JSON خواهید پرداخت. در حال حاضر، درک این نکته مهم است که JSON یک فرمت مبتنی بر متن است. این بدان معناست که شما می توانید فایل های JSON را با استفاده از هر ویرایشگر کد و یا حتی Notepad ایجاد کنید. به سادگی پسوند فایل را json. تعیین کنید، و اکثر ویرایشگرهای کد به طور خودکار داده های JSON شما را با برجسته کردن سینتکس نمایش می دهند.

بررسی سینتکس JSON

قبلاً، نگاهی اجمالی به داده های JSON داشتید. به عنوان یک توسعه دهنده پایتون، ممکن است متوجه شوید که ساختارهای JSON شبیه ساختارهای داده رایج پایتون هستند، مانند دیکشنری با کلیدهای رشته ای و مقادیر. اگر با دیکشنری های پایتون آشنایی دارید، درک خوبی از سینتکس شیء JSON خواهید داشت.

بعداً در این آموزش، یاد خواهید گرفت که می‌توانید از فهرست‌ها و دیگر انواع داده‌ها در سطح بالای یک سند JSON استفاده کنید.

شباهت بین دیکشنری های پایتون و اشیاء JSON عمدی است. یکی از اهداف ایجاد JSON به عنوان فرمت استاندارد تبادل داده این بود که بدون توجه به زبان برنامه نویسی که استفاده می کنید، کار با آن تا حد امکان راحت باشد.

برای بررسی بیشتر سینتکس JSON، یک فایل جدید به نام website.json ایجاد می کنیم و یک ساختار پیچیده‌تر JSON را به عنوان محتوای فایل اضافه می نماییم:

{
  "website": {
    "name": "KaraKit",
    "url": "https://karakit.ir",
    "active": true,
    "visitors_per_month": 15000,
    "contact": {
      "email": "info@karakit.ir",
      "phone": "+98-21-12345678",
      "fax": null
    },
    "sections": [
      {
        "name": "Datasheets",
        "url": "https://karakit.ir/datasheets",
        "items": [
          {
            "component": "ATmega8",
            "type": "Microcontroller",
            "available": true
          },
          {
            "component": "BC547",
            "type": "Transistor",
            "available": false
          }
        ]
      },
      {
        "name": "Programming",
        "url": "https://karakit.ir/programming",
        "tutorials": [
          {
            "title": "Python Basics",
            "level": "Beginner",
            "completed": true
          },
          {
            "title": "Advanced Python",
            "level": "Advanced",
            "completed": false
          }
        ]
      }
    ]
  }
}

در کد بالا، داده‌های فرضی مربوط به وبسایت کاراکیت را می‌بینید که به صورت JSON فرمت شده است. مقدار سطح بالا یک شی JSON است. درست مانند دیکشنری های پایتون، اشیاء JSON را در داخل کروشه {} قرار می دهیم.

در خط 1، شی JSON را با یک کروشه { شروع می‌کنیم و سپس شیء را در انتهای آخرین خط با یک کروشه }  می‌بندیم.

در حالی که فضای خالی بر عملکرد JSON تأثیر نمی گذارد، معمول است که اسناد JSON را با دو یا چهار فاصله برای تورفتگی قالب بندی کنند. اگر اندازه فایل نگران کننده است، می توان با حذف فضای خالی فایل JSON را کوچک کرد.

در یک شی JSON، می توانید صفر، یک یا چند جفت کلید-مقدار تعریف کنید. اگر چندین جفت کلید-مقدار را وارد کنید، باید با کاما (،) از هم جدا شوند.

یک جفت کلید-مقدار در JSON با یک دو نقطه : از هم جدا می شود. کلید، که یک رشته است، باید در دو گیومه ” ” محصور شود. برخلاف پایتون، رشته های JSON از نقل قول های تکی (‘) پشتیبانی نمی کنند.

مقادیر موجود در یک سند JSON به انواع داده های زیر محدود می شود:

نوع داده JSONتوضیحات
objectمجموعه‌ای از جفت‌های کلید-مقدار محصور شده در کروشه ({})
arrayفهرستی از مقادیر محصور در براکت ([])
stringمتن محصور شده در دو گیومه (“”)
numberاعداد صحیح یا اعداد اعشاری
booleanیا درست یا غلط بدون علامت نقل قول
nullیک مقدار null را نشان می دهد و به صورت null نوشته می شود
انواع داده Json

درست مانند دیکشنری ها و لیست ها، می توانید داده ها را داخل اشیاء و آرایه های JSON قرار دهید. به عنوان مثال، می توانید از یک شی به عنوان مقدار یک شی دیگر استفاده کنید یا هر مقدار مجاز را به عنوان یک آیتم در آرایه JSON بگنجانید.

به عنوان یک توسعه دهنده پایتون، به مقادیر Boolean توجه ویژه ای داشته باشید. به جای استفاده از True یا False ، JSON به حروف کوچک به سبک JavaScript Booleans یعنی  true یا false نیاز دارد.

نوشتن JSON با پایتون

پایتون به صورت پیش فرض از فرمت JSON از طریق ماژول داخلی json پشتیبانی می کند. این ماژول به طور خاص برای خواندن و نوشتن رشته های با فرمت JSON طراحی شده است و به شما این امکان را می دهد که به راحتی انواع داده پایتون را به JSON و بالعکس تبدیل کنید.

تبدیل داده ها به فرمت JSON به نام سریال سازی شناخته می شود. این فرآیند داده ها را به یک سری بایت برای ذخیره یا انتقال از طریق شبکه تبدیل می کند. فرآیند معکوس، deserialization، داده‌ها را از فرمت JSON به شکل قابل استفاده در پایتون رمزگشایی می‌کند.

بیایید با استفاده از ماژول json سریال سازی از پایتون به داده های JSON را شروع کنیم.

تبدیل دیکشنری پایتون به JSON

یکی از رایج ترین اقدامات هنگام کار با JSON در پایتون، تبدیل دیکشنری پایتون به یک شی JSON است. برای دریافت تصوری از نحوه کار، کد زیر را بنویسید و اجرا کنید:

import json
website = {"Name": "Karakit", "pages": 500}
json_string = json.dumps(website)
print(json_string)

{"Name": "Karakit", "pages": 500}

پس از وارد کردن ماژول json، می توانید از متد dump برای تبدیل دیکشنری پایتون به رشته ای با فرمت JSON استفاده کنید که نشان دهنده یک شی JSON است.

توجه به این نکته ضروری است که وقتی از dumps استفاده می کنید، خروجی یک رشته پایتون است. به عبارت دیگر، شما یک نوع داده JSON ایجاد نمی کنید. نتیجه مشابه چیزی است که با استفاده از تابع str داخلی پایتون دریافت می کنید:

print(str(website))
{'Name': 'Karakit', 'pages': 500}

استفاده از json.dumps زمانی جالب‌تر می‌شود که دیکشنری پایتون شما حاوی رشته‌هایی به عنوان کلید نباشد یا زمانی که مقادیر مستقیماً به فرمت JSON ترجمه نمی‌شوند:

import json
categories = {1 : "Biomedical Engineering", 2 : "Programming", 3 : "Electronics"}
json_string = json.dumps(categories)
print(json_string)

{"1": "Biomedical Engineering", "2": "Programming", "3": "Electronics"}

در دیکشنری categories ، کلیدهای 1، 2 و 3 عددی هستند. هنگامی که از dumps استفاده می کنید، کلیدهای دیکشنری به رشته هایی در یک رشته دیگر با فرمت JSON تبدیل می شوند.

یکی از ویژگی‌های عالی ماژول json پایتون این است که این تبدیل را برای شما انجام می‌دهد، که مخصوصاً هنگام استفاده از متغیرها به عنوان کلیدهای دیکشنری مفید است:

import json
category_id = 1
category_title = "electronics"
category = {category_id : {"Title": category_title}}
json_string = json.dumps(category)
print(json_string)

{"1": {"Title": "electronics"}}

هنگام تبدیل انواع داده پایتون به JSON، ماژول json مقادیر ارزیابی شده را پردازش می کند. این استاندارد به شدت به استاندارد JSON پایبند است. به عنوان مثال، هنگام تبدیل کلیدهای عدد صحیح مانند 1، آنها را به رشته “1” تبدیل می کند.

سریالی کردن سایر انواع داده های پایتون به JSON

ماژول json شما را قادر می سازد انواع مختلف داده رایج پایتون را به JSON تبدیل کنید. در زیر یک نمای کلی از انواع داده‌های پایتون و مقادیر قابل تبدیل به JSON آورده شده است:

PythonJSON
dictobject
listarray
tuplearray
strstring
intnumber
floatnumber
Truetrue
Falsefalse
Nonenull
تبدیل انواع داده از پایتون به Json

انواع مختلف داده پایتون، مانند لیست ها و تاپل ها، به یک نوع داده آرایه JSON سریال می شوند. این می تواند منجر به مشکلاتی در هنگام تبدیل داده های JSON به پایتون شود، زیرا ممکن است نوع داده اصلی حفظ نشود. بعداً هنگام یادگیری نحوه خواندن JSON، این مشکل را در آموزش بررسی خواهیم کرد.

دیکشنری ها احتمالاً رایج ترین نوع داده پایتون هستند که به عنوان مقدار سطح بالا در JSON استفاده می کنید. با این حال، می توانید انواع داده های دیگر فهرست شده در بالا را به همین راحتی با استفاده از json.dumps تبدیل کنید. به عنوان مثال، یک Boolean یا یک لیست را در نظر بگیرید:

json_boolean = json.dumps(False)
print(json_boolean)
'true'

category_list = ["Biomedical Engineering", "Programming", "Electronics"]
json_string = json.dumps(category_list)
print(json_string)
["Biomedical Engineering", "Programming", "Electronics"]

یک سند JSON می تواند دارای یک مقدار اسکالر منفرد، مانند یک عدد، در سطح بالا باشد که همچنان JSON معتبر است. با این حال، بیشتر اوقات، شما با مجموعه‌ای از جفت‌های کلید-مقدار کار خواهید کرد. همانطور که هر نوع داده ای را نمی توان به عنوان کلید دیکشنری در پایتون استفاده کرد، نمی توان همه کلیدها را به رشته های کلید JSON تبدیل کرد:

نوع داده در پایتونمجاز برای استفاده به عنوان کلید در json
dict
list
tuple
str
int
float
bool
None
انواع داده پایتون قابل استفاده به عنوان کلید در Json

شما نمی توانید از دیکشنری، لیست یا تاپل به عنوان کلید JSON استفاده کنید.

هنگام استفاده از json.dumps ، می‌توانید آرگومان‌هایی را برای کنترل ظاهر رشته با فرمت JSON اضافه کنید. برای مثال، می‌توانید کلیدهای دیکشنری را با تنظیم پارامتر «sort_keys» روی «True» مرتب کنید:

post_count = {"Electronic": 200, "Programming": 150, "Biomedical engineering":50}
json_data = json.dumps(post_count, sort_keys=True)
print(json_data)
{"Biomedical engineering": 50, "Electronic": 200, "Programming": 150}

وقتی «sort_keys» را روی «True» تنظیم می‌کنید، پایتون کلیدها را در طول سریال‌سازی یک دیکشنری بر اساس حروف الفبا مرتب می‌کند. اگر کلیدهای دیکشنری شما نشان دهنده نام ستون های پایگاه داده باشد و بخواهید آنها را به صورت سازماندهی شده برای کاربر نمایش دهید، این ویژگی می تواند مفید باشد.

هنگام تبدیل انواع داده پایتون به JSON، معمولاً هدف خاصی در ذهن دارید. اغلب، از JSON برای تداوم و تبادل داده استفاده می کنید. برای رسیدن به این هدف، باید داده‌های JSON خود را خارج از برنامه پایتون ذخیره کنید. در بخش بعدی با ذخیره داده های JSON در یک فایل آشنا می شویم.

نوشتن فایل JSON با پایتون

فرمت JSON برای ذخیره داده های خارج از برنامه پایتون مفید است. به جای راه اندازی پایگاه داده، ممکن است از یک فایل JSON برای ذخیره داده ها برای گردش کار خود استفاده کنید و پایتون این کار را آسان می کند.

برای نوشتن داده های پایتون در یک فایل JSON خارجی، از تابع json.dump استفاده می کنیم. این تابع مشابه تابعی است که قبلاً دیدید، اما بدون «s» در انتهای نام آن:

import json

website_data = {
                "name": "Karakit",
                "active": True,
                "languages": ["persian", "english",],
                "posts": 500,
                "contacts": {
                            "fax": None,
                            "phone": ("123456789", "987654321",),
                            },
                "categories": [
                              {
                                "category": "electronics",
                                "sub_categories": ["analog", "digital", "embedded",],
                              },
                              {
                                "category": "programming",
                                "sub_categories": ["python", "C++",],
                              },
                              {
                                "category": "biomedical engineering",
                                "sub_categories": ["equipment", "repair",],
                              },
                            ],
                }

with open("website.json", mode="w", encoding="utf-8") as write_file:
    json.dump(website_data, write_file)

در خطوط 3 تا 26 یک دیکشنری با نام «website_data» را تعریف می‌کنیم، که با استفاده از یک Context Manager در یک فایل JSON در خط 28 می‌نویسید. برای نشان دادن اینکه فایل حاوی داده‌های JSON است، پسوند فایل را روی «.json» تنظیم کنید.

هنگام استفاده از open خوب است که رمزگذاری یا encoding را مشخص کنید. برای JSON، utf-8 معمولا برای خواندن و نوشتن فایل ها استفاده می شود.

تابع ()json.dump دو آرگومان لازم دارد:

1. شیئی که می خواهید بنویسید

2. فایلی که می خواهید در آن بنویسید

علاوه بر این، json.dump چندین پارامتر اختیاری را ارائه می دهد که مشابه پارامترهای json.dumps است.

خواندن JSON با پایتون

در بخش‌های قبلی، نحوه سریال‌سازی داده‌های پایتون را در رشته‌ها و فایل‌های با فرمت JSON یاد گرفتید. اکنون، بیایید نحوه بارگیری داده های JSON را در برنامه پایتون خود بررسی کنیم.

مشابه json.dumps و json.dump، کتابخانه json دو تابع را برای جداسازی داده‌های JSON در یک شی پایتون ارائه می‌کند:

– json.loads: یک رشته، بایت، یا نمونه آرایه بایت را از حالت سریالی استخراج می کند.

– json.load: یک فایل متنی یا یک فایل باینری را از حالت سریالی استخراج می کند.

به عنوان یک قاعده کلی، زمانی که داده‌های شما در برنامه پایتون شما موجود است از json.loads استفاده کنید و از json.load برای فایل های خارجی ذخیره شده روی دیسک خود استفاده نمایید.

تبدیل از انواع داده‌ها و مقادیر JSON به Python از نقشه‌برداری مشابهی مانند زمانی که اشیاء پایتون را به فرمت JSON تبدیل می‌کنید، پیروی می‌کند:

JSONPython
objectdict
arraylist
stringstr
numberint
numberfloat
trueTrue
falseFalse
nullNone
تبدیل انواع داده از Json به پایتون

وقتی این جدول را با جدول قسمت قبل مقایسه می کنید، متوجه می شوید که پایتون یک نوع داده مربوط به هر یک از انواع داده JSON را ارائه می دهد. این مساله تضمین می‌کند که هنگام جداسازی داده‌های JSON در پایتون هیچ اطلاعاتی را از دست نخواهید داد.

اما باید توجه کنید که Deserialization دقیقا معکوس فرآیند سریال سازی نیست. چرا که کلیدهای JSON همیشه رشته ای هستند و همه انواع داده های پایتون را نمی توان به انواع JSON تبدیل کرد. این تناقض به این معنی است که برخی از اشیاء پایتون ممکن است پس از Serialization و سپس از Deserialization ، نوع اولیه خود را حفظ نکنند.

برای درک بهتر تبدیل انواع داده، با سریال سازی یک شی پایتون به JSON و سپس تبدیل داده های JSON به پایتون شروع می کنیم. به این ترتیب، می‌توانید تفاوت‌هایی را بین شی اصلی پایتون و چیزی که پس از جداسازی داده‌های JSON دریافت می‌کنید، شناسایی کنید.

تبدیل اشیاء JSON به دیکشنری پایتون

برای بررسی نحوه بارگیری دیکشنری پایتون از یک شی JSON، یک مثال را بررسی می کنیم. با ایجاد دیکشنری website شروع و سپس با استفاده از json.dumps() دیکشنری Python را به رشته JSON سریال می کنیم.

import json

website = {1: {'name': 'Karakit'}}
website_json = json.dumps(website)
print(website_json)

{"1": {"name": "Karakit"}}

با ارسال دیکشنری website به json.dumps، یک رشته با یک شی JSON ایجاد می کنید که در website_json ذخیره می شود. اگر می‌خواهید website_json را به دیکشنری پایتون تبدیل کنید، می‌توانید از json.loads استفاده نمایید:

website_dictionary = json.loads(website_json)
print(website_dictionary)

خواهید دید که نتیجه با دیکشنری website اولیه از نظر نوع داده ها تفاوت دارد:

{'1': {'name': 'Karakit'}}

تفاوت بین این دو دیکشنری ظریف است اما می تواند به طور قابل توجهی روی برنامه های پایتون شما تأثیر بگذارد. در JSON، کلیدها باید همیشه رشته ای باشند. هنگامی که با استفاده از json.dumps دیکشنری website  را به website_json  تبدیل کردید، کلید عدد صحیح 1 به رشته “1” تبدیل شد. موقع استفاده از json.loads، پایتون راهی برای دانستن اینکه کلید رشته باید به یک عدد صحیح برگردد، نداشت. در نتیجه، کلید دیکشنری شما پس از سریال‌زدایی یک رشته باقی ماند.

در مرحله بعد، رفتار مشابهی را با انجام یک تبدیل دیگر با انواع داده های مختلف پایتون بررسی خواهیم کرد!

سریال زدایی انواع داده های JSON

برای بررسی نحوه رفتار انواع داده های مختلف در یک رفت و برگشت از پایتون به JSON و برگشت، بیایید بخشی از دیکشنری «website_data» را از بخش قبلی استفاده کنیم. توجه داشته باشید که چگونه دیکشنری شامل انواع مختلف داده به عنوان مقادیر است:

website_data = {
                "name": "Karakit",
                "active": True,
                "languages": ["persian", "english",],
                "posts": 500,
                "contacts": {
                            "fax": None,
                            "phone": ("123456789", "987654321",),
                            },
                }

دیکشنری «website_data» شامل انواع مختلف داده رایج پایتون به عنوان مقادیر است. به عنوان مثال، شامل یک رشته در خط 2، یک Boolean در خط 3، یک “NoneType” در خط 7، و یک تاپل در خط 8 و غیره است.

حالا «website_data» را به یک رشته با فرمت JSON تبدیل می کنیم و سپس به پایتون برمی گردانیم. پس از آن، دیکشنری تازه ایجاد شده را بررسی می کنیم:

website_json = json.dumps(website_data)
print(website_json)

{"name": "Karakit", "active": true, "languages": ["persian", "english"], "posts": 500, "contacts": {"fax": null, "phone": ["123456789", "987654321"]}}  

website_dictionary = json.loads(website_json)
print(website_dictionary)

{'name': 'Karakit', 'active': True, 'languages': ['persian', 'english'], 'posts': 500, 'contacts': {'fax': None, 'phone': ['123456789', '987654321']}}

شما می توانید هر نوع داده JSON را به طور کامل به یک نوع داده مطابق پایتون تبدیل کنید. JSON Boolean true به ‘True’ تبدیل می شود، ‘null’ به ‘None’ تبدیل می شود و اشیا و آرایه ها به دیکشنری و لیست تبدیل می شوند. با این حال، یک استثنا وجود دارد که ممکن است در طول این رفت و برگشت ها با آن مواجه شوید:

print(type(website_data["contacts"]["phone"]))
<class 'tuple'>

print(type(website_dictionary["contacts"]["phone"]))
<class 'list'>

وقتی یک تاپل پایتون را سریال می کنید، به آرایه JSON تبدیل می شود. پس از بارگذاری JSON، یک آرایه JSON در یک لیست از فهرست خارج می شود، زیرا پایتون نمی تواند استنباط کند که شما قصد دارید آرایه یک تاپل باشد.

مسائلی از این دست ممکن است در طول رفت و برگشت داده ها اتفاق بیفتد. هنگامی که رفت و برگشت در همان برنامه اتفاق می افتد، ممکن است از انواع داده های مورد انتظار آگاهی بیشتری داشته باشید. اما وقتی با فایل‌های JSON خارجی که از برنامه دیگری سرچشمه می‌گیرند سر و کار داشته باشید، تبدیل‌های نوع داده می‌تواند مبهم‌تر باشد. در ادامه وضعیتی مانند این را بررسی خواهیم کرد!

باز کردن و خواندن یک فایل JSON خارجی با پایتون

در بخش قبلی، یک فایل پایتون ایجاد کردید که یک فایل website.json را ذخیره می کرد. هنگامی که می خواهیم محتوا را در یک فایل JSON بنویسیم، از json.dump استفاده می کنیم. همتای این دستور  json.load است. همانطور که از نام آن پیداست، می توانید از json.load برای بارگذاری یک فایل JSON در برنامه پایتون خود استفاده کنید.

برای خواندن فایل json در پایتون مثال زیر را مشاهده کنید:

import json

with open("website.json", mode="r", encoding="utf-8") as read_file:
    website_data = json.load(read_file)

print(website_data)

درست مانند نوشتن فایل، استفاده از مدیریت زمینه with open هنگام خواندن فایل در پایتون ایده خوبی است. به این ترتیب، دیگر نیازی به بستن مجدد فایل ندارید. هنگامی که می خواهید یک فایل JSON را بخوانید، از json.load در داخل بلوک دستور with استفاده می کنید.

آرگومان ورودی تابع load باید یک فایل متنی یا یک فایل باینری باشد. شی پایتون که از json.load دریافت می کنید به نوع داده سطح بالای فایل JSON شما بستگی دارد. در این مورد، فایل JSON حاوی یک شی در سطح بالایی است که به یک دیکشنری تبدیل می شود.