JSON Array برای نمایش مجموعهای مرتب از مقدارها استفاده میشود. فهرست کاربران، نتایج جستجو، آیتمهای سفارش، تگها، مختصات و دادههای سری زمانی معمولاً با Array ساخته میشوند. در ظاهر، Array فقط چند مقدار داخل براکت است؛ اما نوع اعضا، ترتیب، صفحهبندی، Validation، عملکرد و سازگاری نسخهها میتوانند کیفیت کل قرارداد داده را تغییر دهند.
این راهنما JSON Array را از پایه تا کاربرد حرفهای بررسی میکند: Syntax، انواع عضو، Array از Objectها، Array تودرتو، تفاوت با Object، Index، ترتیب، دادههای ناهمگون، Parse و Serialize، Schema، Pagination، امنیت، عملکرد و بهترین روشهای طراحی.
پاسخ سریع: JSON Array فهرستی مرتب از مقدارهاست که داخل براکت نوشته میشود. اعضا با ویرگول جدا میشوند و هر عضو میتواند String، Number، Boolean، null، Object یا Array دیگری باشد.
JSON Array چیست؟
Array ساختاری برای نگهداری چند مقدار در یک ترتیب مشخص است:
[
"json",
"api",
"web"
]
در این نمونه سه String وجود دارد. عضو اول Index صفر، عضو دوم Index یک و عضو سوم Index دو دارد.
ساختار استاندارد JSON Array
[
"value1",
"value2",
"value3"
]
- Array با براکت باز
[شروع میشود. - اعضا میتوانند هر نوع معتبر JSON باشند.
- اعضا با ویرگول جدا میشوند.
- بعد از آخرین عضو ویرگول قرار نمیگیرد.
- Array با براکت بسته
]تمام میشود.
انواع مقدار در Array
| نوع | نمونه |
|---|---|
| String | ["a", "b"] |
| Number | [1, 2, 3] |
| Boolean | [true, false] |
| null | [null, null] |
| Object | [{"id":1}, {"id":2}] |
| Array | [[1,2], [3,4]] |
از نظر Syntax، ترکیب نوعهای مختلف نیز ممکن است:
[
"text",
42,
true,
null,
{"id": 1},
[1, 2, 3]
]
اما معتبر بودن Syntax به معنی طراحی مناسب نیست. Array ناهمگون مصرفکننده را مجبور میکند نوع هر عضو را جداگانه تشخیص دهد.
Array از Objectها
یکی از رایجترین الگوها در API، Array از Objectهاست:
[
{
"id": 1,
"name": "Keyboard",
"price": 895000
},
{
"id": 2,
"name": "Mouse",
"price": 450000
}
]
بهتر است همه Objectهای داخل Array قرارداد یکسانی داشته باشند. نام فیلدها، نوع مقدارها و معنای null باید هماهنگ باشد.
ساختار هماهنگ
[
{
"id": 1,
"name": "Keyboard",
"available": true
},
{
"id": 2,
"name": "Mouse",
"available": false
}
]
ساختار ناسازگار
[
{
"id": 1,
"name": "Keyboard"
},
{
"productCode": "M-2",
"title": "Mouse",
"inStock": "yes"
}
]
Array دوم Parse میشود، اما قرارداد ضعیفی دارد و مصرفکننده مجبور به شرطهای متعدد میشود.
Array تودرتو
[
[1, 2, 3],
[4, 5, 6]
]
این ساختار برای ماتریس، جدول یا مختصات مفید است؛ بااینحال باید طول و معنای هر موقعیت مشخص باشد.
مختصات با Array
[
[35.6892, 51.3890],
[36.2605, 59.6168]
]
مختصات با Object
[
{
"latitude": 35.6892,
"longitude": 51.3890
},
{
"latitude": 36.2605,
"longitude": 59.6168
}
]
Object طولانیتر اما خواناتر است. Array زمانی مناسب است که ترتیب اعضا کاملاً استاندارد و مستند باشد.
تفاوت Array و Object
| ویژگی | Array | Object |
|---|---|---|
| نشانه | [ ] | { } |
| ساختار | فهرست مرتب | کلید و مقدار |
| دسترسی | با Index | با نام کلید |
| کاربرد | چند عضو | یک موجودیت |
| ترتیب | مهم است | نباید مبنای منطق باشد |
Index در JSON Array
JSON فقط ترتیب را نگه میدارد. مفهوم Index هنگام Parse در زبان مقصد استفاده میشود. بیشتر زبانها Index را از صفر شروع میکنند.
[
"first",
"second",
"third"
]
| Index | مقدار |
|---|---|
| 0 | first |
| 1 | second |
| 2 | third |
Index برای موقعیت مناسب است، نه هویت. اگر عضو یک موجودیت واقعی است، id پایدار استفاده کنید.
آیا ترتیب اعضا مهم است؟
بله. برخلاف Object، ترتیب بخشی از معنای Array است.
["admin", "editor"]
["editor", "admin"]
اگر ترتیب در کاربرد شما مهم نیست، قرارداد باید این موضوع را صریح اعلام کند و پیش از مقایسه داده Normalize شود.
Array خالی و null
[]
{
"items": []
}
{
"items": null
}
Array خالی یعنی مجموعه وجود دارد اما عضو ندارد. null معمولاً نبودن مقدار را نشان میدهد. برای فهرستها، [] معمولاً قرارداد سادهتری است؛ زیرا کلاینت بدون null check میتواند روی آن Loop اجرا کند.
Array ناهمگون
[
1,
"two",
true,
{"value": 4}
]
این ساختار معتبر است، اما برای API عمومی معمولاً مناسب نیست. اگر چند نوع عضو لازم است، از Discriminator استفاده کنید:
[
{
"type": "text",
"value": "Hello"
},
{
"type": "image",
"url": "/media/1"
}
]
اعضای تکراری
[
"json",
"api",
"json"
]
JSON عضو تکراری را ممنوع نمیکند. اگر مجموعه باید یکتا باشد، این قانون باید با Schema یا منطق برنامه اعمال شود.
Array در پاسخ API
پاسخ ساده:
[
{"id": 1, "name": "A"},
{"id": 2, "name": "B"}
]
برای افزودن Pagination و Metadata، Envelope مناسبتر است:
{
"items": [
{"id": 1, "name": "A"},
{"id": 2, "name": "B"}
],
"pagination": {
"page": 1,
"pageSize": 20,
"totalItems": 2
}
}
Pagination برای Arrayهای بزرگ
ارسال هزاران عضو در یک پاسخ باعث افزایش زمان انتقال، Parse، Validation و مصرف حافظه میشود.
Page-based Pagination
{
"items": [],
"pagination": {
"page": 3,
"pageSize": 20,
"totalPages": 15
}
}
Cursor-based Pagination
{
"items": [],
"pageInfo": {
"nextCursor": "eyJpZCI6MTAwfQ",
"hasNextPage": true
}
}
Cursor برای دادههای در حال تغییر و فهرستهای بزرگ پایدارتر است، ولی پیادهسازی پیچیدهتری دارد.
Sort و Filter
ترتیب پیشفرض باید مستند باشد. برای Pagination، Sort باید قطعی باشد و در صورت مساوی بودن مقدارها از کلید یکتا استفاده شود.
{
"items": [
{"id": 1, "name": "A"},
{"id": 2, "name": "B"}
],
"sort": {
"field": "name",
"direction": "asc"
}
}
Parse کردن Array در JavaScript
const text = '[{"id":1},{"id":2}]';
try {
const items = JSON.parse(text);
if (!Array.isArray(items)) {
throw new Error("Expected a JSON array");
}
for (const item of items) {
console.log(item.id);
}
} catch (error) {
console.error("Invalid JSON array:", error);
}
ساخت Array در JavaScript
const items = [
{ id: 1, name: "A" },
{ id: 2, name: "B" }
];
const json = JSON.stringify(items, null, 2);
console.log(json);
خواندن Array در Python
import json
text = '[{"id": 1}, {"id": 2}]'
try:
items = json.loads(text)
if not isinstance(items, list):
raise ValueError("Expected a JSON array")
for item in items:
print(item["id"])
except (json.JSONDecodeError, ValueError, KeyError) as error:
print("Invalid JSON array:", error)
Deserialize در C#
using System.Text.Json;
public sealed class ItemDto
{
public int Id { get; init; }
public string Name { get; init; } = string.Empty;
}
var json = "[{\"id\":1,\"name\":\"A\"},{\"id\":2,\"name\":\"B\"}]";
try
{
var items =
JsonSerializer.Deserialize<List<ItemDto>>(json)
?? new List<ItemDto>();
foreach (var item in items)
{
Console.WriteLine(item.Name);
}
}
catch (JsonException exception)
{
Console.WriteLine(exception.Message);
}
JSON Schema برای Array
{
"type": "array",
"minItems": 1,
"maxItems": 100,
"uniqueItems": true,
"items": {
"type": "string",
"minLength": 1
}
}
این Schema نوع ریشه، حداقل و حداکثر تعداد، یکتایی اعضا و نوع هر عضو را کنترل میکند.
Schema برای Array از Objectها
{
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"name": {
"type": "string",
"minLength": 1
}
},
"required": ["id", "name"],
"additionalProperties": false
}
}
Tuple-like Array
[
35.6892,
51.3890
]
این Array کوتاه است، اما بدون مستندات مشخص نیست کدام مقدار latitude و کدام longitude است. Object خواناتر است:
{
"latitude": 35.6892,
"longitude": 51.3890
}
Array Sparse در JSON وجود ندارد
[
"a",
,
"c"
]
این JSON معتبر نیست. برای عضو ناموجود باید null صریح استفاده شود:
[
"a",
null,
"c"
]
Trailing Comma
[
"a",
"b",
]
ویرگول پایانی در JSON استاندارد مجاز نیست.
امنیت Array
Array بسیار بزرگ
مهاجم میتواند Array با تعداد بسیار زیاد عضو ارسال کند. محدودیت اندازه Body، تعداد عضو و زمان پردازش ضروری است.
Validation هر عضو
Validate کردن فقط ریشه کافی نیست. هر Object داخل Array باید نوع، محدوده، طول و مجوز مناسب داشته باشد.
عملیات Batch
{
"userIds": [1, 2, 3, 4]
}
سرور باید برای هر شناسه مجوز را بررسی کند، اندازه Batch را محدود کند و رفتار شکست جزئی را مستند سازد.
افشای داده
Array بزرگ از Objectها ممکن است فیلدهای حساس را برای همه اعضا برگرداند. مدل خروجی باید حداقلی باشد.
عملکرد Arrayهای بزرگ
- مصرف حافظه در Parse کامل
- زمان Serialization
- هزینه انتقال شبکه
- هزینه Validation هر عضو
- زمان Render در Frontend
راهکارهای بهبود
- Pagination یا Cursor
- انتخاب فیلدهای ضروری
- فشردهسازی HTTP
- Streaming برای داده بسیار بزرگ
- Virtualization در رابط کاربری
- Batch Size محدود
Array و Streaming
برای جریانهای بسیار بزرگ، NDJSON یا JSON Lines میتواند مناسبتر باشد:
{"id":1,"name":"A"}
{"id":2,"name":"B"}
{"id":3,"name":"C"}
هر خط مستقل است و جداگانه پردازش میشود. این Format یک Array استاندارد نیست و باید در قرارداد اعلام شود.
Versioning در Array
تغییرهای کمخطر
- افزودن فیلد اختیاری به Objectهای عضو
- افزودن Metadata در Envelope
- افزودن اطلاعات Pagination
تغییرهای پرخطر
- تغییر نوع عضو
- تبدیل Array به Object
- تغییر ترتیب معنایی
- تغییر String به Object
- تبدیل Array خالی به null
["admin", "editor"]
[
{"name": "admin"},
{"name": "editor"}
]
این تغییر معمولاً ناسازگار است و نیاز به نسخه جدید قرارداد دارد.
مقایسه دو Array
[1, 2, 3]
[3, 2, 1]
برابری معمولاً به ترتیب و مقدار اعضا وابسته است. اگر ترتیب بیاهمیت است، قبل از مقایسه Sort یا Normalize انجام شود.
حذف عضو و پایداری Index
حذف یا مرتبسازی Array میتواند Index اعضا را تغییر دهد. برای موجودیتهای واقعی از id پایدار استفاده کنید:
[
{"id": "A-1", "name": "First"},
{"id": "A-2", "name": "Second"}
]
Array برای عملیات Batch
{
"operations": [
{
"type": "update",
"id": 1,
"data": {
"status": "active"
}
},
{
"type": "delete",
"id": 2
}
]
}
در Batch API باید Atomic بودن، ترتیب اجرا، حداکثر تعداد، رفتار شکست جزئی و نتیجه هر عضو مستند شود.
گزارش خطای عضوهای Array
{
"error": {
"code": "VALIDATION_ERROR",
"issues": [
{
"path": "items[0].quantity",
"message": "Quantity must be greater than zero."
},
{
"path": "items[2].productId",
"message": "Product ID is required."
}
]
}
}
Path باید Index عضو و فیلد داخلی را نشان دهد.
اشتباهات رایج
- ویرگول پایانی
- عضو خالی یا Sparse
- Array ناهمگون بدون قرارداد
- استفاده از Index بهعنوان شناسه
- ارسال فهرست بسیار بزرگ بدون Pagination
- تغییر نوع عضو در نسخه جدید
- استفاده از Array وقتی نامگذاری مقدارها مهم است
- نادیده گرفتن ترتیب
- عدم Validation هر عضو
- استفاده از null بهجای Array خالی بدون قرارداد
بهترین روشها
- اعضای Array را تا حد ممکن همنوع نگه دارید.
- برای موجودیتها از Array از Objectهای هماهنگ استفاده کنید.
- ترتیب را مستند کنید.
- برای فهرست خالی از
[]استفاده کنید، مگر قرارداد دیگری دارید. - تعداد اعضا را محدود کنید.
- برای داده بزرگ Pagination یا Streaming داشته باشید.
- هر عضو را با Schema اعتبارسنجی کنید.
- از id پایدار بهجای Index برای هویت استفاده کنید.
- رفتار Batch و شکست جزئی را مستند کنید.
- از Serializer استاندارد استفاده کنید.
چکلیست نهایی
- آیا Array بهترین ساختار برای این داده است؟
- آیا نوع اعضا مشخص و هماهنگ است؟
- آیا ترتیب معنا دارد و مستند شده است؟
- آیا عضو تکراری مجاز است؟
- آیا Array خالی و null تعریف شدهاند؟
- آیا حداکثر تعداد عضو محدود است؟
- آیا هر عضو Validate میشود؟
- آیا Pagination لازم است؟
- آیا id پایدار وجود دارد؟
- آیا تغییرات نسخه جدید سازگارند؟
انتخاب میان Array خالص و Envelope در API
یکی از تصمیمهای مهم در طراحی API این است که پاسخ فهرست مستقیماً Array باشد یا داخل یک Object قرار بگیرد. Array خالص سادهتر و کوتاهتر است:
[
{"id": 1, "name": "A"},
{"id": 2, "name": "B"}
]
اما اگر بعداً به Pagination، تعداد کل، زمان پردازش، لینک صفحه بعد، Warning یا Version نیاز پیدا کنید، باید شکل پاسخ را تغییر دهید. Envelope از ابتدا فضای توسعه بیشتری ایجاد میکند:
{
"items": [
{"id": 1, "name": "A"},
{"id": 2, "name": "B"}
],
"meta": {
"total": 2,
"generatedAt": "2026-08-06T10:30:00Z"
}
}
برای API عمومی یا محصولی که احتمال رشد دارد، Envelope معمولاً انتخاب مطمئنتری است. برای فایل داخلی کوچک یا Endpoint بسیار ساده، Array خالص میتواند کافی باشد.
Array در فرمها و ورودی کاربر
فیلدهای چندمقداری مانند تگها، شمارههای تماس، آیتمهای سفارش و پاسخهای چندانتخابی معمولاً به شکل Array ارسال میشوند:
{
"title": "JSON Guide",
"tags": ["json", "api", "developer-tools"]
}
در این حالت فقط نوع Array کافی نیست. باید قواعدی مانند حداقل و حداکثر تعداد عضو، طول هر String، عضو تکراری و مقدارهای مجاز نیز بررسی شوند. برای مثال، Array دارای هزاران تگ یا String بسیار طولانی میتواند هم خطای منطقی و هم ریسک مصرف منابع ایجاد کند.
Normalize کردن ورودی
در بعضی کاربردها بهتر است پیش از ذخیره، مقدارها Normalize شوند:
- حذف فاصله ابتدا و انتهای String
- یکسانسازی حروف کوچک و بزرگ در دادهای که Case-sensitive نیست
- حذف عضو تکراری براساس قرارداد
- حذف عضو خالی
- مرتبسازی فقط اگر ترتیب معنایی ندارد
این عملیات باید مستند باشد. تغییر خودکار ترتیب در Arrayی که ترتیب آن معنی دارد، داده را خراب میکند.
Array در رابط کاربری و کلید پایدار
در Frontend، فهرستها معمولاً از روی Array Render میشوند. استفاده از Index بهعنوان Key در رابطهای پویا میتواند باعث نمایش اشتباه State شود، چون با حذف یا جابهجایی عضو، Index تغییر میکند.
items.map((item) => (
<Row key={item.id} item={item} />
));
کلید پایدار باید از هویت عضو بیاید، نه موقعیت فعلی آن. Index فقط برای فهرست کاملاً ثابت و بدون افزودن، حذف یا مرتبسازی قابل قبولتر است.
پردازش Array بدون نگهداری نسخه اضافی
در دادههای بزرگ، زنجیره چندین عملیات map، filter و sort ممکن است Arrayهای میانی زیادی ایجاد کند. در بیشتر پاسخهای معمول این موضوع مهم نیست، اما برای صدها هزار عضو باید اندازه و زمان واقعی Benchmark شود.
const activeNames = items
.filter((item) => item.active)
.map((item) => item.name);
برای جریانهای بسیار بزرگ، پردازش مرحلهای، Generator، Stream یا انتقال بخشی از فیلتر به سرور میتواند مصرف حافظه را کاهش دهد. بهینهسازی باید براساس اندازه واقعی داده انجام شود، نه حدس.
آیا Sort کردن Array داده اصلی را تغییر میدهد؟
در برخی زبانها، متد Sort خود Array را تغییر میدهد. اگر ترتیب اصلی اهمیت دارد، باید قبل از Sort نسخه جدید ساخته شود:
const sortedItems = [...items].sort(
(a, b) => a.name.localeCompare(b.name)
);
این نکته در برنامههای State-based مهم است. تغییر مستقیم Array مشترک میتواند باعث باگهای دشوار در Cache، UI یا مقایسه تغییرات شود.
Deduplication در Array از Objectها
حذف عضو تکراری برای Primitiveها سادهتر است، اما برای Object باید معیار یکتایی مشخص شود. دو Object با محتوای مشابه لزوماً از نظر Reference برابر نیستند.
const uniqueById = [
...new Map(items.map((item) => [item.id, item])).values()
];
قبل از Deduplication باید مشخص شود در صورت تکرار id، اولین عضو، آخرین عضو یا خطا انتخاب میشود. در داده مالی یا عملیاتی، حذف خودکار تکرار بدون گزارش ممکن است اطلاعات را پنهان کند.
Array و مقدارهای عددی
Arrayهای عددی در تحلیل داده، نمودار و مختصات رایجاند:
{
"temperatures": [21.4, 22.1, 23.0, 22.7]
}
قرارداد باید واحد، دقت، ترتیب زمانی و رفتار مقدار ناموجود را مشخص کند. استفاده از null برای داده گمشده با صفر یکسان نیست:
{
"temperatures": [21.4, null, 23.0]
}
صفر یک اندازهگیری واقعی است؛ null نبودن اندازهگیری را نشان میدهد. ابزار رسم نمودار و تحلیل باید این تفاوت را بداند.
تست Array در پروژه واقعی
برای یک Endpoint مبتنی بر Array، تستهای زیر ارزش زیادی دارند:
- Array خالی
- یک عضو معتبر
- حداکثر تعداد عضو مجاز
- بیش از حداکثر تعداد
- عضو با نوع اشتباه
- عضو null
- عضو تکراری
- ترتیب غیرمنتظره
- Object عضو با فیلد اجباری حذفشده
- Payload بزرگ و عمیق
تست باید علاوه بر Status Code، مسیر خطا، رفتار Atomic یا Partial Success و ثابت ماندن قرارداد پاسخ را بررسی کند.
جمعبندی
JSON Array ساختاری برای نمایش فهرست مرتب مقدارهاست. اعضای آن میتوانند هر نوع معتبر JSON باشند، اما در طراحی حرفهای بهتر است ساختار اعضا هماهنگ و قابل پیشبینی باشد. ترتیب، Array خالی، null، عضو تکراری، Pagination، Validation و عملکرد باید بخشی از قرارداد باشند.
Array مناسب، داده را ساده و قابل پردازش میکند؛ Array نامناسب میتواند کلاینت را به Type Check، Indexهای ناپایدار و Payloadهای بزرگ وابسته سازد. با Schema، Pagination، id پایدار و قرارداد روشن میتوان JSON Array قابل اعتماد و توسعهپذیر طراحی کرد.