كيف تتعامل مع بيانات JSON في لغة بايثون

كيف تتعامل مع بيانات JSON في لغة بايثون

أهلا وسهلا بكم في هذا المقال من بايثونات والذي نتناول فيه كيفية التعامل مع بيانات json في لغة بايثون. في البداية سنتكلم عن ما هي json ثم سننتقل الى المكتبة المعيارية في البايثون والمختصة بهذا النوع من البيانات، ثم نشرح مثال عملي لقراءة بيانات على هيئة json مُتاحة للعامة في الإنترنت. هذا المقال موجه بالدرجة الأولى للمبتدئين في تعلم البايثون، حيث يُقدم معلومات أساسية في الموضوع.

ما هي json ؟

json هي اختصار لمصطلح JavaScript Object Notation، وهي معيار خاص يُستخدم في تمثيل البيانات في ملف أو مصدر بيانات ما، بحيث يستطيع الانسان قراءة البيانات بشكل سهل ومفهوم. الهدف من المعيار هو تقديم طريقة لتبادل البيانات بشكل متوافق عليه بين البرامج والأنظمة، ويعتمد طريقة خاصة في كتابة البيانات في الملف. بالطبع json ليست لغة ترميز او لغة برمجة، فهي تختص بالبيانات فقط.

كيف نكتب البيانات في json ؟

الطريقة الأشهر في كتابة البيانات على شكل json هي طريقة الكائن object. من خلال هذه الطريقة نستخدم الأقواس المُزهرة { } في كتابة البيانات بينها، ونُعطي كل عنصر من البيانات اسم مُعين يُمكن ان نعتبره المفتاح Key. كل مفتاح ترتبط به قيمة مُعينة Value تُمثل البيانات. يُمكن ان تكون القيمة عبارة عن عنصر json آخر.

json في لغة بايثون

من الجميل أن نجد مكتبة معيارية في بايثون مُخصصة للتعامل مع بيانات json. المكتبة هي بنفس الإسم json. الرابط التالي هو التوثيق الخاص بالمكتبة على الموقع الرسمي للغة البايثون: توثيق مكتبة json. للبدء باستخدام مكتبة json في لغة بايثون نستورد المكتبة:
import json

قراءة بيانات json وتحويلها لبايثون

يُمكننا تحويل البيانات الموجودة على هيئة نص json الى ما يقابلها من بيانات بايثون. لهذا الغرض نستخدم الدالة json.loads. من المهم أن نعرف هنا أن لغة البايثون تتعامل مع بيانات json كنص، وعليه فإن البيانات التي سنمررها لدالة json.loads ستكون بيانات بصيغة نصية. انظر المثال التالي الذي يعمل على تحويل بيانات json الى ما يُقابلها في البايثون:

import json

# json data as string
pythonat_json = '{ "Blog Name":"Pythonat", "Articles":19, "Authors":{"Founder":"Ibrahim","CoFounder":"Nasser"} }'

# parse json string
pythonat_python = json.loads(pythonat_json)

print(pythonat_python["Authors"])

لاحظ معي أن العنصر Authors هو عنصر json مُضمن داخل العنصر الرئيسي في مثالنا، فالعنصر الرئيسي يحتوي على 3 عناصر هي:

  1. Blog Name عند تحويله لبايثون سيكون من نوع نص
  2. Articles عند تحويله لبايثون سيكون من نوع رقم
  3. Authors عند تحويله لبايثون سيكون من نوع قاموس
# result will be str
type(pythonat_python["Blog Name"])

# result will be int
type(pythonat_python["Articles"])

# result will be dict
type(pythonat_python["Authors"])

التحويل من بايثون إلى json

كما أنه يُمكننا تحويل بيانات json الى ما يُقابلها في بايثون، يُمكننا من خلال مكتبة json في بايثون من إجراء التحويل بطريقة عكسية. لنعمل على تحويل عُنصر من نوع قاموس في البايثون إلى ما يُقابله في json.

يتم ذلك من خلال استخدام دالة json.dumps  كما يلي:

import json

# python variable as dict
pythonat_python = { "Blog Name":"Pythonat", "Articles":19, "Authors":
			{"Founder":"Ibrahim","CoFounder":"Nasser"}}

# dumps dict to json
pythonat_json = json.dumps(pythonat_json)

print(pythonat_json)

عند التعامل مع بيانات json في بايثون من المهم لنا معرفة أنواع البيانات التي يُمكننا التعامل معها في عملية التحويل من والى البايثون. الجدول التالي يُوضح لنا ما هي أنواع البيانات في بايثون وما يُقابلها في json:

JSON data typesPython data types
dictObject
listArray
tupleArray
strString
intNumber
floatNumber
Truetrue
Falsefalse
Nonenull

المثال التالي يشمل جميع أنواع البيانات التي يُمكن استخدامها في البايثون وتحويلها الى بيانات من نوع json:

import json

pythonat_data = {
  "Blog Name": "Pythonat",
  "Authors": [
    {"Name": "Ibrahim", "Age": 33},
    {"Name": "Nasser", "Age": 38}
  ],
  "Articles": 20,
  "New Blog": True,
  "News Blog": False,
  "Errors": None,
  "Categories": ("Networking","Data Science","GUI", "Security","Packages")
}

print(json.dumps(pythonat_data))

مثال عملي: قراءة بيانات json في لغة بايثون من الويب

كما أنه يُمكننا قراءة متغير من نوع نصي على شكل json، يُمكننا التعامل مع أي مصدر بيانات يُتيح لنا الحصول على بياناته بشكل json. في هذا العنوان نحن نتحدث عن كيفية قراءة بيانات json موجودة على الانترنت.

هذه الحالة شائعة في الكثير من البرامج والتطبيقات، وهي ان نتعامل مباشرةً مع البيانات الموجودة على شكل json. نحتاج لذلك الاستعانة بالمكتبة المعيارية الشهيرة في بايثون urllib التي يُمكننا من خلالها التعامل مع الروابط urls.

سنعمل في هذا المثال على قراءة بيانات خاصة بجائزة نوبل العالمية. البيانات مُتاحة للعامة على شكل json من خلال الرابط التالي:

بيانات جائزة نوبل على هيئة JSON

في البداية نستورد المكتبات اللازمة للعمل، ثم نستخدم دالة urlopen الموجودة في وحدة urllib.request والتي سنستعين بها لقراءة الناتج من رابط البيانات. الناتج سيكون من نوع HTTPRespose. اذا استطعنا قراءة الرابط بشكل صحيح، سيكون رقم حالة الطلب العائد من طلب الرابط هو 200 (لمعرفة المزيد حول أرقام حالات طلب http يُمكنك الاطلاع هنا). 200 تعني أننا استطعنا قراء الرابط بنجاح.

بعد ذلك نقرأ البيانات الراجعة من طلب الرابط من خلال دالة read ونحفظها في متغير باسم data.

import urllib.request
import json

urlData = "http://api.nobelprize.org/v1/prize.json"
webUrl = urllib.request.urlopen(urlData)
print(webUrl)
if (webUrl.getcode() == 200):
    data = webUrl.read()
else:
    print ("Error codde:" + str(webUrl.getcode()))

سنعمل على تجهيز دالتين، الأولى باسم count_years وتعمل على الحصول على عدد جوائز نوبل لكل سنة منذ بداية توزيع جوائز نوبل، والدالة الثانية باسم print_names تعمل على طباعة أسماء الأشخاص الذين حصلوا على جائزة نوبل حسب المجال وحسب العام. سأشرح الدوال مباشرة في الشيفرة البرمجية.

دالة count_years:

#دالة الحصول على عدد الجوائز لكل عام
def count_years(data):
    #نحول البيانات الناتجة عن قراءة رد الطلب الى جيسون
    theJSON = json.loads(data)
    #نعرف متغير من نوع قاموس سيكون فيه العام هو المفتاح وعدد الجوائز هي القيمة
    counts = {}
    #بعد ان اطلعنا على البيانات في جيسون وفهمنا هيكلتها عرفنا اننا سنبحث عن العنصر باسم
    #prizes
    #نقوم بالمرور على كل جائزة
    for i in theJSON["prizes"]:
        #نتأكد من وجود العام للجائزة
        if "year" in i:
            #دخولنا تحت هذه الجملة الشرطية يعني انه يوجد عنصر به رقم عام
            #نحفظ رقم العام الذي صدرت فيه الجائزة
            #ثم نضيف على مجموع تكرارها في البيانات برقم 1
            counts[i["year"]] = counts.get(i["year"],0) + 1
    #نطبع عدد الجوائز
    print(counts)
    return counts

دالة print_names:

#دالة طباعة أسماء الحاصلين على الجائزة
def print_names(data):
    #نحول البيانات الناتجة عن قراءة رد الطلب الى جيسون
    theJSON = json.loads(data)

    # نقوم بالمرور على كل جائزة عن طريق حلقة تكرار
    for i in theJSON["prizes"]:
        #لكل جائزة نطبع سطر يحتوي على نص ونوع مجال الجائزة والعام التي صدرت فيه
        print(("%s"+i["category"]+"%s"+i["year"]) % ("The winners of "," prize for year"))
        #لكل جائزة قد يكون هناك اكثر من فائز، نستخدم حلقة تكرار للمرور على كل فائز ونطبع اسمه
        #نستخدم هنا الاستثناء لوجود بعض الجوائز التي ليس لها بيانات كاملة (لن نطبعها) لعدم وجودها أساسًا
        try:
            for x in i["laureates"]:
                try:
                    print("   "+x["firstname"]+" "+x["surname"])
                except:
                    pass
        except:
            pass

المثال كاملًا:

import urllib.request
import json

#دالة الحصول على عدد الجوائز لكل عام
def count_years(data):
    #نحول البيانات الناتجة عن قراءة رد الطلب الى جيسون
    theJSON = json.loads(data)
    #نعرف متغير من نوع قاموس سيكون فيه العام هو المفتاح وعدد الجوائز هي القيمة
    counts = {}
    #بعد ان اطلعنا على البيانات في جيسون وفهمنا هيكلتها عرفنا اننا سنبحث عن العنصر باسم
    #prizes
    #نقوم بالمرور على كل جائزة
    for i in theJSON["prizes"]:
        #نتأكد من وجود العام للجائزة
        if "year" in i:
            #دخولنا تحت هذه الجملة الشرطية يعني انه يوجد عنصر به رقم عام
            #نحفظ رقم العام الذي صدرت فيه الجائزة
            #ثم نضيف على مجموع تكرارها في البيانات برقم 1
            counts[i["year"]] = counts.get(i["year"],0) + 1
    #نطبع عدد الجوائز
    print(counts)
    return counts

#دالة طباعة أسماء الحاصلين على الجائزة
def print_names(data):
    #نحول البيانات الناتجة عن قراءة رد الطلب الى جيسون
    theJSON = json.loads(data)

    # نقوم بالمرور على كل جائزة عن طريق حلقة تكرار
    for i in theJSON["prizes"]:
        #لكل جائزة نطبع سطر يحتوي على نص ونوع مجال الجائزة والعام التي صدرت فيه
        print(("%s"+i["category"]+"%s"+i["year"]) % ("The winners of "," prize for year"))
        #لكل جائزة قد يكون هناك اكثر من فائز، نستخدم حلقة تكرار للمرور على كل فائز ونطبع اسمه
        #نستخدم هنا الاستثناء لوجود بعض الجوائز التي ليس لها بيانات كاملة (لن نطبعها) لعدم وجودها أساسًا
        try:
            for x in i["laureates"]:
                try:
                    print("   "+x["firstname"]+" "+x["surname"])
                except:
                    pass
        except:
            pass

urlData = "http://api.nobelprize.org/v1/prize.json"
webUrl = urllib.request.urlopen(urlData)
print(webUrl)
if (webUrl.getcode() == 200):
    data = webUrl.read()
    count_years(data)
    #print_names(data)
else:
    print ("Error codde:" + str(webUrl.getcode()))

 

 

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *