Skip to content
العودة إلى المدوّنة
دروس تعليمية

تسطيح JSON المتداخل إلى CSV: ٥ استراتيجيات ومصفوفة قرار

سطّح JSON المتداخل إلى CSV بخمس استراتيجيات: تدوين نقطي ومصفوفات مفهرسة وتوسيع صفوف وStringify. مصفوفة قرار لـ Excel وPandas وBigQuery.

12 دقائق للقراءة

كيف تُسطّح JSON المتداخل إلى CSV: ٥ استراتيجيات ومصفوفة قرار

مشكلة الهندسة الشكلية

تصطدم بالجدار نفسه في كل مرة. واجهة برمجية تُعيد JSON متداخلًا، والمحلل على Slack يريد جدول بيانات وحسب. أداة mongoexport تُنتج أغلفة $oid وثلاث طبقات من البيانات الوصفية، وBigQuery ينتظر جدولًا مسطّحًا. تسطيح JSON المتداخل إلى CSV ليس مشكلة في النحو، بل مشكلة في الهندسة الشكلية. JSON شجرة، وCSV شبكة، ولا يمكنك نقل شجرة إلى شبكة دون أن تختار كيف تنطوي الأغصان.

ثمة خمس استراتيجيات انطواء لا غير. اختر الخاطئة منها فترسل ٢٠٠ عمود إلى Excel، أو تفقد دقة معرّف على Twitter، أو تُعطّل الرحلة الذهاب‑والإياب التي يعتمد عليها خط الإنتاج لديك. اختر الصحيحة منها فيصبح التحويل سطرًا واحدًا.

الاستراتيجيةالسطر الواحدالأنسب لـ
التدوين النقطيcustomer.address.cityتحليل Excel/Sheets
التسطير السفليcustomer_address_cityأعمدة مناسبة لـ SQL
المصفوفات المفهرسةitems.0.sku, items.1.skuالمصفوفات ثابتة الحجم
توسيع الصفوفتكرار الأب لكل ابنتحليلات Pandas/BigQuery
Stringify"{\"city\":\"Seattle\"}" في خلية واحدةرحلة ذهاب‑وإياب بلا فقد

يشرح هذا الدليل الاستراتيجيات الخمس، ومصفوفة قرار مفتاحها المستهلِك (Excel وPandas وBigQuery وPostgres)، وأربع حمولات حقيقية ليست فيها الاستراتيجية الصحيحة هي الواضحة. وللاطلاع على نظرة ثنائية الاتجاه (مكتبات التحليل والبث المتدفق ومزالق الترميز)، راجع دليل تحويل CSV إلى JSON.

لماذا لا يتسع CSV لـ JSON المتداخل

يحمل JSON ثلاثة أنواع من البنية يفتقر إليها CSV. التراتبية هي كائن داخل كائن. التسلسل هو مصفوفة. الخليط هو الاجتماع: مصفوفات من كائنات، وكائنات فيها مصفوفات، ومصفوفات من مصفوفات. وأي طلب تجارة إلكترونية اعتيادي يجمع الثلاثة دفعة واحدة.

لـ CSV بُعدان لا ثالث لهما: صفوف وأعمدة. ليس ثمة محور ثالث يقول “هذا العمود يحوي ثلاثة أبناء”. وحين تطلب شبكة من شجرة، فلا بد أن يتنازل شيء. إما أن تنشر الأبناء عبر مزيد من الأعمدة (وتتعايش مع أسماء من قبيل items.0.options.0.value)، أو تنشرهم عبر مزيد من الصفوف (مع تكرار حقول الأب)، أو تحشرهم في خلية واحدة بصيغة نص وتكفّ عن معاملتهم كبنية.

كل استراتيجية أدناه تجيب عن هذا السؤال بطريقة مختلفة. بعضها يحافظ على قابلية القراءة ويُضحّي بسلامة الذهاب‑والإياب، وبعضها العكس. لا واحدة منها كونية. وفّق الإجابة لمن سيقرأ الملف تاليًا.

مقارنة بين الاستراتيجيات الخمس للتسطيح

الاستراتيجية ١: التدوين النقطي (customer.address.city)

يسير التدوين النقطي من الجذر إلى الورقة، ويستخدم . لوصل المفاتيح. يصبح كل كائن متداخل عمودًا لكل ورقة، ويُدمج المسار في اسم العمود.

{ "customer": { "address": { "city": "Seattle" } }, "email": "alice@example.com" }

يتحول إلى

customer.address.city,email
Seattle,alice@example.com

في Pandas، يكفي سطر واحد:

import pandas as pd

data = [{"customer": {"address": {"city": "Seattle"}}, "email": "alice@example.com"}]
df = pd.json_normalize(data, sep='.')
df.to_csv("out.csv", index=False)

وفي JavaScript، تكفي دالة تكرارية صغيرة:

function flattenDot(obj, prefix = '', acc = {}) {
  for (const [k, v] of Object.entries(obj)) {
    const key = prefix ? `${prefix}.${k}` : k;
    if (v && typeof v === 'object' && !Array.isArray(v)) {
      flattenDot(v, key, acc);
    } else {
      acc[key] = v;
    }
  }
  return acc;
}

المزايا: قابل للقراءة البشرية، وهو الافتراضي في Pandas، ويُبقي على المسار الأصلي. العيوب: قد تطول أسماء الأعمدة (تُنتج مواصفات Kubernetes أسماء مثل spec.template.spec.containers.0.resources.limits.memory)، وتصير النقطة ملتبسة إذا احتوى مفتاح فعلي على . (وهو حال معاملات الأحداث في Google Analytics 4).

الاستراتيجية ٢: تدوين التسطير السفلي (customer_address_city)

الفكرة ذاتها بفاصل مختلف. استبدل . بـ _ فتحصل على نتيجة آمنة في SQL: SELECT customer_address_city FROM events يعمل دون تنصيص المعرّف. BigQuery وSnowflake وPostgres كلها تُفضّل ذلك.

import pandas as pd
df = pd.json_normalize(data, sep='_')

القرار بين النقطة والتسطير السفلي يتعلق فقط بالأداة المستهلكة. محللو Excel يقرؤون النقطة أيسر، ومحركات SQL تقبل التسطير السفلي بلا اعتراض. يكفي تغيير وسيط واحد للتبديل بينهما.

المزايا: أسماء أعمدة آمنة في SQL، ومعرّفات متوافقة مع BigQuery، ولا حاجة للتنصيص. العيوب: يبقى الالتباس قائمًا إن احتوى المفتاح على _ (أقل شيوعًا من . لكنه وارد).

الاستراتيجية ٣: المصفوفات المفهرسة (items.0.sku، items.1.sku)

الكائنات تنبسط بسلاسة لأن مفاتيحها فريدة، أما المصفوفات فلا، لأن طولها غير محدود. تُعامل استراتيجية الفهرسة مواضع المصفوفة قطعًا من المسار: يصبح items[0] هو items.0.

{ "id": "ord-001", "items": [{"sku": "A"}, {"sku": "B"}] }

يتحول إلى

id,items.0.sku,items.1.sku
ord-001,A,B

هذا هو السلوك الافتراضي لوضع التسطيح في محوّل JSON إلى CSV لدينا. لكل ورقة عمودها الخاص، ويُحفظ الموضع في الاسم.

المزايا: كل قيمة تحصل على خليتها، ويُحفظ الموضع، ولا تكرار للصفوف. العيوب: ينفجر عدد الأعمدة (١٠٠ عنصر = ١٠٠ عمود)؛ والصفوف ذات أطوال المصفوفات المتفاوتة تُنتج جداول مهلهلة؛ ويتعطّل التجميع لاحقًا (لا يصلح SUM(items.*.qty)).

الاستراتيجية ٤: توسيع الصفوف (مصفوفة إلى صفوف متعددة)

بدلًا من توسيع الجدول ليتسع للمصفوفة، طوّله. كرّر حقول الأب مرة لكل عنصر من المصفوفة، ودَع كل عنصر يصبح صفًا مستقلًا.

{ "order_id": "ord-001", "customer": "Alice", "items": [{"sku": "A", "qty": 2}, {"sku": "B", "qty": 1}] }

يتحول إلى

order_id,customer,items.sku,items.qty
ord-001,Alice,A,2
ord-001,Alice,B,1

في Pandas، يقوم سطر واحد بالتوسيع والتطبيع معًا:

import pandas as pd

orders = [{"order_id": "ord-001", "customer": "Alice",
           "items": [{"sku": "A", "qty": 2}, {"sku": "B", "qty": 1}]}]
df = pd.json_normalize(orders, record_path='items', meta=['order_id', 'customer'])
df.to_csv("orders.csv", index=False)

وفي SQL، يفعل UNNEST الشيء نفسه:

SELECT order_id, item.sku, item.qty FROM orders, UNNEST(items) AS item;

المزايا: يتعامل Pandas وBigQuery مع هذا الشكل مباشرة، والتجميعات تنجح (GROUP BY order_id)، ويبقى المخطط ضيقًا. العيوب: تتكرر حقول الأب في كل صف ابن (تضخّم في التخزين)، وحد العلاقة من واحد إلى متعدد ضمني (تحتاج إلى order_id)، ومصفوفتان في المستوى نفسه تُنتجان حاصل ضرب ديكارتيًا ما لم تُفكّكهما بحذر بـ UNNEST.

الاستراتيجية ٥: Stringify (JSON داخل خلية)

الخيار الجذري: لا تُسطّح أصلًا. سلسِل القيمة المتداخلة كاملةً كنص JSON، وضعها في خلية واحدة. يبقى الجدول الخارجي مسطّحًا، وتُحفظ البنية حرفيًا في الداخل.

{ "id": "ord-001", "items": [{"sku": "A"}, {"sku": "B"}] }

يتحول إلى

id,items
ord-001,"[{""sku"":""A""},{""sku"":""B""}]"

هذا هو وضع Stringify في محوّل JSON إلى CSV لدينا. عدد الأعمدة لا ينفجر، ويُحفظ الشكل الأصلي بايتًا ببايت، ويعيد الاتجاه العكسي بناء المدخل بحذافيره.

المزايا: بلا فقد ١٠٠٪، وعدد الأعمدة متوقَّع، وآمن للذهاب‑والإياب حين يقترن باستنباط الأنواع في الاتجاه العكسي. العيوب: يرى مستخدمو Excel علامات اقتباس مهرّبة، وتحتاج محركات SQL إلى دوال JSON للاستعلام داخل القيمة (JSON_EXTRACT_SCALAR في BigQuery، و->>'key' في Postgres)، ولا تستطيع صيغ جداول البيانات الوصول داخل الخلية.

الاستراتيجيات الخمس جنبًا إلى جنب

المدخل ذاته عبر الخمس جميعًا: {"id":"ord-001","customer":{"name":"Alice"},"items":[{"sku":"A","qty":2},{"sku":"B","qty":1}]}.

الاستراتيجيةالأعمدةآمنة للذهاب‑والإيابالمستهلِك الأنسب
التدوين النقطيتنمو مع المصفوفةلامحلل Excel
التسطير السفليتنمو مع المصفوفةلامستودع SQL
المصفوفات المفهرسةاثنان لكل خانة مصفوفةلا (التباس عند العكس)المصفوفات ثابتة الحجم
توسيع الصفوفضيقة، صف لكل ابنجزئية (تحتاج مفتاحًا)Pandas / BigQuery
Stringifyثابتةنعمالذهاب‑والإياب في خط الإنتاج

مصفوفة القرار: أي استراتيجية لأي مستهلِك

المستهلِكالاستراتيجية الموصى بهالماذا
Excel / Sheets (محلل)نقطي + Stringify للمصفوفات الكبيرةأسماء أعمدة قابلة للقراءة؛ المصفوفات الكبيرة لا تُفجّر الورقة
Excel-EU (DE/FR/IT/ES)نقطي + فاصل ; + UTF-8 BOMالفاصلة المنقوطة لازمة؛ وBOM يمنع تشوّه الترميز
Pandas (json_normalize + explode)تسطير سفلي + توسيع صفوفأعمدة صديقة لـ SQL؛ والتوسيع يتجاوب مع groupby
BigQuery / SnowflakeTSV + Stringify أو توسيعاعتماد علامة الجدولة يُجنّب فخاخ التنصيص؛ وJSON_EXTRACT يستعلم داخل الخلية
PostgreSQL COPYRFC 4180 + تسطير سفلي + مسطّحأعمدة آمنة في SQL؛ وتنصيص RFC صارم
MongoDBBigQuery ETLحمّل NDJSON مباشرة وتجاوز CSVBigQuery يُحمّل NDJSON مباشرة؛ وCSV طريق التفاف

Excel / Google Sheets: فخ اللغة المحلية

ليس لطول أسماء أعمدة Excel حد عملي. الفخاخ الحقيقية ثلاثة.

أولًا، الانقسام بحسب اللغة المحلية. Excel الأوروبي (ألمانيا وفرنسا وإيطاليا وإسبانيا) ينتظر ; فاصلًا، لأن , فاصل عشري. يفتح ملف CSV المفصول بفواصل وكل صف منهار في العمود A. الإعداد المسبق Excel في أداتنا json-to-csv يُبدّل إلى ; + CRLF + UTF-8 BOM بنقرة واحدة.

ثانيًا، الترميز العلمي. يرى Excel الرقم 9007199254740993 ويعرضه 9.00719925474E+15. خزّن الأعداد الصحيحة الكبيرة كنصوص في JSON المصدر، وفعّل BOM ليُبقي Excel الخلية نصًا. ومحوّلنا يكتشف الأعداد الصحيحة الكبيرة تلقائيًا.

ثالثًا، الحد العملي للأعمدة. يدعم Excel نظريًا ١٦٬٣٨٤ عمودًا، لكن ما يتجاوز ٥٠٠ تقريبًا يصير عسير الإدارة. سلسِل الفروع الثقيلة، أو اعرض مسبقًا بـ jq قبل التحويل.

Pandas: json_normalize + explode

النمط القياسي للمصفوفات المتداخلة هو record_path + meta في تمرير واحد:

import pandas as pd

orders = [{
    "order_id": "ord-001",
    "customer": {"name": "Alice", "city": "Seattle"},
    "items": [{"sku": "SKU-100", "qty": 2}, {"sku": "SKU-205", "qty": 1}]
}]

df = pd.json_normalize(orders, record_path='items',
    meta=['order_id', ['customer', 'name'], ['customer', 'city']], sep='_')
df.to_csv("orders.csv", index=False)

الناتج صف لكل عنصر مع تكرار order_id وcustomer_name وcustomer_city. وهذا أفضل من تشغيل explode أولًا ثم json_normalize لاحقًا: فـ record_path يتجاوز عمود الكائن الوسيط، وmeta يتيح لك التحكم في حقول الأب التي تنتشر. وللمدخلات التي تحوي عناصرها كائنات متداخلة، اضبط max_level= لتحديد العمق.

BigQuery / Snowflake: TSV + JSON داخل الخلية

أمر LOAD DATA في BigQuery صارم في تنصيص CSV، وكثيرًا ما يُسيء قراءة الملفات التي تحوي فواصل داخل نصوص منصَّصة. TSV أأمن لأن علامة الجدولة لا تظهر تقريبًا داخل الحقول النصية:

bq load --source_format=CSV --field_delimiter='\t' \
  dataset.orders gs://bucket/orders.tsv \
  order_id:STRING,customer:STRING,items:STRING

وحين تُحمّل بيانات متداخلة على هيئة JSON مُسلسَل في عمود واحد، يظل BigQuery قادرًا على الاستعلام داخلها بـ JSON_EXTRACT_SCALAR:

SELECT order_id, JSON_EXTRACT_SCALAR(items, '$[0].sku') AS first_sku
FROM dataset.orders;

وSnowflake يوفّر القدرة نفسها عبر VARIANT، مع استعلامات مسار مثل items:0.sku::STRING. وفي كلا المحركَين، يتفوّق Stringify مع استعلامات مسارات JSON على التسطيح الكامل حين تكون المصفوفات المتداخلة كبيرة أو متفاوتة الطول.

PostgreSQL COPY: التزام صارم بـ RFC 4180

COPY ... FROM ... WITH (FORMAT csv, HEADER true) هو أصرم قارئ RFC 4180 ستلتقيه عمليًا. ثمة سلوكان يُعثران الناس.

أولًا، لا يقبل COPY UTF-8 BOM. تصير علامة ترتيب البايتات بادئة حرفية على اسم العمود الأول (id بدلًا من id)، فيفشل كل استعلام يُشير إلى id بصمت. عطّل BOM لأهداف Postgres.

ثانيًا، لا يستطيع COPY تحليل البيانات المتداخلة من تلقاء نفسه. إما أن توسّع المصفوفات إلى صفوف متعددة قبل التحميل، وإما أن تُعرّف الوجهة بنوع jsonb وتسلسل القيمة المتداخلة:

CREATE TABLE orders (order_id text PRIMARY KEY, customer text, items jsonb);
COPY orders FROM '/tmp/orders.csv' WITH (FORMAT csv, HEADER true);
SELECT order_id, items->0->>'sku' AS first_sku FROM orders;

ولخطوط الإنتاج التي تتحدث JSON من طرف إلى طرف، تخطّ CSV واستخدم COPY ... FROM ... WITH (FORMAT text) مع مدخلات سطر‑JSON بدلًا منه.

جولات على حمولات من الواقع

الجولة ١: طلبات التجارة الإلكترونية (عميل + مصفوفة عناصر)

طلب اعتيادي يجمع معلومات عميل متداخلة مع مصفوفة عناصر متفاوتة الطول:

[{ "id": "ord-001",
   "customer": { "name": "Alice", "address": {"city": "Seattle", "country": "US"} },
   "items": [{"sku": "SKU-100", "qty": 2}, {"sku": "SKU-205", "qty": 1}] }]

الاستراتيجية الصحيحة تتوقف على من يقرأ الملف. المالية تريد صفًا لكل عنصر لحساب الإيراد لكل SKU؛ وتلك هي استراتيجية التوسيع، فتُنتج صفين مع تكرار id وcustomer.name. والعمليات تريد صفًا لكل طلب لأجل لوحات التنفيذ؛ وذلك بالتدوين النقطي مع Stringify لـ items كي لا تنفجر المصفوفة في عدد الأعمدة. المدخل ذاته ومخرجان مختلفان، وكلاهما صحيح لمستهلكه.

جرّب مباشرة: ألصق الحمولة في محوّل JSON إلى CSV وبدّل بين التسطيح وStringify في خيار التداخل. مثال “Nested E-commerce Orders” يُحمّل الشكل نفسه.

الجولة ٢: واجهة قضايا GitHub البرمجية (مصفوفة وسوم + كائن مستخدم)

تُعيد نقطة النهاية /repos/{owner}/{repo}/issues شكلًا متداخلًا مختلطًا:

[{ "id": 1001, "title": "Bug: login 404", "state": "open",
   "labels": ["bug", "priority:high"], "user": {"login": "alice"} }]

user كائن فيه حقل واحد مفيد، وlabels مصفوفة نصوص غير محدودة الطول. التسطيح الواقعي هجين: تدوين نقطي على user (يهمّك user.login فقط)، ودمج labels داخل خلية واحدة مفصولة بـ ;:

id,title,state,labels,user.login
1001,Bug: login 404,open,bug;priority:high,alice

لا تستطيع التقاط “ضم المصفوفات في خلية” و”تسطيح الكائنات بنقاط” في استراتيجية واحدة. محوّلنا يُسطّح الكائنات تلقائيًا؛ عالج الوسوم مسبقًا بـ jq (map(.labels = (.labels | join(";")))) أو اقبل السلوك الافتراضي لـ Stringify المصفوفات.

الجولة ٣: MongoDB mongoexport ($oid + بيانات وصفية)

تُنتج mongoexport --jsonArray أغلفة JSON الموسّع:

[{ "_id": {"$oid": "6634a1b2c3d4e5f600000001"},
   "email": "alice@example.com",
   "metadata": { "signupDate": "2026-01-15T10:30:00Z",
                 "preferences": {"newsletter": true, "theme": "dark"} } }]

غلاف $oid يُنتج عمودًا اسمه حرفيًا _id.$oid، وأكثر محركات SQL ترفضه. عالج مسبقًا بـ jq لفك الغلاف:

mongoexport --collection=users --jsonArray | jq 'map(._id = ._id."$oid")' > users.json

أما الكتلة المتداخلة بعمق metadata.preferences، فاختر بحسب المستهلِك. تصدير للمحلل: سطّح كل شيء نقطيًا؛ metadata.preferences.theme يُقرأ على ما يرام. ذهاب‑وإياب لخط الإنتاج: سلسل metadata لإبقاء البنية سليمة. وللاطلاع على أنماط jq الكاملة التي تقترن بخطوط أنابيب CSV، راجع مرجع jq السريع.

الجولة ٤: مواصفات Pod في Kubernetes (متداخل بعمق)

استجابة kubectl get pod -o json أسوأ حالة للاستراتيجيات المسطّحة. البنية تذهب روتينيًا ست طبقات في العمق (spec.template.spec.containers.0.resources.limits.memory). والتسطيح النقطي الساذج يُنتج أسماء أعمدة تتجاوز ٧٠ حرفًا و٢٠٠+ عمود من الناتج. تنفع استراتيجيتان.

اعرض مسبقًا بـ kubectl jsonpath. اختر فقط الحقول التي تحتاجها فعلًا:

kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[0].image}{"\t"}{.status.phase}{"\n"}{end}' > pods.tsv

سلسل spec وسطّح metadata. أبقِ metadata (الاسم وفضاء الأسماء والوسوم) مسطّحًا، وسلسل spec في خلية واحدة:

kubectl get pods -o json | jq 'map({name: .metadata.name, namespace: .metadata.namespace, spec: (.spec | tostring)})'

ثم ألصق في المحوّل بوضع التسطيح. يصير عمود spec خلية JSON واحدة، وتبقى أعمدة metadata قابلة للقراءة. تجنّب النمط المضاد kubectl get pod -o json | json-to-csv flatten بلا عرض مسبق؛ سيكون عدد الأعمدة عصيًا على الإدارة.

سلامة الذهاب‑والإياب: التسطيح يفقد، وStringify لا يفقد

التدوين النقطي والتسطير السفلي والمصفوفات المفهرسة وتوسيع الصفوف، جميعها إسقاطات أحادية الاتجاه. متى سطّحت بأيٍّ منها، لا يمكن إعادة بناء JSON الأصلي بدقة من CSV وحده.

الأمثلة المضادة سهلة التركيب. عمود اسمه customer.address.city ملتبس بين {"customer": {"address": {"city": "..."}}} و{"customer": {"address.city": "..."}}. والمصفوفات المفهرسة تبدو عكوسة، لكن CSV لا يستطيع أن يُقرّر هل ينبغي أن يُعيد items.0.sku بناء مصفوفة أم كائنًا بمفتاح رقمي. وتوسيع الصفوف يحتاج إلى مفتاح تجميع؛ بلا order_id لا يمكنك تحديد الصفوف التي تنتمي إلى الأب نفسه.

Stringify وحده يصمد في الذهاب‑والإياب. تُحفظ القيمة المتداخلة حرفيًا كنص JSON، فيقرأ المحوّل العكسي الخلية ويُحلّلها ويُعيد إدراج الأصل سليمًا. حوّل بـ Stringify، واحفظ CSV، وألصق في محوّل CSV إلى JSON، وفعّل استنباط الأنواع، فتحصل على بايتات مطابقة للمدخل.

القاعدة العملية: ذهاب‑وإياب في خط إنتاج ← Stringify. تحليل لقطة واحدة أو تقارير ← نقطي أو تسطير سفلي أو توسيع بحسب المستهلِك.

القيام به في أداتنا داخل المتصفح

محوّل JSON إلى CSV يكشف اثنتين من الاستراتيجيات الخمس مباشرة: التسطيح (يجمع التدوين النقطي والمصفوفات المفهرسة) وStringify (الحفاظ على البنية داخل الخلية). والثلاث الأخرى (التسطير السفلي وتوسيع الصفوف والإعدادات المسبقة المستهدفة لـ SQL) تبعد خطوة معالجة مسبقة واحدة.

تستغرق جلسة اعتيادية خمس نقرات:

  1. صادق على المدخل بـ منسق JSON كي لا تصير الأخطاء النحوية إخفاقات تحويل صامتة.
  2. ألصق JSON في محوّل JSON إلى CSV. يجري التحويل فورًا.
  3. اضبط التداخل على تسطيح للحصول على مفاتيح منقّطة ومُفهرسة، أو Stringify لإبقاء المصفوفات والكائنات في خلايا مفردة.
  4. اختر إعدادًا مسبقًا: RFC 4180 لخطوط الإنتاج، وExcel لجداول البيانات الأوروبية، وTSV للمستودعات، وPipe للنصوص الكثيرة الفواصل.
  5. انقر تبديل الاتجاه واستخدم محوّل CSV إلى JSON مع تفعيل استنباط الأنواع للتحقق من ذهاب‑وإياب Stringify.

كل شيء يجري في متصفحك. لا تغادر معلوماتك الشخصية أو الصادرات الداخلية أو أسرار الإنتاج الصفحة؛ ولا تُوجَّه أي طلبات شبكية بعد تحميل الصفحة. آمن للبيانات الحساسة حين لا يكون رفعها إلى موقع خارجي خيارًا.

مزالق شائعة

ستة أنماط فشل تتكرر:

  1. انفجار أسماء الأعمدة. تُنتج مواصفات Kubernetes وخيوط مراجعة طلبات السحب على GitHub مئات من مسارات الأوراق. الحل: اعرض مسبقًا بـ jq أو kubectl jsonpath، أو سلسل الفروع الثقيلة مع تسطيح البيانات الوصفية.
  2. عدم تطابق طول المصفوفة. الصف ١ فيه ٣ عناصر، والصف ٢ فيه ٥. المصفوفات المفهرسة تُنتج خلايا فارغة في items.3.sku وitems.4.sku للصف ١. الحل: انتقل إلى توسيع الصفوف.
  3. مفاتيح الفهرسة تُعامل كنصوص عند العكس. حين يرى محوّل CSV إلى JSON items.0.sku، فإن 0 فنيًا مفتاح نصي. بعض المحوّلات العكسية تُعيد بناء {"0": {"sku": "A"}} بدلًا من [{"sku": "A"}]. الحل: استخدم Stringify للرحلات ذهابًا وإيابًا.
  4. مفاتيح تحوي الفاصل أصلًا. أحداث GA4 فيها مفاتيح من قبيل event_params.key تحوي نقاطًا حرفية؛ التسطيح بـ . يُنتج مسارات ملتبسة. الحل: استخدم التسطير السفلي، أو أعد تسمية المفاتيح المُربكة. راجع دليل تنسيق JSON5 وJSONC لخلفية عن صيغ JSON بدعم موسّع للمفاتيح.
  5. أنواع مختلطة المستوى. بعض الصفوف فيها address كائنٌ، وأخرى null. التسطيح يُنتج خلايا فارغة حيث كان الكائن null. ملاحظة المخطط التحذيرية في محوّلنا تنبهك حتى تتحقق من المستهلِك التالي.
  6. أعداد صحيحة كبيرة يقطعها Excel. قيمة $oid طويلة، أو معرّف snowflake على Twitter، أو resourceVersion في K8s، يتجاوز نطاق JavaScript الآمن (٢^٥٣ - ١) فيُقرَّب بصمت. ثم يعرضها Excel 9.00719925474E+15. الحل: خزّن المعرّفات كنصوص في JSON المصدر، وفعّل BOM، واستخدم الإعداد المسبق Excel.

الأسئلة الشائعة

ما أفضل طريقة لتسطيح JSON المتداخل إلى CSV؟

أفضل طريقة لتسطيح JSON المتداخل إلى CSV تتوقف على المستهلِك التالي. استخدم التدوين النقطي لـ Excel أو Google Sheets. استخدم توسيع الصفوف حين يُجمّع Pandas أو BigQuery البيانات. استخدم Stringify حين يلزم أن يعود CSV ذهابًا وإيابًا إلى JSON بلا فقد بيانات. وفّق الاستراتيجية مع القارئ التالي.

كيف أحوّل مصفوفة JSON إلى صفوف CSV متعددة؟

حوّل مصفوفة JSON إلى صفوف CSV متعددة باستخدام استراتيجية التوسيع: كرّر حقول الأب مرة لكل عنصر من المصفوفة كي يصير كل عنصر صفه. في Pandas، pd.json_normalize(data, record_path='items', meta=['order_id']) يفعل ذلك باستدعاء واحد. وفي SQL، UNNEST(items) يُنتج الشكل نفسه. تتكرر مفاتيح الأب عبر الصفوف الموسّعة.

هل يمكنني أن أعود ذهابًا وإيابًا بـ CSV إلى JSON المتداخل الأصلي؟

العودة ذهابًا وإيابًا بـ CSV إلى JSON المتداخل الأصلي تنجح فقط مع وضع Stringify. التدوين النقطي والتسطير السفلي والمصفوفات المفهرسة وتوسيع الصفوف إسقاطات فاقدة أحادية الاتجاه؛ ولا يستطيع المحوّل العكسي إعادة بناء الشجرة بدقة. Stringify يحفظ المصفوفات والكائنات بصيغة JSON داخل خلية واحدة، فتكون الرحلة الكاملة مطابقة بايتًا ببايت حين يكون استنباط الأنواع مفعّلًا.

لماذا يعرض Excel JSON المسطَّح لديّ كعمود واحد طويل؟

يعرض Excel JSON المسطَّح لديك كعمود واحد طويل حين تكون في لغة محلية أوروبية (ألمانيا أو فرنسا أو إيطاليا أو إسبانيا) إذ تُحجز الفاصلة للكسور العشرية وينتظر Excel الفاصلة المنقوطة فاصلًا. الإعداد المسبق Excel في json-to-csv يُبدّل إلى ; + CRLF + UTF-8 BOM بنقرة واحدة.

هل أستخدم التدوين النقطي أم التسطير السفلي لأسماء الأعمدة؟

استخدم التدوين النقطي حين يكون الهدف Excel أو Google Sheets أو Pandas؛ النقاط هي افتراضي json_normalize وتُقرأ بسلاسة. استخدم التسطير السفلي حين يكون الهدف SQL: Postgres وBigQuery وSnowflake تستلزم تنصيصًا حول المعرّفات التي تحوي نقاطًا، بينما يُقبل التسطير السفلي بلا تنصيص في كل مكان.

كيف يتعامل pandas json_normalize مع مصفوفات الكائنات؟

يتعامل json_normalize في Pandas مع مصفوفات الكائنات عبر وسيطَي record_path وmeta. pd.json_normalize(data, record_path='items', meta=['order_id']) يُفجّر items إلى صف لكل عنصر مع تكرار order_id. وللكائنات المتداخلة بلا مصفوفات، يُنتج pd.json_normalize(data, sep='_') الأبسط أسماء أعمدة مفصولة بتسطير سفلي مثل customer_address_city. استخدم max_level= لتحديد العمق في الأشجار العميقة.

ما حد الأعمدة عند تسطيح JSON المتداخل بعمق؟

حد الأعمدة عند تسطيح JSON المتداخل بعمق هو ١٦٬٣٨٤ في Excel، وعمليًا بلا حد في CSV ذاته، لكن بعد ٥٠٠ عمود يصير الناتج عسير الإدارة. مواصفات Pod في Kubernetes أو ردود GraphQL تتجاوز ذلك بيسر. سلسل الفروع الثقيلة بـ محوّل JSON إلى CSV، أو اعرض مسبقًا بـ jq أو kubectl jsonpath.

هل jq أداة جيدة لتسطيح JSON قبل التحويل إلى CSV؟

نعم، jq هو الأداة الصحيحة لتسطيح JSON قبل التحويل إلى CSV. يتعامل مع العرض المسبق (map({id, name})) والتوسيع المسبق (.[] | {id, item: .items[]}) وتطبيع الشكل في سطر واحد. يجري خط أنابيب jq قبل خطوة CSV، ويتحكم بدقة في الحقول التي تصل إلى المحوّل. راجع مرجع jq السريع للأنماط.

خاتمة

خمس خلاصات:

  1. تحويل JSON إلى CSV مشكلة هندسة شكلية لا مشكلة نحو. لا تتسع الشجرة لشبكة دون اختيار كيف تنطوي الأغصان.
  2. الاستراتيجيات الخمس تُغطي الكون العملي (نقطي، تسطير سفلي، مصفوفات مفهرسة، توسيع صفوف، Stringify). اختر بحسب المستهلِك.
  3. Stringify هو المسار الوحيد بلا فقد. استخدمه للرحلات ذهابًا وإيابًا في خطوط الإنتاج.
  4. لـ Excel-EU وBigQuery إعدادات مسبقة لسبب وجيه. استخدمها.
  5. الحمولات الواقعية (mongoexport ومواصفات Kubernetes وردود GitHub) تحتاج عادة إلى خطوة عرض مسبق بـ jq أو kubectl jsonpath أولًا.

جرّب حمولتك في محوّل JSON إلى CSV. يعمل محليًا، ويتعامل مع الاستراتيجيات الخمس جميعًا، ويعود ذهابًا وإيابًا بلا فقد مع Stringify. لا رفع ولا تسجيل، والبيانات تبقى في صفحتك.

مقالات ذات صلة

عرض جميع المقالات