C# – JSON

C#
C#

JSON או JavaScript Object Notation הוא פורמט פשוט להעברת מידע, אשר ניתן לקרוא ולכתוב אותו בקלות, מה שהופך אותו לדבר שימושי ורב תכליתי שנוכל להיעזר בו רבות בכתיבת תכניות כאלה ואחרות. אילו אופרציות נוכל לבצע באמצעות JSON בתוכנית ה-C# שלנו?

במאמר זה נעבוד עם ספריית ה-JSON אשר מובנית ב-C#.
לשם תחילת העבודה נשתמש ב-System.Text.Json:

using System.Text.Json; 

Namespace זה כולל מגוון של כלים לעבודה עם אובייקטי JSON ובעזרתו נוכל לבצע סריאליזציה מאובייקטים לטקסט JSON וכמובן שגם ההיפך, כמו כן קיימת תמיכה מובנית ל-UTF-8.

JSON Parse

במתודה JsonDocument.Parse נוכל להשתמש על מנת לנתח "זרם" (Stream) UTF-8 אשר מייצג את ערך ה-JSON ולהפוך אותו לאובייקט JsonDocument.
לדוגמא נתאר מצב שבו אנו צריכים להכניס כמה ערכים לאובייקט JSON ולקרוא מתוכו לאחר מכן.
שימו לב לקטע הקוד הבא:

using System.Text.Json;

string data = @"[{""Name"": ""Ringo"", ""SureName"": ""Starr"", ""Proffesion"": ""Musician""},
{""Name"": ""Sam"", ""SureName"": ""Yosemite"", ""Proffesion"": ""driver""}]";

using JsonDocument document = JsonDocument.Parse(data);
JsonElement root = document.RootElement;

Console.WriteLine(root + "\n");

var person1 = root[0];
var person2 = root[1];
Console.WriteLine(person1);
Console.WriteLine(person2 + "\n");

Console.WriteLine(person1.GetProperty("Name"));
Console.WriteLine(person1.GetProperty("SureName"));
Console.WriteLine(person1.GetProperty("Proffesion"));

Console.WriteLine(person2.GetProperty("Name"));
Console.WriteLine(person2.GetProperty("SureName"));
Console.WriteLine(person2.GetProperty("Proffesion"));

בדוגמא זו ביצענו JSON Parse על מחרוזת פשוטה (שורה 6), ולאחר מכן הפכנו את המידע ל -JsonDocument (שורה 7).
ולבסוף יצרנו שני משתנים שכל אחד מהם מחזיק person אחד מתוך ה-JsonDocument (שורות 11-12).
מה שנשאר לנו זה להריץ את התוכנית על מנת שנוכל לקבל את הפלט הבא:

JSON Parse
JSON Parse

JSON Enumerate

במתודה JsonElement.EnumerateArray נוכל להשתמש על מנת שנוכל לבצע אינומרציה על ה-JsonDocument שלנו.
שימו לב שבדוגמא הקודמת היינו צריכים לנקוב בשמות המאפיינים על מנת להדפיס אותם, משהו שהפעם לא נצטרך לעשות משום שנוכל לרוץ בלולאה על כל המאפיינים:

using System.Text.Json;

string data = @"[{""Name"": ""Ringo"", ""SureName"": ""Starr"", ""Proffesion"": ""Musician""},
{""Name"": ""Sam"", ""SureName"": ""Yosemite"", ""Proffesion"": ""driver""}]";

using JsonDocument document = JsonDocument.Parse(data);
JsonElement root = document.RootElement;

var persons = root.EnumerateArray();

while (persons.MoveNext())
{
    var person = persons.Current;
    var properties = person.EnumerateObject();

    System.Console.WriteLine("\n" + person + "\n");

    while (properties.MoveNext())
    {
        var prop = properties.Current;
        Console.WriteLine($"{prop.Name}: {prop.Value}");
    }
}

בשורה 9 ביצענו אינומרציה על כל התכולה של ה-RootElement והכנסנו למשתנה persons, מה שנותן לנו מעין מערך של כל האלמנטים שמכיל ה-RootElement.
בלולאה החיצונית יצרנו משתנה person, נדפיס את הערכים שכל person מחזיק בכל אינטרוול של הלולאה לפי הסדר.
לאחר מכן יצרנו את המשתנה – properties, שהוא בעצם מערך של כל המאפיינים שמכיל כל אלמנט ב-RootElement (שורה 14).
ולבסוף הוספנו לולאה פנימית שבאמצעותה נוכל להדפיס את המאפיינים של כל אלמנט כאמור.
ומה שיישאר לנו לאחר מכן זה להריץ את התוכנית:

JSON enumerate
JSON Enumerate

JSON Serialize

בשפת C# קיימות מגוון של אפשרויות לפירוק או הרכבה של קבצים\אובייקטים מפורמט לפורמט אחר על מנת שנוכל להעביר נתונים וכו' ממערכת אחת למערכת אחרת, כאמור, ניתן לפרק אובייקט למגוון שפות אוניברסליות  (JSON במקרה שלנו), כלומר שגם נוכל לקחת קובץ כזה ולהרכיב ממנו אובייקט לתוכנית שלנו.
לצורך ההדגמה, נייצר את מחלקת person, שעל המאפיינים שלה נבצע סריאליזציה (תהליך הרכבה) לאובייקט ג'ייסון:

using System.Text.Json;

public class Person
{
    public string Name { get; set; }
    public string SureName { get; set; }
    public string Proffesion { get; set; }
    public int Age { get; set; }

    public Person(string name, string sureName, string proffesion, int age)
    {
        Name = name;
        SureName = sureName;
        Proffesion = proffesion;
        Age = age;
    }

    public override string ToString()
    {
        var options = new JsonSerializerOptions { WriteIndented = true };
        return JsonSerializer.Serialize(this, options);
    }
}

על מנת להציג את הערכים של מאפייני המופע נוכל למשל לדרוס את המתודה ToString (שורה 19) כך שתבצע סריאליזציה למאפייני המופע ותחזיר לנו אובייקט ג'ייסון אשר ניתן להדפסה בצורה קריאה.
שימו לב לשורה 20. ניתן להגדיר כל מיני אפשרויות לתהליך הסריאליזציה, במקרה זה כאמור, סידרנו את ההזחה של הפלט שיתקבל לאחר מכן.
כעת נרצה לייצר כמה מופעים של Person ולהדפיס אותם:

List<Person> persons = new()
{
    new Person("Ringo", "Starr", "Musician", 40),
    new Person("Sam", "Yosemite", "Driver", 70),
    new Person("Buggs", "Funny", "Rabbit", 26)
};

persons.ForEach(person => Console.WriteLine(person));

על מנת שנוכל לקבל את התוצאה הבאה:

JSON serialize
JSON Serialize

JSON Deserialize

פעולות הפירוק וההרכבה יכולות לפעול על איזה טייפ שנרצה, למשל מערכים או מילונים.
שימו לב ל-Code Snippet הבא שבו ניצור מילון, נבצע עליו סריאליזציה לאובייקט ג'ייסון, שאותו נפרק לאחר מכן בחזרה למילון:

using System.Text.Json;

var fruits = new Dictionary<int, string>
{
    {1, "Banana"},
    {2, "Apple"},
    {3, "Pear"},
    {4, "Peach"},
    {5, "Cherry"},
    {6, "Orange"},
};

Console.WriteLine("serialized Fruits:\n");
var serializedFruits = JsonSerializer.Serialize(fruits, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(serializedFruits);

Console.WriteLine("\ndeserialized Fruits:\n")
var deserializedFruits = JsonSerializer.Deserialize<Dictionary<int, string>>(serializedFruits);
foreach (var (key, value) in deserializedFruits!)
{
    Console.WriteLine($"{key}: {value}");
}

את הדה-סריאליזציה ביצענו בשורה 18. הפכנו את אובייקט הג'ייסון (שייצרנו בשורה 14 כאשר ביצענו סריאליזציה למילון שלנו) בחזרה למילון.
על מנת שנוכל להדפיס את המילון נוכל להיעזר ב-Tuple Deconstruction.
וכאשר נריץ את התוכנית נקבל את הפלט הבא:

JSON Deserialize
JSON Deserialize

Utf8 JSON Writer

נוכל גם להרכיב אובייקט ג'ייסון על יד שימוש ב-Utf8JsonWriter. ה-Code Snippet הבא ידגים זאת:

using System.Text.Json;
using System.Text;

using var memoryStream = new MemoryStream();
using var jsonWriter = new Utf8JsonWriter(memoryStream);

jsonWriter.WriteStartObject();
jsonWriter.WriteString("Name", "Bruce");
jsonWriter.WriteString("SureName", "Mee");
jsonWriter.WriteString("Proffesion", "Martial Artist");
jsonWriter.WriteNumber("Age", 36);
jsonWriter.WriteEndObject();
jsonWriter.Flush();

string text = Encoding.UTF8.GetString(memoryStream.ToArray());

Console.WriteLine(text);

בשורה 4 ייצרנו ואתחלנו מופע של MemoryStream ובשורה 5 את ייצרנו ואתחלנו את ה-Utf8JsonWriter.
שימו לב של-Utf8JsonWriter יש מגוון של מתודות שניתן להשתמש בהם:

  • בשורה 7 התחלנו את את כתיבת האובייקט על ידי שימוש במתודה WriteStartObject
  • בשורות 8-11 הזנו את הנתונים לתוך האובייקט באמצעות המתודות – WriteString ו-WriteNumber
  • בשורה 12 הצהרנו על סגירה של כתיבת האובייקט על ידי שימוש במתודה WriteENDObject
  • בשורה 13 השתמשנו במתודה Flush על מנת לעשות commit(ניתן לומר כי פעולה זו מעדכנת את כל הטקסט אל הפלט שיצא לאחר מכן)


טיפ
: אם אתם עובדים עם Visual Studio תוכלו לסמן את הטייפ Utf8JsonWriter וללחוץ F12, כך תוכלו לראות בדיוק איזה מתודות יש לו ומה הם עושות.

ולאחר מכן, בשורה 15 פירקנו את ה-MemoryStream למחרוזת פשוטה שנוכל להדפיס לאחר מכן.
וכשנריץ את התוכנית, נקבל את הפלט הבא:

Utf8JsonWriter
Utf8JsonWriter  

למידע נוסף על סריאלזציה ודה-סראליזציה של ג'ייסון באתר של מייקרוסופט יש ללחוץ כאן

רוצים לשתף את המדריך?

אהבתכם את המדריך? פתר לכם תקלה? הזמינו את כותב המדריך לכוס קפה

גולשים יקרים, רוב התכנים המוצגים באתר נכתבים בהתנדבות מלאה מתוך כוונה להנגיש מידע עבורכם. אם נתקלתם במדריך חינמי שפתר לכם תקלה או לימד אתכם משהו חדש שלא ידעתם, וברצונכם לתגמל את כותב המדריך או סתם להזמין אותו לכוס קפה, הינכם יותר ממוזמנים לתרום.

כתיבת תגובה

הזמינו אותי לכוס קפה
buy me coffee

אהבתכם את המדריך? פתר לכם תקלה? הזמינו את כותב המדריך לכוס קפה

גולשים יקרים, רוב התכנים המוצגים באתר נכתבים בהתנדבות מלאה מתוך כוונה להנגיש מידע עבורכם. אם נתקלתם במדריך חינמי שפתר לכם תקלה או לימד אתכם משהו חדש שלא ידעתם, וברצונכם לתגמל את כותב המדריך או סתם להזמין אותו לכוס קפה, הינכם יותר ממוזמנים לתרום.