CodeGym /Kurslar /C# SELF /Dinamik strukturlar: JObje...

Dinamik strukturlar: JObject, JArray

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş

Əvvəlki mühazirələrdə biz həmişə möhkəm type-lı strukturlarla işləyirdik. Məsələn, bizim Person sinifimiz var ki, onu JSON-a serializasiya edir və geri alırıq:

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

Amma bəzən məlumatın strukturunu əvvəlcədən bilmirsən. Məsələn:

  • Xarici servisin parserini yazırsan və cavabın strukturu sabit deyil.
  • Yalnız müəyyən hissəni çıxarmaq lazımdır, bütöv sinifi doldurmağa ehtiyac yoxdur.
  • JSON-u "uçuşda" redaktə etmək və ya yaratmaq lazımdır, dinamik şərtlərə əsaslanaraq.

Elə burada "dinamik strukturlar" — JSON ağacını açar-qiymət cütləri kimi saxlayan, əvvəlcədən C# sinifi tələb etməyən obyektlər — işə düşür.

Niyə əksər hallarda Newtonsoft.Json istifadə olunur

.NET-də JSON ilə işləmək üçün iki əsas oyunçu var:

  • System.Text.Json — Microsoft-un daxil edilmiş kitabxanası (.NET Core 3.0-dan inkişaf edir).
  • Newtonsoft.Json (Json.NET) — məşhur kitabxana, C#-a JObjectJArray kimi sinifləri gətirib.

Mühazirənin yazıldığı vaxtda System.Text.Json hələ JObject/JArray-ın eyni rahatlığında tam ekvivalent təklif etmir. Ona görə mürəkkəb/naməlum JSON-strukturlarını tez-tez analiz etmək və ya modifikasiya etmək lazım olarsa, adətən Newtonsoft.Json seçilir.

Əsas tiplər: JObject, JArray, JValueJToken ailəsi

  • JToken — bütün JSON-node-lar üçün baza tipidir.
  • JObject — JSON-obekt { ... }, açar-qiymət cütlərinin toplusu.
  • JArray — massiv [ ... ].
  • JValue — ayrıca qiymət (42, "mətin", true, null).

İdeya sadədir: JSON-u parse edirsən — bu tokenlərdən ibarət "ağac" alırsan və onun üzərində gəzə, axtara, dəyişdirə, silə və əlavə edə bilirsən.

2. Naməlum JSON-un oxunması

Tutaq ki, bizə belə bir JSON gəldi və biz onun üçün əvvəlcədən sinif yazmaq istəmirik və ya mümkün deyil:

{
  "status": "ok",
  "amount": 150.5,
  "items": [
    {
      "name": "book",
      "qty": 1
    },
    {
      "name": "pen",
      "qty": 3
    }
  ]
}

Newtonsoft.Json ilə bunu ağaca çevirib uçuşda tədqiq edə bilərik.

Nümunə: JSON-u JObject-ə oxumaq

using Newtonsoft.Json.Linq;

string json = @"{
  ""status"": ""ok"",
  ""amount"": 150.5,
  ""items"": [
    { ""name"": ""book"", ""qty"": 1 },
    { ""name"": ""pen"", ""qty"": 3 }
  ]
}";

// Sətiri parse edib ağacı alırıq
JObject root = JObject.Parse(json);

// Xüsusiyyətləri lüğət kimi götürürük
string status = (string)root["status"]; // "ok"
double amount = (double)root["amount"]; // 150.5

// items — massivdir, yəni JArray
JArray items = (JArray)root["items"];

// Massivi dövr edirik
foreach (JObject item in items)
{
    string name = (string)item["name"];
    int qty = (int)item["qty"];
    Console.WriteLine($"Məhsul: {name}, Say: {qty}");
}

Çox rahatdır: sinif elan etməyə ehtiyac yoxdur — lazım olan parçaları tez çıxarırsan.

3. İndeksatorlar və dinamik giriş

İndeksatorlar:

  • Obyektdə: root["status"], root["items"]
  • Massivdə: items[0], items[1]

Dərhal lazım olan tipdə qiymət almaq üçün cast istifadə et: (string), (int), (bool), (double) — kitabxana tipə avtomatik çevirmə edir.

Əgər məlumatlar olmaya bilərsə, ehtiyatlı ol: mövcud olmayan açara giriş null qaytaracaq və düzgün olmayan cast istisna yaradacaq. Daha yaxşı yoxlama metodlarından istifadə et:

if (root.TryGetValue("amount", out var token))
{
    double amount = token.Value<double>();
    // Bu üsul rahatdır: Value<T>() — birbaşa çevirir
}

Daxili obyektlər və massivlər də oxunur sadəcə:

// İkinci məhsulu götürmək
JObject secondItem = (JObject)root["items"][1];
string itemName = (string)secondItem["name"]; // "pen"

Dinamika ilə də mümkündür:

dynamic droot = root;
Console.WriteLine(droot.status); // "ok"

Amma unutma: dynamic ilə compiler sahələri yoxlamır — xətalar yalnız çalışma zamanı ortaya çıxacaq.

4. JSON-açını uçuşda dəyişdirmək

Element əlavə etmək

root["currency"] = "RUB";        // Yeni xüsusiyyət əlavə etdik
items.Add(new JObject
{
    ["name"] = "eraser",
    ["qty"] = 2
});

Dəyişmə və silmə

root["status"] = "done";         // Qiyməti dəyişdik
items[0]["qty"] = 5;             // Birinci məhsulun sayını artırdıq
items.RemoveAt(1);               // İkinci məhsulu sildik

Nəticəni sətirə saxlamaq

string modifiedJson = root.ToString();
// Və ya root.ToString(Formatting.Indented) daha gözəl üçün

5. Sıfırdan JSON-struktur yaratmaq

var person = new JObject
{
    ["name"] = "Alice",
    ["age"] = 22,
    ["languages"] = new JArray { "C#", "Python" },
    ["isStudent"] = true
};

Console.WriteLine(person.ToString(Newtonsoft.Json.Formatting.Indented));
{
  "name": "Alice",
  "age": 22,
  "languages": [
    "C#",
    "Python"
  ],
  "isStudent": true
}

Faydalıdır, əgər xarici API-yə yalnız hissə məlumat qaytarmaq və ya şərtlərə görə JSON yığmaq lazımdırsa.

6. JObject-dən öz obyektimizi necə yığmaq

Bəzən elastik JSON-u möhkəm C#-obyektinə çevirmək lazımdır. Variantlar:

  • Adi deserializasiya: JsonConvert.DeserializeObject<MyClass>(...).
  • JObject-dən lazım olan sahələri çıxarıb obyekt əl ilə yığmaq.
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// Tutaq ki, belə bir JSON gəldi:
string incoming = @"{ ""name"":""Bob"", ""age"":30, ""extraField"":true }";

JObject j = JObject.Parse(incoming);

// Obyekti əl ilə yığırıq — yalnız lazım olan sahələr
var person = new Person
{
    Name = (string)j["name"],
    Age = (int)j["age"],
    // extraField bizə lazım deyil — və yaxşıdır!
};

7. Nümunə xətalar və incəliklər: tipik tələlər

Dinamik JSON-strukturlarla işləmək çevikdir, amma "sualtı daşlar" var:

  • Mövcud olmayan açar/elementə müraciət null verir; qiymətli tipə birbaşa cast istisna yaradacaq.
  • Gözlənilən tiplə uyğunsuzluq (obyekt gözlənilir, amma qiymət gəldi) — cast xətası.
  • Obyektdəki sahələri gəzərkən Properties()-dən istifadə edin:
foreach (var prop in root.Properties())
{
    Console.WriteLine($"Sahə: {prop.Name}, Qiymət: {prop.Value}");
}
  • Newtonsoft.Json-la LINQ-oxşar sorğularla işləmək rahatdır (filter, axtarış):
var expensiveItems = items.Where(obj => (int)obj["qty"] > 2);
foreach (var item in expensiveItems)
    Console.WriteLine(item);

8. JObject/JArray ilə işləyərkən tipik səhvlər

Səhv №1: gözlənilən sahənin olmaması və ya tipin uyğun gəlməməsi. Çox vaxt developer hesab edir ki, obyektdə müəyyən sahə olacaq, amma ya yoxdur, ya da başqa tipdədir. Əgər obyekt gözlənilirsə, amma rəqəm gəlibsə, cast zamanı istisna yaranacaq. İstifadədən əvvəl mövcudluğu və tipi yoxlayın.

Səhv №2: null üçün yoxlama etmədən daxili sahələrə müraciət etmək. JSON-da daxil edilən obyektlər olduqda və açarlar fərqli və ya yoxdursa, mövcud olmayan sahəyə müraciət etmək çökməyə səbəb ola bilər. Daxili node-ları oxumadan əvvəl null yoxlaması edin.

Səhv №3: qiymətli tipə cast edərkən dəyərin null olması. Əgər açar mövcuddursa amma onun qiyməti null-dırsa, belə ifadə: (int)j["age"] istisna yaradacaq. Value<T>() istifadə edin — o default dəyər qaytaracaq (məsələn, int üçün 0, sətirlər üçün null).

Səhv №4: məhdudiyyətsiz şəkildə dinamik obyektlərə aludəçilik, sərt modellər yerinə. Həddindən artıq mürəkkəb strukturlar üçün C# sinifləri yazmaq daha rahat və təhlükəsizdir: bu səhvləri azaldar və kodun oxunaqlılığını artırar. Dinamikanı yalnız struktur həqiqətən naməlum və ya çox dəyişkəndirsə istifadə et.

İndi bilirsən ki, necə tez və təhlükəsiz şəkildə JObjectJArray vasitəsilə JSON-strukturlarını parse etmək, dəyişdirmək və yaratmaq olar, hətta əvvəlcədən təsvir olunmuş modellər olmadan.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION