Battle of C # JSON المسلسلات لـ .NET Core 3

مرحبا. استعدادًا لبدء الدورة التدريبية "C # Developer" ، قمنا بإعداد ترجمة ممتعة لك ، ونقدم لك أيضًا مشاهدة سجل الدرس مجانًا: "Design Pattern State (State)"










جاء NET Core 3 الذي تم إصداره مؤخرًا بعدد من الابتكارات. بالإضافة إلى C # 8 ودعم WinForms و WPF ، أضاف الإصدار الأخير مُسلسل JSON (de) جديدًا - System.Text.Json ، وكما يوحي اسمه ، فإن جميع فئاته موجودة في مساحة الاسم هذه.



هذا ابتكار رئيسي. يعتبر تسلسل JSON عاملاً مهمًا في تطبيقات الويب.تعتمد معظم REST API اليوم عليها. عندما يرسل عميل javascript الخاص بك JSON في نص طلب POST ، يستخدم الخادم إلغاء تسلسل JSON لتحويله إلى كائن C #. وعندما يعرض الخادم كائنًا ردًا على ذلك ، فإنه يسلسل هذا الكائن إلى JSON حتى يتمكن عميل جافا سكريبت لديك من فهمه. هذه عمليات كبيرة يتم إجراؤها عند كل طلب باستخدام كائنات. يمكن أن يؤثر أدائهم بشكل كبير على أداء التطبيقات ، وهو ما سأعرضه الآن.



إذا كانت لديك خبرة في استخدام .NET ، فلا بد أنك سمعت عن برنامج Json.NET المتسلسل الممتاز ، والمعروف أيضًا باسم Newtonsoft.Json . لذلك لماذا نحن بحاجة إلى مسلسل جديد عندما يكون لدينا بالفعل Newtonsoft.Json جميل ؟ في حين أن Newtonsoft.Json رائع بلا شك ، إلا أن هناك بعض الأسباب الوجيهة لاستبداله:



  • كانت مايكروسوفت حريصة على استخدام أنواع جديدة ، مثل Span<T>، لتحسين الأداء. يعد تعديل مكتبة ضخمة مثل Newtonsoft دون كسر الوظائف أمرًا صعبًا للغاية.
  • , HTTP, UTF-8. String .NET — UTF-16. Newtonsoft UTF-8 UTF-16, . UTF-8.
  • Newtonsoft , .NET Framework ( BCL FCL), . ASP.NET Core Newtonsoft, .


في هذه المقالة ، سنقوم ببعض المعايير لنرى إلى أي مدى يكون المسلسل الجديد أفضل من حيث الأداء. بالإضافة إلى ذلك ، سنقارن أيضًا Newtonsoft.Json و System.Text.Json بالمسلسلات الأخرى المعروفة ونرى كيف يتعاملون مع بعضهم البعض.



معركة المسلسل



هذا هو حاكمنا:



  • Newtonsoft.Json (المعروف أيضًا باسم Json.NET ) هو المسلسل القياسي حاليًا في الصناعة. تم دمجه في ASP.NET ، على الرغم من أنه طرف ثالث. حزمة NuGet رقم 1 في كل الأوقات. مكتبة حائزة على العديد من الجوائز (ربما لا أعرف على وجه اليقين).
  • System.Text.Json — Microsoft. Newtonsoft.Json. ASP.NET Core 3. .NET, NuGet ( ).
  • DataContractJsonSerializer — , Microsoft, ASP.NET , Newtonsoft.Json.
  • Jil — JSON Sigil



  • ServiceStack — .NET JSON, JSV CSV. .NET ( ).



  • Utf8Jso n هو أسرع مُسلسل C # إلى JSON. يعمل بدون تخصيص للذاكرة ويقرأ / يكتب مباشرة إلى UTF8 الثنائي للحصول على أداء أفضل.





لاحظ أن هناك مسلسلين بخلاف JSON أسرع. على وجه الخصوص ، فإن protobuf-net عبارة عن برنامج تسلسلي ثنائي يجب أن يكون أسرع من أي من المسلسلات المقارنة في هذه المقالة (والتي لم يتم اختبارها من خلال المعايير رغم ذلك)



هيكل المعيار



ليس من السهل مقارنة المسلسلات. سنحتاج إلى مقارنة التسلسل وإلغاء التسلسل. سنحتاج إلى مقارنة أنواع مختلفة من الفصول (صغيرة وكبيرة) والقوائم والقواميس. وسنحتاج إلى مقارنة أهداف التسلسل المختلفة: السلاسل والتدفقات ومصفوفات الأحرف (مصفوفات UTF-8). هذه مصفوفة اختبار كبيرة إلى حد ما ، لكنني سأحاول إبقائها منظمة وموجزة قدر الإمكان.



سنختبر 4 وظائف مختلفة:



  • التسلسل إلى السلسلة
  • التسلسل لتيار
  • إلغاء التسلسل من السلسلة
  • الطلبات في الثانية على تطبيق ASP.NET Core 3


لكل منها ، سنختبر أنواعًا مختلفة من الكائنات (والتي يمكنك رؤيتها على GitHub ):



  • فئة صغيرة مع 3 خصائص فقط من النوع البدائي.
  • فئة كبيرة تضم حوالي 25 عقارًا ، DateTime واثنين من التعدادات
  • قائمة 1000 عنصر (فئة صغيرة)
  • قاموس من 1000 عنصر (فئة صغيرة)


هذه ليست كلها معايير مرجعية ضرورية ، لكنها في رأيي كافية للحصول على فكرة عامة.

لجميع المعايير اعتدت BenchmarkDotNet على النظام التالية: BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17134.1069 (1803/April2018Update/Redstone4) Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores. .NET Core SDK=3.0.100. Host : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT. يمكنك العثور على المشروع المعياري نفسه على GitHub .


سيتم تشغيل جميع الاختبارات فقط على مشاريع .NET Core 3.



المعيار 1: التسلسل إلى سلسلة



أول شيء سنتحقق منه هو إجراء تسلسل لعينة الكائنات إلى سلسلة نصية.



الكود المعياري نفسه بسيط جدًا (انظر على GitHub ):



public class SerializeToString<T> where  T : new()
{
 
    private T _instance;
    private DataContractJsonSerializer _dataContractJsonSerializer;
 
    [GlobalSetup]
    public void Setup()
    {
        _instance = new T();
        _dataContractJsonSerializer = new DataContractJsonSerializer(typeof(T));
    }
 
    [Benchmark]
    public string RunSystemTextJson()
    {
        return JsonSerializer.Serialize(_instance);
    }
 
    [Benchmark]
    public string RunNewtonsoft()
    {
        return JsonConvert.SerializeObject(_instance);
    }
 
    [Benchmark]
    public string RunDataContractJsonSerializer()
    {
        using (MemoryStream stream1 = new MemoryStream())
        {
            _dataContractJsonSerializer.WriteObject(stream1, _instance);
            stream1.Position = 0;
            using var sr = new StreamReader(stream1);
            return sr.ReadToEnd();
        }
    }
 
    [Benchmark]
    public string RunJil()
    {
        return Jil.JSON.Serialize(_instance);
    }
 
    [Benchmark]
    public string RunUtf8Json()
    {
        return Utf8Json.JsonSerializer.ToJsonString(_instance);
    }
 
    [Benchmark]
    public string RunServiceStack()
    {
        return SST.JsonSerializer.SerializeToString(_instance);
    }   
}


فئة الاختبار أعلاه عامة ، لذا يمكننا اختبار جميع كائناتنا بنفس الكود ، على سبيل المثال:



BenchmarkRunner.Run<SerializeToString<Models.BigClass>>();


بعد تشغيل جميع فئات الاختبار مع جميع المسلسلات ، حصلنا على النتائج التالية:





يمكن العثور على مؤشرات أكثر دقة هنا


  • Utf8Json هو الأسرع حتى الآن ، أسرع من Newtonsoft.Json و System.Text.Json بأكثر من 4 مرات . هذا فرق مذهل.
  • جيل أيضًا سريع جدًا ، أسرع بنحو 2.5 مرة من Newtonsoft.Json و System.Text.Json.
  • في معظم الحالات ، يعمل برنامج System.Text.Json المتسلسل الجديد بشكل أفضل من Newtonsoft.Json بحوالي 10٪ ، باستثناء القاموس ، حيث انتهى به الأمر ليكون أبطأ بنسبة 10٪.
  • يعد DataContractJsonSerializer الأقدم أسوأ بكثير من البرامج الأخرى.
  • يقع ServiceStack في المنتصف ، مما يدل على أنه لم يعد أسرع برنامج تسلسلي للنص. على الأقل لـ JSON.


المعيار 2: التسلسل إلى البث



المجموعة الثانية من الاختبارات متشابهة إلى حد كبير ، باستثناء أننا نقوم بالتسلسل إلى دفق. رمز المعيار هنا . النتائج:







يمكن العثور على أرقام أكثر دقة هنا . شكرًا لآدم سيتنيك وأحسون خان لمساعدتي في الحصول على System.Text.Json للعمل.


النتائج مشابهة جدًا للاختبار السابق. Utf8Json و Jil أسرع بأربع مرات من الآخرين. جيل سريع جدا ، في المرتبة الثانية بعد Utf8Json . لا يزال DataContractJsonSerializer هو الأبطأ في معظم الحالات. تعمل Newtonsoft بنفس طريقة System.Text.Json تقريبًا في معظم الحالات ، باستثناء القواميس ، حيث تتمتع Newtonsoft بميزة ملحوظة .



المعيار 3: إلغاء التسلسل من السلسلة



المجموعة التالية من الاختبارات تتعامل مع إلغاء التسلسل من سلسلة. يمكن العثور على رمز الاختبار هنا .







يمكن العثور على أرقام أكثر دقة هنا .


أواجه بعض الصعوبة في تشغيل DataContractJsonSerializer لهذا المعيار ، لذلك لم يتم تضمينه في النتائج. خلاف ذلك ، نرى أن جيل هو الأسرع في إلغاء التسلسل ، بينما يأتي Utf8Json في المركز الثاني. إنها أسرع مرتين أو ثلاث مرات من System.ext.Json . و System.ext.Json أسرع بحوالي 30٪ من Json.NET .



حتى الآن ، اتضح أن Newtonsoft.Json الشهير و System.Text.Json الجديد لديهما أداء أسوأ بكثير من منافسيهما. كانت هذه نتيجة غير متوقعة بالنسبة لي بسبب شعبية Newtonsoft.Jsonوكل الضجيج حول برنامج Microsoft System.Text.Json الجديد الأفضل أداءً . دعنا نتحقق من ذلك في تطبيق ASP.NET.



المعيار 4: عدد الطلبات في الثانية على خادم .NET



كما ذكرنا سابقًا ، فإن تسلسل JSON مهم جدًا لأنه موجود باستمرار في واجهات برمجة تطبيقات REST. application/jsonستحتاج طلبات HTTP إلى خادم يستخدم نوع المحتوى إلى إجراء تسلسل أو إلغاء تسلسل كائن JSON. عندما يقبل الخادم الحمولة في طلب POST ، يقوم الخادم بإلغاء التسلسل من JSON. عندما يعرض الخادم كائنًا في استجابته ، فإنه يسلسل JSON. تعتمد اتصالات خادم العميل الحديثة بشكل كبير على تسلسل JSON. لذلك ، لاختبار السيناريو "الحقيقي" ، فمن المنطقي إنشاء خادم اختبار وقياس أدائه.



لقد ألهمني اختبار أداء Microsoftحيث قاموا بإنشاء تطبيق خادم MVC وفحصوا الطلبات في الثانية. اختبار معايير Microsoft System.Text.Json و Newtonsoft.Json . في هذه المقالة ، سنفعل الشيء نفسه ، باستثناء أننا سنقارنهم بـ Utf8Json ، الذي أثبت أنه أحد أسرع برامج التسلسل في الاختبارات السابقة.

لسوء الحظ ، لم أتمكن من دمج ASP.NET Core 3 مع Jil ، لذا لا يتضمنه المعيار. أنا متأكد من أنه يمكن القيام بذلك بمزيد من الجهد ، لكن للأسف.


ثبت أن إنشاء هذا الاختبار أصبح أكثر صعوبة من ذي قبل. لقد قمت أولاً بإنشاء تطبيق ASP.NET Core 3.0 MVC ، تمامًا كما هو الحال في معيار Microsoft. لقد أضفت وحدة تحكم لاختبارات الأداء ، على غرار تلك الموجودة في اختبار Microsoft :



[Route("mvc")]
public class JsonSerializeController : Controller
{
 
    private static Benchmarks.Serializers.Models.ThousandSmallClassList _thousandSmallClassList
        = new Benchmarks.Serializers.Models.ThousandSmallClassList();
    
    [HttpPost("DeserializeThousandSmallClassList")]
    [Consumes("application/json")]
    public ActionResult DeserializeThousandSmallClassList([FromBody]Benchmarks.Serializers.Models.ThousandSmallClassList obj) => Ok();
 
    [HttpGet("SerializeThousandSmallClassList")]
    [Produces("application/json")]
    public object SerializeThousandSmallClassList() => _thousandSmallClassList;
}


عندما يستدعي العميل نقطة النهاية DeserializeThousandSmallClassList، سيقبل الخادم نص JSON ويلغي تسلسل المحتوى. هذه هي الطريقة التي نختبر بها إلغاء التسلسل. عندما يتصل العميل SerializeThousandSmallClassList، سيرد الخادم قائمة من 1000 SmallClassعنصر ، وبالتالي يسلسل المحتوى إلى JSON.



ثم نحتاج إلى إلغاء التسجيل لكل طلب حتى لا يؤثر على النتيجة:



public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();
            //logging.AddConsole();
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });


نحتاج الآن إلى طريقة للتبديل بين System.Text.Json و Newtonsoft و Utf8Json . الأمر سهل مع الأولين. بالنسبة لـ System.Text.Json ، لا تحتاج إلى القيام بأي شيء على الإطلاق. للتبديل إلى Newtonsoft ، قم بإضافة سطر واحد فقط إلى ConfigureServices :



public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews()
    //   Newtonsoft.   -     System.Text.Json
    .AddNewtonsoftJson()
    ;


ل Utf8Json، نحن بحاجة إلى إضافة منسقات الإعلام العرف InputFormatterو OutputFormatter. لم يكن الأمر بهذه السهولة ، ولكن في النهاية وجدت حلاً جيدًا على الإنترنت ، وبعد البحث في الإعدادات ، نجح الأمر. هناك أيضًا حزمة NuGet مع المُنسِّقات ، لكنها لا تعمل مع ASP.NET Core 3.



internal sealed class Utf8JsonInputFormatter : IInputFormatter
{
    private readonly IJsonFormatterResolver _resolver;
 
    public Utf8JsonInputFormatter1() : this(null) { }
    public Utf8JsonInputFormatter1(IJsonFormatterResolver resolver)
    {
        _resolver = resolver ?? JsonSerializer.DefaultResolver;
    }
 
    public bool CanRead(InputFormatterContext context) => context.HttpContext.Request.ContentType.StartsWith("application/json");
 
    public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
    {
        var request = context.HttpContext.Request;
 
        if (request.Body.CanSeek && request.Body.Length == 0)
            return await InputFormatterResult.NoValueAsync();
 
        var result = await JsonSerializer.NonGeneric.DeserializeAsync(context.ModelType, request.Body, _resolver);
        return await InputFormatterResult.SuccessAsync(result);
    }
}
 
internal sealed class Utf8JsonOutputFormatter : IOutputFormatter
{
    private readonly IJsonFormatterResolver _resolver;
 
    public Utf8JsonOutputFormatter1() : this(null) { }
    public Utf8JsonOutputFormatter1(IJsonFormatterResolver resolver)
    {
        _resolver = resolver ?? JsonSerializer.DefaultResolver;
    }
 
    public bool CanWriteResult(OutputFormatterCanWriteContext context) => true;
 
    
    public async Task WriteAsync(OutputFormatterWriteContext context)
    {
        if (!context.ContentTypeIsServerDefined)
            context.HttpContext.Response.ContentType = "application/json";
 
        if (context.ObjectType == typeof(object))
        {
            await JsonSerializer.NonGeneric.SerializeAsync(context.HttpContext.Response.Body, context.Object, _resolver);
        }
        else
        {
            await JsonSerializer.NonGeneric.SerializeAsync(context.ObjectType, context.HttpContext.Response.Body, context.Object, _resolver);
        }
    }
}


الآن لـ ASP.NET لاستخدام هذه المُنسق:



public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews()
 
    //   Newtonsoft
    //.AddNewtonsoftJson()
 
   //   Utf8Json
    .AddMvcOptions(option =>
    {
        option.OutputFormatters.Clear();
        option.OutputFormatters.Add(new Utf8JsonOutputFormatter1(StandardResolver.Default));
        option.InputFormatters.Clear();
        option.InputFormatters.Add(new Utf8JsonInputFormatter1());
    });
}


إذن هذا هو الخادم. الآن عن العميل.



عميل C # لقياس الطلبات في الثانية



لقد قمت أيضًا بإنشاء تطبيق عميل C # ، على الرغم من أن عملاء JavaScript سيسودون في معظم سيناريوهات العالم الحقيقي. لا يهم لأغراضنا. ها هو الكود:



public class RequestPerSecondClient
{
    private const string HttpsLocalhost = "https://localhost:5001/";
 
    public async Task Run(bool serialize, bool isUtf8Json)
    {
        await Task.Delay(TimeSpan.FromSeconds(5));
        
        var client = new HttpClient();
        var json = JsonConvert.SerializeObject(new Models.ThousandSmallClassList());
 
       //  ,    
        for (int i = 0; i < 100; i++)
        {
            await DoRequest(json, client, serialize);
        }
 
        int count = 0;
 
        Stopwatch sw = new Stopwatch();
        sw.Start();
 
        while (sw.Elapsed < TimeSpan.FromSeconds(1))
        {
            count++;
            await DoRequest(json, client, serialize);
        }
        
        Console.WriteLine("Requests in one second: " + count);
    }
 
    
    private async Task DoRequest(string json, HttpClient client, bool serialize)
    {
        if (serialize)
            await DoSerializeRequest(client);
        else
            await DoDeserializeRequest(json, client);
    }
    
    private async Task DoDeserializeRequest(string json, HttpClient client)
    {
        var uri = new Uri(HttpsLocalhost + "mvc/DeserializeThousandSmallClassList");
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        var result = await client.PostAsync(uri, content);
        result.Dispose();
    }
 
    private async Task DoSerializeRequest(HttpClient client)
    {
        var uri = HttpsLocalhost + "mvc/SerializeThousandSmallClassList";
        var result = await client.GetAsync(uri);
        result.Dispose();
    }
}


سيرسل هذا العميل الطلبات بشكل مستمر لمدة ثانية واحدة ، مع احتسابها.



النتائج



لذلك ، دون مزيد من اللغط ، ها هي النتائج:







يمكن العثور على مؤشرات أكثر دقة هنا


تفوق Utf8Json على أجهزة التسلسل الأخرى بهامش ضخم. لم تكن هذه مفاجأة كبيرة بعد الاختبارات السابقة.



من حيث التسلسل ، يعد Utf8Json أسرع مرتين من System.Text.Json و 4x أسرع من Newtonsoft . لإلغاء التسلسل ، يعد Utf8Json أسرع 3.5 مرة من System.Text.Json و 6 مرات أسرع من Newtonsoft .



المفاجأة الوحيدة بالنسبة لي هنا هي مدى ضعف عمل Newtonsoft.Json... ربما يكون هذا بسبب مشكلة UTF-16 و UTF-8. يعمل بروتوكول HTTP مع نص UTF-8. يقوم Newtonsoft بتحويل هذا النص إلى أنواع سلاسل .NET ، وهي UTF-16. هذا الحمل غير موجود في Utf8Json أو System.Text.Json ، اللذين يعملان مباشرة مع UTF-8.



من المهم ملاحظة أنه لا ينبغي الوثوق بهذه المعايير بنسبة 100٪ لأنها قد لا تعكس السيناريو الفعلي بالكامل. ولهذا السبب:



  • قمت بتشغيل كل شيء على جهازي المحلي - كل من العميل والخادم. في سيناريو العالم الحقيقي ، يكون الخادم والعميل على أجهزة مختلفة.
  • . , . . - . , , . , , GC. Utf8Json, .
  • Microsoft ( 100 000). , , , , .
  • . , - - .


كل الأشياء التي تم أخذها في الاعتبار ، هذه النتائج مذهلة جدًا. يبدو أنه يمكن تحسين وقت الاستجابة بشكل كبير عن طريق اختيار مُسلسل JSON المناسب. سيؤدي التبديل من Newtonsoft إلى System.Text.Json إلى زيادة عدد الطلبات بمقدار 2-7 مرات ، وسيتحسن التبديل من Newtonsoft إلى Utf8Json بمعدل 6-14 مرة. هذا ليس عادلاً تمامًا ، لأن الخادم الحقيقي سيفعل أكثر بكثير من مجرد قبول الحجج وإرجاع الكائنات. من المحتمل أن تقوم بأشياء أخرى أيضًا ، مثل العمل مع قواعد البيانات وبالتالي تنفيذ بعض منطق الأعمال ، لذلك قد يكون وقت التسلسل أقل أهمية. ومع ذلك ، فإن هذه الأرقام لا تصدق.



الاستنتاجات



دعونا نلخص:



  • System.Text.Json , Newtonsoft.Json ( ). Microsoft .
  • , Newtonsoft.Json System.Text.Json. , Utf8Json Jil 2-4 , System.Text.Json.
  • , Utf8Json ASP.NET . , , , ASP.NET.


هل هذا يعني أنه يجب علينا جميعًا التبديل إلى Utf8Json أو Jil؟ الجواب على ذلك ... ربما. تذكر ، Newtonsoft.Json صمد أمام اختبار الزمن وأصبح أشهر المسلسل لسبب ما. يدعم العديد من الميزات ، وقد تم اختباره مع جميع أنواع حالات الحواف ، ويحتوي على الكثير من الحلول والحلول الموثقة. يتم دعم كل من System.Text.Json و Newtonsoft.Json جيدًا. ستستمر Microsoft في استثمار الموارد والجهود في System.Text.Json حتى تتمكن من الاعتماد على دعم كبير. في حين أن جيل و Utf8Jsonتلقى عددًا قليلاً جدًا من الالتزامات في العام الماضي. في الواقع ، يبدو أنهم لم يتلقوا الكثير من الصيانة في الأشهر الستة الماضية.



أحد الخيارات هو دمج العديد من المسلسلات في تطبيقك. قم بالترقية إلى برامج تسلسلية أسرع للتكامل مع ASP.NET للحصول على أداء فائق ، ولكن استمر في استخدام Newtonsoft.Json في منطق عملك لتحقيق أقصى استفادة من مجموعة الميزات الخاصة بها.



آمل أن يحظى هذا المقال بإعجابكم. حظا سعيدا)



معايير أخرى



العديد من المعايير الأخرى التي تقارن العديد من المتسلسلات



عندما أعلنت Microsoft عن System.Text.Json ، أظهروا معيارهم الخاص بمقارنة System.Text.Json و Newtonsoft.Json . بالإضافة إلى التسلسل وإلغاء التسلسل ، يختبر هذا الاختبار فئة Document للوصول العشوائي ، Reader and Writer. لقد عرضوا أيضًا اختبار Query Per Second ، الذي ألهمني لإنشاء اختبار خاص بي.



يتضمن مستودع .NET Core GitHub مجموعة من المعايير المشابهة لتلك الموضحة في هذه المقالة. نظرت عن كثب في اختباراتهم للتأكد من أنني لم أرتكب أخطاءً بنفسي. يمكنك أن تجدهم فيحل المعايير الدقيقة .



جيل لديها قناعاتها المعايير التي تقارن جيل ، Newtonsoft ، Protobuf، و ServiceStack .



قام Utf8Json بنشر مجموعة من المعايير المتاحة على GitHub . هم أيضا اختبار المسلسلات الثنائية.



أجرى Alois Kraus اختبارًا متعمقًا ممتازًا لمسلسلات .NET الأكثر شيوعًا ، بما في ذلك المتسلسلات JSON والمسلسلات الثنائية ومتسلسلات XML. يتضمن معياره معايير .NET Core 3 و .NET Framework 4.8.






تعلم المزيد عن الدورة.






اقرأ أكثر:






All Articles