نحوه تبدیل JSON در NET Core.

دوشنبه 20 مرداد 1399

ما به تازگی با پروژه‌ای رو به رو شدیم که کار ساده‌ای انجام می‌داد؛ خواندن یک فایل JSON. اما روشی که به JSON تبدیل شد گیج‌کننده بود. به نظر می‌رسید که پیچیده‌ترین روش خواندن داده‌های JSON که تا به حال دیده‌ایم بود. وقتی راه‌حل این کار را جستجو می‌کنیم، با کمال تعجب می‌بینیم که بسیاری از نتایج همان کارهای گیج‌کننده است.

نحوه تبدیل JSON در NET Core.

بنابراین در این آموزش می‌خواهیم ببینیم که چطور JSON را در NET Core. تبدیل کنیم.

نصب JSON.NET

اگر قبل از NET Core 3.0. با پروژه ASP.NET Core کار کرده‌اید، احتمالا JSON.NET را از قبل نصب دارید. اما اگر در حال کار بر روی برنامه کنسول یا Class Library هستید، باید آن را از کنسول package manager با دستور زیر نصب کنید.

Install-Package Newtonsoft.Json

سند JSON مثال ما

برای اهداف این آموزش، ما می‌خواهیم یک سند JSON خیلی ساده داشته باشیم تا با آن کار کنیم. این سند چنین خواهد بود:

{
  "MyStringProperty": "StringValue",
  "MyIntegerProperty": 1,
  "MySubDocument": {
    "SubDocumentProperty": "SubDocumentValue"
  },
  "MyListProperty": [
    1,
    2,
    3
  ]
}

این را در یک فایل ذخیره می‌کنیم، و تمام کاری که باید انجام دهیم، بارگذاری آن در یک رشته (string) در یک برنامه کنسول است:

static void Main(string[] args)
{
    var myJsonString = File.ReadAllText("myfile.json");
}

سپس این رشته را می‌گیریم، و می‌بیینیم که چگونه داده‌ها را از آن استخراج کنیم.

استفاده از JObject

به نظر ما این بدترین روش برای تبدیل یک سند JSON بزرگ است، اما به نظر می‌رسد که پاسخ سریع در هر سوال stackoverflow در رابطه با JSON و C# این است. از نظر ما این به یک رشته جادویی متکی است و واقعا پیچیده است.

بیایید ببینیم چطور می‌توانیم یک پراپرتی ساده string را با استفاده از JObject به دست آوریم:

static void Main(string[] args)
{
    var myJsonString = File.ReadAllText("myfile.json");
    var myJObject = JObject.Parse(myJsonString);
    Console.WriteLine(myJObject.SelectToken("MyStringProperty").Value<string>());
}

بسیار خوب است، اما این امر به این متکی است که در یک رشته جادویی ارسال کنیم تا پراپرتی را پیدا کنیم. این وحشتناک نیست، اما عالی هم نیست.

اگر یک زیرمجموعه‌ای از سند را بخواهیم چطور؟ ابتدا ممکن است فکر کنید می‌توانید از کوئری XPath استفاده کنید که به طور معمول برای تبدیل فایل‌های XML استفاده می‌شود. اشتباه می‌کنید. به دلایلی،‌ یک زبان پرس و جوی متفاوتی به نام JSONPath وجود دارد که در عوض از نشانه‌گذاری نقطه استفاده می‌کند. با توجه به بعضی دلایل منطقی است زیرا JSON تمام ویژگی‌های XML را ندارد (اتربیوت‌ها، فضای نام‌ها و غیره) اما این نیز آزاردهنده است که مجبور شویم مجموعه دیگری از نشانه‌گذاری‌ها را یاد بگیریم.

به هر حال، به کوئری زیر مجموعه سند برگردید:

myJObject.SelectToken("$.MySubDocument.SubDocumentProperty").Value<string>()

اگر بخواهیم همه لیست‌ آبجکت را بگیریم:

var myList = myJObject.SelectTokens("$.MyListProperty").Values<int>().ToList();
Console.WriteLine(myList[1].ToString());

تاکنون فقط مقادیر منحصربه‌فرد را گرفتیم. اگر بخواهیم همه سند مپ شود چطور؟ مپ کردن هر آیتم به صورت جداگانه در یک کلاس بزرگ‌تر می‌تواند عذاب‌آور باشد (و با این حال هنوز می‌بینیم که مردم این کار را همیشه انجام می‌دهند).

تنها دلیل استفاده از JObject این است که شما یک پراپرتی/آیتم خاصی را می‌خواهید و به اکثریت سند اهمیت نمی‌دهید.

استفاده از Dynamic JToken

یکی دیگر از روش‌های نه چندان جالب تبدیل JSON استفاده از JToken برای تبدیل کل سند JSON به یک آبجکت داینامیک است. مثلا:

static void Main(string[] args)
{
    var myJsonString = File.ReadAllText("myfile.json");
    dynamic jToken = JToken.Parse(myJsonString);
    Console.WriteLine(jToken.MyStringProperty);
    Console.ReadLine();
}

این کار می‌کند و بسیار آسان است، اما دارای نقص‌های بزرگی است. بزرگ‌ترین مورد آن این است که پوشش سند JSON شما برای نحوه ظاهر آبجکت داینامیک بسیار مهم باشد. مثلا:

"MyStringProperty" => jToken.MyStringProperty
"myStringProperty" => jToken.myStringProperty

با توجه به اینکه JSON معمولا camel case است، و پراپرتی‌ها در سی‌شارپ pascal case هستند، یکی باید تسلیم شود و سبک پوشش خود را تغییر دهد.

این امر همچنین نادیده گرفتن این واقعیت است که شما اکنون در استفاده از آبجکت‌های داینامیک که با مجموعه‌ای از دردسرهای خود در رابطه با داینامیک همراه هستند، قفل شده‌اید.

به نظر ما، همانند JObject، استفاده از این متد برای تبدیل تمام اسناد JSON ارزش ندارد. شاید اگر باید به یک پراپرتی دسترسی داشته باشید، ترجیح می‌دهید که از آبجکت داینامیک سی‌شارپ با استفاده از JSONPath استفاده کنید، در غیر این صورت فراموشش کنید.

استفاده از JsonConvert

به نظر ما این تنها راه تبدیل JSON به آبجکت C# است.

ابتدا یک کلاس سی‌شارپ ایجاد می‌کنیم که مطابق با آن چیزی است که در JSON داریم:

class MyJsonType
{
    public string MyStringProperty { get; set; }

    public int MyIntegerProperty { get; set; }

    public MyJsonSubDocumentType MySubDocument { get; set; }

    public List<int> MyListProperty { get; set; }
}

class MyJsonSubDocumentType
{
    public string SubDocumentProperty { get; set; }
}

سپس با یک خط می‌توانیم رشته JSON را به آبجکت strongly typed تبدیل کنیم:

var myJsonObject = JsonConvert.DeserializeObject<MyJsonType>(myJsonString);
Console.WriteLine(myJsonObject.MyStringProperty);
Console.ReadLine();

وقتی صحبت از دسترسی به مواردی مانند لیست است، از آنجایی که JSON.NET آن را به طور مستقیم در لیست آبجکت deserialize می‌کند، هیچ نگرانیی در مورد تبدیل کردن یا چیزی مثل آن وجود ندارد. مثلا این مستقیم بدون هیچ تنظیم خاصی کار می‌کند:

myJsonObject.MyListProperty.First()

جمع‌بندی

9 بار از 10 بار، شما می‌خواهید از گزینه JsonConvert استفاده کنید. این کل سند JSON را به یک کلاس deserialize می‌کند که در بیشتر موارد همان چیزی می‌شود که شما برای آن انجام می‌دهید. تنها زمانی که باید از JObject استفاده کنید وقتی است که زیرمجموعه خیلی کوچکی از سند را می‌خواهید (ترجیحا فقط یک یا دو آیتم).

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان
  • C#.net
  • 2k بازدید
  • 1 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید