JSON (مخفف JavaScript Object Notation) یک فرمت سبک و مبتنی بر متن برای تبادل دادههاست که برای انسان خوانا و برای ماشینها قابل پردازش است. این فرمت مستقل از زبان برنامهنویسی است و امروزه بهعنوان استانداردی برای تبادل داده بین سرورها و برنامههای کاربردی وب استفاده میشود.
ساختار JSON
JSON از دو ساختار اصلی تشکیل شده است:
| ساختار | توضیح | مثال |
|---|---|---|
| Object | مجموعهای از جفتهای کلید-مقدار که با {} مشخص میشود. | {"name": "Ali", "age": 30} |
| Array | یک لیست مرتب از مقادیر که با [] مشخص میشود. | ["apple", "banana", "cherry"] |
مقادیر در JSON میتوانند از انواع زیر باشند:
-
String: رشته متنی با نقلقول دوگانه (
"Hello") -
Number: عدد (بدون نقلقول) (
42,3.14) -
Boolean:
trueیاfalse -
Null: مقدار خالی (
null) -
Object: شیء تو در تو
-
Array: آرایهای از مقادیر
مثال یک شیء JSON کامل:
{ "name": "John Doe", "age": 35, "isAdmin": true, "address": { "city": "Tehran", "zip": "12345" }, "hobbies": ["reading", "coding", "swimming"], "projects": null }
jq
jq یک ابزار خط فرمان فوقالعاده قدرتمند و سبک برای پردازش JSON است. این ابزار به شما امکان میدهد که دادههای JSON را فیلتر کنید، تغییر دهید، استخراج کنید و به هر شکلی که نیاز دارید، تبدیل کنید. jq از یک زبان پرسوجو (Query Language) خاص خود استفاده میکند که شبیه به Pipeها در شل است.
ساختار کلی:
jq [options] 'filter' [file...]
-
filter: برنامهیjqکه نحوهی تبدیل داده را مشخص میکند. -
اگر فایلی مشخص نشود،
jqداده را از ورودی استاندارد (stdin) میخواند.
نصب:
# در اوبونتو/دبیان sudo apt install jq # در macOS brew install jq # در Arch sudo pacman -S jq
jq پایه و پرکاربرد
۱. jq '.' (Pretty Print)
سادهترین و رایجترین فیلتر، نقطه (.) است که ورودی را بدون تغییر به خروجی میفرستد. کاربرد اصلی آن قالببندی (Pretty Print) و اعتبارسنجی JSON است:
echo '{"name":"Ali","age":30}' | jq '.'
خروجی:
{ "name": "Ali", "age": 30 }
۲. دسترسی به کلیدها (.key یا .["key"])
برای دسترسی به مقدار یک کلید خاص در یک شیء از .key استفاده کنید:
echo '{"name": "Ali", "age": 30}' | jq '.name'
خروجی: "Ali"
اگر نام کلید شامل کاراکترهای خاص (مانند - یا .) باشد، باید از .["key"] استفاده کنید:
echo '{"first-name": "Ali"}' | jq '.["first-name"]'
خروجی: "Ali"
۳. دسترسی به المانهای آرایه (.[index])
برای دسترسی به یک المان خاص در آرایه از .[index] استفاده کنید. ایندکسها از صفر شروع میشوند:
echo '["apple", "banana", "cherry"]' | jq '.[1]'
خروجی: "banana"
برای دریافت همهی المانهای آرایه، ایندکس را خالی بگذارید: .[]:
echo '["apple", "banana", "cherry"]' | jq '.[]'
خروجی:
"apple" "banana" "cherry"
نکته: خروجی در اینجا یک لیست نیست، بلکه سه مقدار JSON جداگانه است که هر کدام در یک خط چاپ میشوند. این مفهوم برای درک Pipe در jq حیاتی است.
فیلترهای پیشرفته و ترکیبی
۱. Pipe (|) در jq
همانند شل، Pipe در jq خروجی فیلتر سمت چپ را به ورودی فیلتر سمت راست میدهد. این قابلیت، هستهی اصلی ترکیب فیلترهاست.
مثال: استخراج username از تمام المانهای یک آرایه:
[ {"username": "alice", "id": 1}, {"username": "bob", "id": 2} ]
jq '.[] | .username' data.json
خروجی:
"alice" "bob"
-
.[]: تمام المانهای آرایه را بهصورت یک جریان (Stream) از دو شیء تولید میکند. -
| .username: هر شیء را به فیلتر.usernameمیدهد وusernameآن را استخراج میکند.
۲. select برای فیلتر کردن شرطی
تابع select برای انتخاب دادههایی که یک شرط را برآورده میکنند استفاده میشود. اگر شرط true باشد، داده را برمیگرداند و در غیر این صورت، هیچچیز (نه null).
مثال: انتخاب کاربرانی که id آنها بزرگتر از ۱ است:
echo '[{"username": "alice", "id": 1}, {"username": "bob", "id": 2}]' | jq '.[] | select(.id > 1)'
خروجی:
{ "username": "bob", "id": 2 }
با ترکیب select و map میتوانید یک آرایهی جدید از نتایج فیلترشده بسازید:
jq 'map(select(.id > 1))'
۳. map برای اعمال تغییرات روی همهی المانها
تابع map یک فیلتر را روی همهی المانهای یک آرایه اعمال میکند و یک آرایهی جدید برمیگرداند.
مثال: تبدیل همهی idها به دو برابر:
echo '[1, 2, 3]' | jq 'map(. * 2)'
خروجی:
[2, 4, 6]
۴. ترکیب select و map برای فیلتر و تغییر
مثال: انتخاب کاربرانی با id بزرگتر از ۱ و استخراج فقط username آنها:
echo '[{"username": "alice", "id": 1}, {"username": "bob", "id": 2}]' | jq 'map(select(.id > 1)) | .[].username'
خروجی: "bob"
گزینههای پرکاربرد jq
| گزینه | توضیح | مثال |
|---|---|---|
-c | خروجی فشرده (Compact) - هر شیء در یک خط | jq -c '.[]' |
-r | خروجی خام (Raw) - خروجی را بدون نقلقول چاپ میکند | jq -r '.name' |
-s | (Slurp) کل ورودی را بهعنوان یک آرایه میخواند | jq -s 'add' |
-n | ورودی نمیخواند و با null شروع میکند | jq -n '42' |
مثال با -r: استخراج username بدون نقلقول
echo '{"username": "alice"}' | jq -r '.username'
خروجی: alice
پردازش JSON از ترمینال: سناریوهای عملی
۱. کار با APIها (استخراج فیلدهای خاص)
فرض کنید خروجی یک API به این شکل است:
{ "response": { "segments": [ {"id": 1, "short_name": "cookie_birthday"}, {"id": 123, "short_name": "creative_macro_test_seg"} ] } }
برای استخراج id و short_name از همهی segmentsها:
curl -s 'https://api.example.com/segment' | jq '.response.segments[] | {id, short_name}'
این یک الگوی بسیار رایج در کار با APIهاست. خروجی:
{"id": 1, "short_name": "cookie_birthday"} {"id": 123, "short_name": "creative_macro_test_seg"}
۲. محاسبات روی دادههای JSON
jq از عملیات ریاضی نیز پشتیبانی میکند:
-
جمع کردن اعداد یک آرایه:
echo '[1, 2, 3, 4]' | jq 'add'
خروجی:
10 -
میانگین گرفتن:
echo '[1, 2, 3, 4]' | jq 'add / length'
خروجی:
2.5
۳. تغییر نام کلیدها در یک آرایه
فرض کنید میخواهید کلید Cities را به City تغییر دهید و ساختار را حفظ کنید:
ورودی:
{ "Country": "India", "States": [ {"Name": "TN", "Cities": ["city1", "city2"]}, {"Name": "KL", "Cities": ["city3", "city4"]} ] }
راهحل با jq:
jq '.States[] |= {Name, City: .Cities}' data.json
-
.States[] | =: برای هر المان آرایه، مقدار را با یک شیء جدید جایگزین کن. -
{Name, City: .Cities}: یک شیء جدید با کلیدName(با همان مقدار قبلی) و کلید جدیدCity(با مقدار.Cities) بساز.
خروجی:
{ "Country": "India", "States": [ {"Name": "TN", "City": ["city1", "city2"]}, {"Name": "KL", "City": ["city3", "city4"]} ] }
۴. ادغام چند فایل JSON
با استفاده از --slurp میتوانید چند فایل JSON را بهعنوان یک آرایه خوانده و آنها را ادغام کنید:
jq -s 'add' file1.json file2.json
اگر هر دو فایل شامل یک آرایه باشند، add آنها را بههم میچسباند.
خلاصه و نکات کلیدی
-
JSON یک فرمت استاندارد برای تبادل داده است که از شیءها (
{}) و آرایهها ([]) تشکیل شده است. -
jqیک پردازشگر قدرتمند خط فرمان برای JSON است و تقریباً روی همهی سیستمها در دسترس است. -
فیلتر
.برای Pretty Print و اعتبارسنجی استفاده میشود. -
فیلترهای دسترسی:
.keyبرای شیءها و.[index]برای آرایهها. -
پایپ (
|) درjqبرای زنجیرهسازی فیلترها استفاده میشود و هستهی اصلی زبانjqاست. -
selectبرای فیلتر کردن دادهها بر اساس شرایط وmapبرای اعمال تغییرات روی همهی المانهای یک آرایه استفاده میشود. -
گزینههای
-r(خروجی خام) و-c(فشرده) پرکاربردترین گزینهها در اسکریپتنویسی و پردازش داده هستند.