JSON إلى Go

يولّد هياكل Go بوسوم json من JSON: يحدد نوع كل رقم بحسب طريقة كتابته، ويستخدم المؤشرات حيث قد تغيب القيمة — كل ذلك في متصفحك.

الإدخال
Go
type Root struct {
	Orders  []Order `json:"orders"`
	HasMore bool    `json:"has_more"`
}

type Order struct {
	ID        int64    `json:"id"`
	UserID    int64    `json:"user_id"`
	CreatedAt string   `json:"created_at"`
	Price     float64  `json:"price"`
	Coupon    *string  `json:"coupon"`
	GiftNote  *string  `json:"gift_note,omitzero"`
	Shipping  Shipping `json:"shipping"`
	Tags      []any    `json:"tags"`
}

type Shipping struct {
	City     string          `json:"city"`
	Postcode json.RawMessage `json:"postcode"`
}
  • في كل موضع أدناه، قُرئ كل رقم كعدد صحيح، لذا النوع هناك int64. القيمة المكتوبة بنقطة عشرية أو بصيغة أُسّية، حتى 10.0، لن يُفك ترميزها فيه.

    المواضع: ‎2

    • Order.ID
    • Order.UserID
  • في كل موضع أدناه، القيم من أكثر من نوع — أرقام ونصوص مثلًا — لذا النوع هناك json.RawMessage، الذي يحفظ كل قيمة كما هي مكتوبة في JSON الخاص بك، ليفك برنامجك ترميزها حين يعرف نوعها. وحيث يكون أحد الأنواع كائنًا، يبقى هيكله في المخرجات، ويمكن فك ترميز تلك القيمة إليه.

    المواضع: ‎1

    • Shipping.Postcode
  • في كل موضع أدناه لم يكن هناك ما يُستنتج منه نوع: لم يظهر هناك سوى null، أو كانت المصفوفة فارغة دائمًا، أو لم يكن للكائن أي مفتاح، أو كانت القيمة متداخلة أعمق من أن تتتبعها هذه الأداة. لذا النوع هناك any، الذي يقبل أي قيمة — أو map[string]any حيث لم يكن للكائن أي مفتاح، الذي يقبل أي كائن أو null ولا شيء غير ذلك.

    المواضع: ‎1

    • Order.Tags[]

هياكل تفك ترميز JSON الذي جاءت منه

الصق عيّنة من JSON فتكتب هذه الصفحة تصريحات Go لها: هيكلًا مسمّى لكل كائن في العيّنة، ووسم json على كل حقل يسمّي المفتاح الذي يقرؤه. وعد واحد يحسم كل ما يلي. فإذا وُضعت التصريحات في برنامج يُبنى باستخدام Go 1.27، فكّت ترميز JSON الذي ألصقته عبر "encoding/json" دون خطأ، وقُرئ كل مفتاح في حقل، إلا المفتاح الذي لا يستطيع أي وسم هيكل حمله، فيُترك خارج الهيكل. وحيث لا يدع Go هذا الوعد يصمد، أو يُلزم الصفحة باختيار شيء لم تحسمه بياناتك، يبيّن تنبيه تحت المخرجات موضع ذلك، باستثناء حالة واحدة نادرة موصوفة في القسم الخاص بالوسوم.

أما الشكل نفسه فيُحدَّد قبل أن يُكتب أي شيء من Go، بقراءة JSON الخاص بك نفسها التي تغذّي صفحة JSON إلى TypeScript. دمج عناصر المصفوفة، وملاحظة المفاتيح التي لا يحملها إلا بعضها، والفصل بين null ومفتاح لم يُرسَل قط، وتسمية كل كائن يوجد داخل كائن آخر: كل ذلك يغطيه دليل تلك الصفحة، ولذلك لا يتكرر شيء منه أدناه. وما يلي هو نصيب Go — نوع لكل رقم، والمؤشرات، ونوع لمفتاح قيمه من أنواع مختلفة، وأسماء الحقول، والوسوم، والأسئلة التي تطرحها التنبيهات.

ثلاثة أنواع للأرقام، تُختار بحسب طريقة كتابة كل رقم

المتصفح الذي يقرأ JSON يحوّل 10 و10.0 إلى الرقم نفسه. أما Go فلا: فحقل "int64" لا يقبل رقمًا مكتوبًا بنقطة عشرية أو بصيغة أُسّية — 10.0 أو 1e3، بل حتى ‎-0.0 — بينما يقبل 11 و‎-0. لذلك لا تختار الصفحة نوع الرقم من القيم وحدها. إنها تسأل محلّل المتصفح نفسه كيف كُتب كل رقم، وتقرر على هذا الأساس:

  • حيث يكون كل رقم في موضع ما مكتوبًا عددًا صحيحًا، بلا نقطة عشرية وبلا صيغة أُسّية، يكون الحقل "int64"، ويذكره تنبيه الأعداد الصحيحة.
  • أي رقم آخر يكون "float64"، فالسعر المكتوب 10.0 يكون "float64" حتى لو جاءت كل الأسعار في العيّنة بلا كسور. فوحدة "json" في Python تكتب عدد float ذا القيمة الصحيحة بهذه الطريقة تمامًا، ولهذا تكون واجهة API تقدّمها Python المكان المعتاد لمصادفة ذلك.
  • أما "json.Number" فيُخصَّص للأرقام التي لا يحملها أي من النوعين بدقة: عدد صحيح يتجاوز أحد طرفي نطاق "int64"، ورقم أكبر من أن يسعه "float64" أصلًا، مثل 1e999، وعدد صحيح أطول من أن يسعه "float64" بجانب كسر، كما في ‎[9007199254740993, 1.5]. وهو يحمل كلًّا منها بدقة، ويحوّله برنامجك حيث يستخدم القيمة.

أما العدد الصحيح الطويل بين أعداد صحيحة أخرى فلا يحتاج إلى مثل هذا الحرص: ‎[9007199254740993, 1] يكون "‎[]int64". والكسر الذي فيه خانات أكثر مما يحفظه "float64" يبقى "float64" ويُذكر في تنبيه خاص به، لأن فك ترميزه ثم ترميزه من جديد يعيد 0.30000000000000001 على هيئة 0.3.

قراءة طريقة كتابة الرقم تحتاج إلى متصفح يُبلغ عنها. أما المتصفح الذي لا يُبلغ عنها فيقرأ كل رقم من قيمته وحدها، فيبدو 10.0 هناك عددًا صحيحًا ويصير نوع حقله "int64"، فلا يفك ذلك الحقل ترميز JSON ذاك؛ وتعدّ الصفحة الأرقام التي لم تستطع تمييزها عن الأعداد الصحيحة، وتبيّن أين يقع أولها. ومثل هذا المتصفح لا يرى أيضًا الخانات التي يُسقطها "float64"، فهناك يصير نوع العدد الصحيح الطويل بجانب كسر "float64"، ولا يُذكر الكسر الذي يُقرَّب.

مؤشرات حيث قد تغيب القيمة

المفتاح الذي تُغفله بعض الكائنات، أو تجعل قيمته null، يكون مؤشرًا: "‎*string" أو "‎*int64"، أو مؤشرًا إلى الهيكل المكتوب لكائن. وعناصر المصفوفة التي تحمل null مؤشرات كذلك، ولذلك فإن ‎[1, null] يكون "‎[]‎*int64". والمفتاح الغائب عن بعض الكائنات يحمل وسمه أيضًا "omitzero". وباجتماع الأمرين يستطيع الحقل أن يقول هل وصلت قيمة، وعند ترميز الهيكل من جديد بعد فك ترميزه يُحذف المفتاح الذي لم تفعل العيّنة سوى أن تُغفله، ويُكتب المفتاح الذي لم تجعل قيمته إلا null على هيئة null.

لا تأخذ الشريحة (slice) ولا الخريطة (map) ولا "any" ولا "json.RawMessage" مؤشرًا، لأن كلًّا منها يكون nil أصلًا حين لا يُفك ترميز شيء إليه. ومع ذلك تأخذ الشريحة "omitzero" حيث قد يغيب مفتاحها، والمصفوفة التي كانت حاضرة لكنها فارغة تُكتب من جديد على هيئة [].

ثمة تمييز واحد لا يصمد. فالمفتاح الغائب عن بعض الكائنات والذي قيمته null في بعضها الآخر يصير nil واحدًا في Go، فلا يستطيع برنامجك التمييز بين الحالتين، وعند ترميز الهيكل من جديد يُحذف المفتاح حتى حيث كانت قيمته null في العيّنة؛ والصفحة تسمّي كل حقل يحدث له ذلك. أما المفتاح ذو الأنواع المختلطة فيحتفظ بالفرق، لأن "json.RawMessage" يحمل null على هيئة البايتات null.

json.RawMessage للأنواع المختلطة، وany حيث لم يُرَ شيء

حين تختلف قيم مفتاح في نوعها — رقم في موضع، ونص أو كائن في موضع آخر — يكون الحقل "json.RawMessage": بايتات القيمة نفسها، متروكة لبرنامجك ليفك ترميزها بعد أن ينظر في نوع ما وصل. ولا يغيّر null بينها شيئًا. وحيث يكون أحد الأنواع كائنًا، يبقى الهيكل المستخرج له مطبوعًا إلى جانب غيره. وكان "any" سيقبل كل الأنواع أيضًا، لكنه لا يُستخدم للخليط، لأن الرقم الذي يُفك ترميزه إلى "any" يصير "float64" ويفقد كل ما لا يستطيع "float64" حمله.

بعض أجزاء العيّنة لا تقدّم قيمة يُتعلَّم منها: مفتاح لم يحمل قط سوى null، ومصفوفة كانت فارغة في كل مرة، وكائن بلا مفاتيح، وقيمة مدفونة أعمق مما يقرؤه الاستنتاج. وفي Go يصير مفتاح null والقيمة المدفونة "any"، وتصير عناصر المصفوفة الفارغة "‎[]any"، ويصير الكائن "map[string]any". و"any" يقبل كل نوع من القيم. أما الخريطة فتقبل كائنًا أو null، وإذا جاء مكانها نص أو رقم أو مصفوفة أو قيمة منطقية فشل فك الترميز.

ووراء ذلك العمق يبقى أمران لا تذكرهما التنبيهات. فالمفتاح هناك الغائب عن بعض الكائنات والذي قيمته null في بعضها الآخر لا يُذكر إلا بوصفه موضعًا لم يكن فيه ما يُستنتج منه نوع، وحيث كانت قيمته null يحذفه Go عند كتابته من جديد. والعدد الصحيح الأطول مما يحمله "float64" يعود مُقرَّبًا، إذ يعود 9007199254740993 على هيئة 9007199254740992، لأن الموضع من النوع "any".

أسماء الحقول بأسلوب Go، وأسماء الهياكل مشتركة مع صفحة TypeScript

اسم الحقل هو تهجئة Go لمفتاحه. يُقسَّم المفتاح إلى كلمات عند كل محرف ليس حرفًا ولا رقمًا، وحيثما جاء حرف كبير بعد حرف صغير؛ ثم تُوصل الكلمات وكل منها يبدأ بحرف كبير: "user_name" و"last-name" و"firstName" تصير UserName وLastName وFirstName. والكلمة الموجودة في قائمة الاختصارات الافتراضية في staticcheck تُكتب بحروف كبيرة — "id" يُكتب ID، و"api_key" يُكتب APIKey، و"video_url" يُكتب VideoURL — لكن الكلمة الكاملة وحدها هي التي تُحتسب: "idle" يُكتب Idle، وصيغة الجمع "ids" تُكتب Ids. والمفتاح المكتوب كله بحروف كبيرة يُقرأ كلمات: "USER_ID" يُكتب UserID.

تبقى حروف المفتاح نفسه: "имя" يصير Имя. وحيث لن يبدأ الاسم بحرف كبير — مفتاح بنظام كتابة لا حروف كبيرة فيه مثل "名前"، أو مفتاح يبدأ برقم مثل "1st"، أو حرف أول ليس له حرف كبير من محرف واحد مثل "ß" — يأخذ الاسم X في أوله، كما في X名前 وX1st وXß، ويقرأ الحقل مفتاحه مع ذلك. وتُسقط علامات التشكيل المدمجة من الاسم وتُحفظ في الوسم. والمفتاح الذي ليس فيه حرف ولا رقم أصلًا، مثل "@"، يُسمّى Field، والاسم المستخدم من قبل في الهيكل نفسه يأخذ رقمًا: "user_id" و"userId" و"USER_ID" معًا تصير UserID وUserID2 وUserID3.

يصل أسلوب Go إلى أسماء الحقول ويتوقف عندها: فكل هيكل يحتفظ بالاسم الذي اختاره الاستنتاج لكائنه، ولذلك تحمل التصريحات هنا والواجهات في صفحة TypeScript الأسماء نفسها، وقد يُكتب الحقل على نحو يختلف عن الهيكل الذي يحمله. أما طريقة اختيار ذلك الاسم فمن شأن دليل صفحة TypeScript.

وسوم من أجل Go 1.27، والمفاتيح التي لا يستطيع أي وسم حملها

يسمّي وسم كل حقل مفتاحه بدقة، كما في json:"user_id"‎، مع ‎,omitzero بعد المفتاح حيث قد يغيب. ومحرف التحكم في المفتاح يُكتب بصيغة الهروب التي يستخدمها Go نفسه، والمفتاح "-" يُكتب json:"-,"‎، وهي صيغة يقرؤها Go على أنها ذلك المفتاح.

تُكتب الوسوم من أجل Go 1.27. أما Go 1.26 فيقرأ عبر الوسم مفاتيح أقل: فالمفتاح الذي يحوي أي شيء غير الحروف والأرقام والمسافة من ASCII ومجموعة من علامات الترقيم من ASCII — مثل "Price (€)"، "temp °C"، أو رمز تعبيري، أو محرف تحكم، أو علامة تشكيل مدمجة — لا يُقرأ هناك، والصفحة تسمّي كل حقل كهذا. ويُفحص هذا النصف مقابل Go 1.27 المبني مع "GOEXPERIMENT=nojsonv2"، الذي يقرأ الوسوم كما يقرؤها Go 1.26 لكن بجداول Unicode الأحدث في Go 1.27، ولذلك فإن المفتاح الذي يحوي حرفًا لا تعرفه جداول Go 1.26 الأقدم يُقرأ في ذلك الفحص ولا يُطلق أي تنبيه.

المفتاح الذي يحوي فاصلة، أو شرطة مائلة خلفية، أو علامة اقتباس مزدوجة، أو فاصلة عليا، أو فاصلة عليا مائلة، أو المفتاح الفارغ، هو مفتاح لا يستطيع أي وسم هيكل حمله، ولذلك لا يحصل على حقل أصلًا. ويبقى JSON الخاص بك قابلًا لفك الترميز: إذ يتخطى "json.Unmarshal" ذلك المفتاح دون اعتراض، وإن كان "json.Decoder" المضبوط على "DisallowUnknownFields" يتوقف عنده. ويذكر التنبيه مثل هذا المفتاح بهيكله وبالمفتاح بين علامتي اقتباس كما يكتب Go النصوص، مثل Order["note,internal"]، والكائن الذي تحت مفتاح كهذا يبقى هيكله مطبوعًا. وحالة واحدة تمر دون تنبيه: مفتاحان لا يختلفان إلا في بديل منفرد، وهو صيغة هروب لا تمثّل أي محرف، هما مفتاح واحد في نظر Go، ولا يُملأ أي من حقليهما.

تصريحات فقط، بتنسيق gofmt

تحمل المخرجات تصريحات أنواع ولا شيء غيرها: لا سطر package ولا import، فتدخل في ملف موجود لديك، تحت سطر package الخاص بذلك الملف. وحيث تستخدم "json.RawMessage" أو "json.Number"، يستورد الملف أيضًا "encoding/json"، وهذا هو السطر الوحيد المتروك لك أو لمحررك. والتنسيق هو تنسيق gofmt نفسه — محرف جدولة قبل كل حقل، وأسماء كل هيكل وأنواعه ووسومه في أعمدة مصطفّة — ولذلك يتركه gofmt كما هو تمامًا. ويُطبع نوع الجذر أولًا، وكل كائن نوع مسمّى لا هيكل مكتوب داخل الحقل الذي يحمله، وJSON الذي هو مصفوفة أو قيمة مفردة في المستوى الأعلى نوع مسمّى كذلك، مثل "type Root []RootItem"، فيوجد دائمًا نوع يُفك ترميزه إليه.

ما تطلب منك التنبيهات التحقق منه

كل نوع من القرارات التي فرضها Go يحصل على تنبيه واحد تحت التصريحات، ويجمع التنبيه كل موضع ينطبق عليه، فالعيّنة التي فيها حقول كثيرة من الأعداد الصحيحة تحصل على تنبيه واحد لا على تنبيه لكل حقل. وتُكتب المواضع كما تكتبها التصريحات — Order.UserID حقل، وOrder.Tags[]‎ عناصر مصفوفة، والجذر يُكتب باسمه وحده — إلا في تنبيهين يشيران إلى JSON الخاص بك بالسطر والعمود بدلًا من ذلك: مفتاح مكتوب مرتين، وأرقام لم يستطع هذا المتصفح تمييزها عن الأعداد الصحيحة. ولا يغيّر أي منها التصريحات. اقرأ كلًّا منها سؤالًا عن بياناتك:

  • أعداد صحيحة نوعها "int64". كل رقم هناك كُتب عددًا صحيحًا. وإن كان ما يصل لاحقًا من قيم قد يحمل نقطة عشرية أو صيغة أُسّية، كما قد يحمل سعر أو قياس، فلن يُفك ترميزه، لذا اجعل ذلك الحقل "float64"؛ أما المعرّف أو العدّاد فيمكن أن يبقى كما هو.
  • "json.Number". لا يحمل أي نوع رقمي آخر تلك القيم بدقة. حوّل كلًّا منها حيث يستخدمها برنامجك، أو، إن كنت تعرف أن القيم الحقيقية يسعها نوع أضيق، غيّر الحقل بنفسك.
  • كسر يقرّبه "float64". في ذلك الموضع رقم فيه خانات أكثر مما يحفظه "float64"، فيرى برنامجك قيمة قريبة لا القيمة المكتوبة. وحيث تهم كل خانة، اجعل الحقل "json.Number".
  • أنواع مختلطة محفوظة على هيئة "json.RawMessage". انظر في كل قيمة حين تصل وفُكّ ترميزها بحسب النوع الذي يتبيّن أنها منه؛ وحيث يكون أحد الأنواع كائنًا، يبقى هيكله في المخرجات لتفك ترميز تلك القيمة إليه.
  • لا شيء يُستنتج منه نوع. الحقل "any"، أو خريطة من "any"، لأن العيّنة لم تحمل هناك قيمة يُتعلَّم منها. ضع مكانه النوع الذي تعرف أن ذلك الحقل يحمله، أو حوّل من جديد انطلاقًا من JSON يحمل فيه قيمًا حقيقية.
  • غائب عن بعض الكائنات، وnull في بعضها الآخر. يحفظ Go الحالتين على هيئة nil واحد، فيُحذف المفتاح عند ترميز الهيكل من جديد. ولا يهم ذلك إلا إذا كان ما يقرأ مخرجاتك يعامل null معاملة تختلف عن مفتاح غير موجود.
  • مفاتيح لا يقرؤها Go 1.26. ابنِ باستخدام Go 1.27، أو غيّر أسماء تلك المفاتيح حيث تُنتَج؛ ففي Go 1.26 تبقى دون قراءة.
  • مفاتيح تُركت خارج الهيكل. لا حقل لها. ولقراءة أحدها، فُكّ ترميز الكائن إلى "map[string]json.RawMessage" أو اكتب للهيكل دالة "UnmarshalJSON"، كما يقترح التنبيه نفسه.
  • مفتاح مكتوب مرتين. تُبنى الأنواع على النسخة الأخيرة من المفتاح، لكن Go يفك ترميز كل نسخة بدورها، فالنسخة السابقة التي لا يستطيع النوع حملها، كنص حيث النسخة الأخيرة رقم، تجعل فك الترميز يُرجع خطأ، والمفتاح الذي لا يوجد إلا في نسخة سابقة من كائن لا يُقرأ. أصلح JSON عند السطر والعمود المعروضين.
  • لا يميّز هذا المتصفح بين 10 و10.0. فهو لا يُبلغ عن طريقة كتابة الرقم، ولذلك فإن الحقل الذي صار نوعه "int64" بسبب قيمة مكتوبة بنقطة عشرية أو بصيغة أُسّية لن يفك ترميز JSON الخاص بك. تحقّق من الحقول المكتوبة بهذه الطريقة، أو حوّل JSON في متصفح يُبلغ عنها.

لا يوجد تنبيه عن التواريخ أو الصيغ أو المجموعات الثابتة من القيم، لأن الصفحة لا تخمّن أيًّا منها من نص أبدًا: يبقى "created_at" في المثال "string"، أيًّا كان شكله.

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

لماذا سعري float64 مع أن كل سعر في JSON الخاص بي رقم بلا كسور؟
لأن كل سعر مكتوب بنقطة عشرية، مثل 10.0، وحقل "int64" لا يقبل رقمًا مكتوبًا بهذه الطريقة، سواء كان بلا كسور أم لا. والصفحة تقرأ طريقة كتابة كل رقم لا قيمته وحدها، فيكون الحقل "float64" ويُفك ترميز JSON الخاص بك. ولو كان نوعه "int64" بحسب القيم وحدها، لتوقف فك الترميز عند أول سعر.
متى يخرج الرقم على هيئة json.Number؟
حين تكون إحدى قيمه عددًا صحيحًا يتجاوز نطاق "int64"، أو رقمًا أكبر من أن يسعه "float64"، أو عددًا صحيحًا طويلًا يجاور كسرًا، وهو ما كان "float64" سيقرّبه. و"json.Number" يحفظ كلًّا منها بدقة، والتنبيه الذي تحت المخرجات يسرد كل حقل اختير له.
لماذا بعض الحقول مؤشرات، وما عمل omitzero في الوسوم؟
يكون الحقل مؤشرًا حيث يغيب مفتاحه عن بعض الكائنات أو تكون قيمته null في بعضها، كي يستطيع nil أن يقول إنه لم تصل قيمة. ويُوضع "omitzero" حيث يغيب المفتاح عن بعض الكائنات: فعند ترميز الهيكل من جديد يُحذف ذلك المفتاح، كما فعل JSON الخاص بك، بدل أن يُكتب له null.
لماذا json.RawMessage لمفتاح مختلط الأنواع، لا any؟
"json.RawMessage" يحفظ بايتات كل قيمة إلى أن يقرر برنامجك كيف يقرؤها. و"any" كان سيقبل القيم أيضًا، لكن الرقم الذي يُفك ترميزه إلى "any" يكون "float64"، والعدد الصحيح الطويل يفقد هناك خاناته الأخيرة.
لماذا تبدأ بعض أسماء الحقول بحرف X؟
لأن الاسم لن يبدأ بحرف كبير لولا ذلك: فالمفتاح إما مكتوب بنظام كتابة لا حروف كبيرة فيه، أو يبدأ برقم، أو يبدأ بحرف ليس له شكل كبير من محرف واحد. وحرف X يُبقي حروف المفتاح نفسه في الاسم، ويظل الحقل يقرأ مفتاحه — X名前 يقرأ "名前".
أي إصدار من Go تحتاجه الهياكل؟
تُكتب وتُفحص من أجل Go 1.27. ويُفحص أيضًا كيف يقرأ Go 1.26 الوسوم، عبر ما يقوم مقامه: لا يقرأ Go 1.26 مفتاحًا يحوي محرفًا خارج الحروف والأرقام والمسافة من ASCII ومجموعة من علامات الترقيم من ASCII، مثل رمز عملة أو رمز تعبيري، والصفحة تسمّي كل حقل يتأثر مفتاحه بذلك — باستثناء مفتاح يحوي حرفًا أحدث من جداول Unicode في Go 1.26، وهو ما لا تستطيع الصفحة ولا ذلك الفحص رؤيته.
لماذا يغيب أحد مفاتيحي عن الهيكل؟
لأن المفتاح يحوي فاصلة أو شرطة مائلة خلفية أو علامة اقتباس مزدوجة أو فاصلة عليا أو فاصلة عليا مائلة، أو لأنه فارغ، ولا يستطيع أي وسم هيكل حمل مفتاح كهذا. ويذكره تنبيه بهيكله وبالمفتاح نفسه، مثل Root["a,b"]؛ ويبقى باقي JSON الخاص بك قابلًا لفك الترميز، ويقول التنبيه كيف يُقرأ ذلك المفتاح بطريقة أخرى.
هل من الآمن لصق استجابة تحمل رموز وصول أو كلمات مرور؟
نعم. كل خطوة تجري داخل هذه الصفحة على حاسوبك، والاستجابة التي تلصقها لا تذهب إلى أي مكان آخر: لا يستقبلها أي خادم ولا يحتفظ أي شيء بنسخة منها. والتصريحات الناتجة لا تحمل إلا أسماء الحقول والوسوم وأنواع Go، فرمز الوصول أو كلمة المرور في JSON لا يترك فيها أي أثر سوى حقل "string" مسمّى باسم مفتاحه.

أدوات ذات صلة

  • JSON إلى TypeScript

    حيث تختلف قيم مفتاح في نوعها، تحفظ هذه الصفحة كل قيمة كما هي مكتوبة في JSON الخاص بك ليفك برنامجك ترميزها، لأنه ليس في Go اتحاد. تكتب تلك الصفحة الشكل نفسه في صورة أنواع TypeScript بأسماء الأنواع نفسها، مع اتحاد في ذلك الموضع، ويشرح دليلها كيف يُستنتج ذلك الشكل.

  • JSON إلى Zod

    ليس في Go نوع هو رقم JSON فحسب، لذا تجعل هذه الصفحة نوع الحقل عددًا صحيحًا حيث يكون كل رقم مكتوبًا عددًا صحيحًا، والقيمة المكتوبة بنقطة عشرية لن يُفك ترميزها فيه. تكتب تلك الصفحة الشكل نفسه في صورة مخططات Zod بأسماء الأنواع نفسها، والمخطط يتحقق من البيانات في كل مرة تصل فيها ويقبل كسرًا في مثل هذا الحقل أيضًا.

  • مُختبِر JSONPath

    اختبار استعلامات JSONPath (RFC 9535) على JSON.

  • مولّد جداول Markdown

    أنشئ جداول Markdown من CSV أو TSV أو JSON وحاذِ أعمدتها.