فرمت دهی JavaScript Object Notation
در این مقاله قرار است طریقه فرمت دهی JSON و خودکارسازی jq و CI/C را بیاموزیم.
یک برنامه تحت وب زمانی مدرن محسوب میشود که یک REST API برای برگرداندن JSON داشته باشد. برای شکل دهی JSON ها، نیاز است که اول آنها را تجزیه کنیم که اکثرا بعد از تجزیه شدن به صورت اسکریپت در می آیند. سپس سرویس daemon ها برای خودکارسازی, آن API ها را بررسی و تست میکنند.
با یک REST API جدید شروع کنید. البته یادتان باشد که اکثر اوقات نقطه پایان آن غافلگیر کننده است.
عمل مستندسازی گاهی اوقات به شما پیشنهاد میکند که به یک مجموعه از SDK ها و کتابخانه زبان های مختلف توجه و نگاه کنید و یا برای ارسال یک درخواست با استفاده از دستور curl یا wget در CLI، شما را راهنمایی میکند.
اگر به فرمت دهی و شکل JSON توجه کنید، میبینید که ابزارهای CLI یک سری پارامترهای مختلف برای کمک کردن به دانلود و چاپ خروجی های string دارد.
ممکن است که پاسخ دهی به رشته بازیابی شده از curl ، طولانی و گیج کننده باشد.از این رو برای کوچکتر کردن لیست نتایج، نیاز است که فرمت دهی JSON تجزیه و فیلتر شود.
این کار به مشاهده نتایج در CLI کمک می کند و داده های قابل پردازش در اسکریپت ها را به حداقل میرساند.
مثال زیر تمام پروژه ها را از گیت لب بازیابی می کند که با توجه به 20 پروژه اول، یک نتیجه صفحه بندی شده را برمیگرداند:
$ curl "https://gitlab.com/api/v4/projects"
مستندسازی REST API ها در گیت لب، در ابتدا شما را به وسیله مدیریت خطا و احراز هویت راهنمایی میکند. در این مقاله ما از یک Access Token شخصی به عنوان متد احراز هویت استفاده کرده ایم. برای احراز هویت خودکار نیز میتوانید از access token های پروژه استفاده کنید چون این نوع توکن ها موقع احراز هویت، به افراد اجازه نمیدهند که از مدارک شخصی استفاده کنند.
احراز هویت REST API
با توجه به این که همه ی نقطه پایان ها به وسیله دسترسی ناشناس یا anonymous access قابل دسترسی نیستند، نیاز است که احراز هویت شوند.
سعی کنید با استفاده از درخواست زیر داده های پروفایل کاربری را واکشی یا fetch کنید:
$ curl "https://gitlab.com/api/v4/user"
{"message":"401 Unauthorized"}
درخواست API در مقابل نقطه پایان user/ ، نیاز دارد که access token شخصی را از یک درخواست ( مثلا درخواست سربرگ)، انتقال دهد و برای جلوگیری از افشا و لو رفتن مدارک در محیط ترمینال، میتوانید آن توکن و مقدارش را به محیط کاربر ارسال کنید. از این رو با استفاده از ZSH و پلاگین env. ،می توانید کار ارسال کردن متغیر را در محیط پوسته خود، خودکار کنید.
همچنین می توانید برای یکبار به env. موجود در محیط پوسته تان، منبع یا سورس بدهید:
$ vim ~/.env
export GITLAB_TOKEN=”...”
$ source ~/.env
اسکریپت ها و کامنت هایی که در پوسته محیط اجرا شده اند، میتوانند به متغیر GITLAB_TOKEN$ مراجعه کنند.
حال با اضافه کردن سربرگ مجوز به درخواست، دوباره سعی کنید نقطه پایان API کاربر را استعلام کنید :
$ curl -H "Authorization: Bearer $GITLAB_TOKEN" "https://gitlab.com/api/v4/user"
به یاد داشته باشید که ادمین ها میتوانند به اطلاعات همه کاربران دسترسی داشته باشند و کاربران نیز فقط میتوانند پروفایل کاربری خودشان را ببینند.
در JSON چگونه به درخواست ها پاسخ داده میشود؟
API های موجود در گیت لب، چندین منبع و نقطه پایان URL فراهم کرده اند. با استفاده از رابط کاربری گرافیکی میتوان هر چیزی که پیکربندی میشود را مدیریت کرد. پس از ارسال درخواست API، یک پیام پاسخ که شامل یک body از نوع string یا متن است، دریافتت میشود. دستور curl می تواند اکثر اطلاعات مربوط به سربرگ پاسخ که برای رفع اشکال مفید است را فراهم کند. سطوح چندگانه verbose، یک خروجی فعال میکند که به وسیله vvv- ، بطور کامل اشکال زادیی یا debug شده است.
$ curl -vvv "https://gitlab.com/api/v4/projects"
[...]
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=gitlab.com
* start date: Jan 21 00:00:00 2021 GMT
* expire date: May 11 23:59:59 2021 GMT
* subjectAltName: host "gitlab.com" matched cert's "gitlab.com"
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
* SSL certificate verify ok.
[...]
> GET /api/v4/projects HTTP/2
> Host: gitlab.com
> User-Agent: curl/7.64.1
> Accept: */*
[...]
< HTTP/2 200
< date: Mon, 19 Apr 2021 11:25:31 GMT
< content-type: application/json
[...]
[{"id":25993690,"description":"project for adding issues","name":"project-for-issues-1e1b6d5f938fb240","name_with_namespace":"gitlab-qa-sandbox-group / qa-test-2021-04-19-11-13-01-d7d873fd43cd34b6 / project-for-issues-1e1b6d5f938fb240","path":"project-for-issues-1e1b6d5f938fb240","path_with_namespace":"gitlab-qa-sandbox-group/qa-test-2021-04-19-11-13-01-d7d873fd43cd34b6/project-for-issues-1e1b6d5f938fb240"
[... JSON content ...]
"avatar_url":null,"web_url":"https://gitlab.com/groups/gitlab-qa-sandbox-group/qa-test-2021-04-19-11-12-56-7f3128bd0e41b92f"}}]
* Closing connection 0
خروجی دستور curl ، دید و نگرش مفیدی را نسبت به نسخه ها و رمزهای TLS ایجاد میکند. خطوط درخواست با > و خطوط پاسخ نیز با < شروع میشوند. String های موجود در body پاسخ، بعنوان JSON رمزگذاری شده اند.
چگونه میتوان ساختار یک JSON برگردانده شده را دید؟
در این قسمت نحوه ساختار فایل های JSON برگردانده شده را بطور کلی مورد بررسی قرار میدهیم :
- از [ … ] برای شناسایی کردن آرایه ها استفاده میشود.
- از { … } برای شناسایی دیکشنری استفاده میشود.
دیکشنری ها به اسم های آرایه های انجمنی، نقشه ها و … هم شناخته شده اند.
- دستور ”key”: value یک جفت key-value را در دیکشنری نشان میدهد که با کاراکترهای ” ” شناسایی می شوند.
JSON شامل چندین نوع متغیر مثل int ،Boolean ،floating و … است که هر کدام به یک شکل خاص شناسایی میشوند.
اگر یک کلید داشته باشیم که نوع متغیر آن تنظیم نشده باشد، معمولا REST API ها آن را بصورت null برمیگردانند.
با اجرا کردن Linters، ساختار داده ها تایید میشود. ماژول Python JSON می تواند JSON string ها را تجزیه و lint کند.
Jq یک پردازنده سبک و انعطاف پذیر CLI است که میتوان از آن به عنوان یک ابزار مستقل برای تجزیه و اعتبارسنجی داده های JSON استفاده کرد.
$ echo '[{"key": "broken"}' | python -m json.tool
Expecting object: line 1 column 19 (char 18)
Jq در پکیج منیجرهای اکثر سیستم عامل ها وجود دارد و به راحتی می توانیم به آنها دسترسی داشته باشیم.
$ curl "https://gitlab.com/api/v4/projects" | jq
[
{
"id": 25994891,
"description": "...",
"name": "...",
[...]
"forks_count": 0,
"star_count": 0,
"last_activity_at": "2021-04-19T11:50:24.292Z",
"namespace": {
"id": 11528141,
"name": "...",
[...]
}
}
]
تاثیر Dive در ساختار داده های JSON
قدرت واقعی jq این است که می توان از آن برای تجزیه داده های JSON استفاده کرد.
نکته:
Jq برای داده های JSON همانند sed است.همچنین مثل sed, awk, grep etc. می تواند slice، فیلتر، نقشه و تبدیل ساختار داده ها را به آسانی انجام دهد و به شما اجازه میدهد که متن ها را دستکاری و ویرایش کنید.
خروجی زیر نشان میده که یک درخواست چگونه میتواند مجددا در برابر API پروژه اجرا شود ولی خروجی آن به jq منتقل شود.
$ echo '[{"key": "broken"}' | jq
parse error: Unfinished JSON term at EOF at line 2, column 0
آرایه ها و دیکشنری ها
مجموعه نتایج API ها، اکثرا به عنوان آیتم و مواردی از یک آرایه بازگردانی میشوند. یک آیتم خودش به تنهایی می تواند یک مقدار یا یک شی JSON باشد.
مثال زیر از پاسخ GitLab API ها پیروی میکند و یک آرایه از دیکشنری ها را به عنوان مجموعه ایی از نتایج تو در تو ایجاد میکند:
$ vim result.json
[
{
"id": 1,
"name": "project1"
},
{
"id": 2,
"name": "project2"
},
{
"id": 3,
"name": "project-internal-dev",
"namespace": {
"name": "EMOJI"
}
}
]
برای چاپ محتوای فایل در Stdout، از دستور cat استفاده میشود. خروجی ساختار داده ، آرایه ایی است که از آن برای دسترسی و چاپ تمام موارد به کمک دستور -c .[ ] استفاده میشود.
$ cat result.json | jq -c '.[]'
{"id":1,"name":"project1"}
{"id":2,"name":"project2"}
{"id":3,"name":"project-internal-dev","namespace":{"name":"EMOJI"}}
فیلتر کردن ساختار داده ها با jq
با انتقال (…) select | به jq میتوان آیتم ها را فیلتر کرد. فیلترها یک تابع بازگشتی lambda را به عنوان یک شرط مقایسه ایی دریافت میکنند. وقتی که آیتم ها با شرایط مطابقت داشته باشند، به جایی که فراخوانی شده اند باز میگردند و برای دسترسی به کلیدهای دیکشنری و مقادیر آنها از علامت . استفاده می شود.
سعی کنید برای همه مواردی که نامشان project2 است، این فیلتر را اعمال کنید:
با توجه به این که همه ی نقطه پایان ها به وسیله دسترسی ناشناس یا anonymous access قابل دسترسی نیستند، نیاز است که احراز هویت شوند.
سعی کنید با استفاده از درخواست زیر داده های پروفایل کاربری را واکشی یا fetch کنید:
$ cat result.json | jq -c '.[] | select (.name == "project2")'
{"id":2,"name":"project2"}