1. Giriş
Kolleksiyaların “qutudan çıxanda” ideal şəkildə serialize/deserialize olunduğunu düşünmək istəsəniz də, real layihələrdə çox vaxt belə olmur. Bəzən müəyyən kolleksiyaları serialization-dən gizlətmək lazımdır — məsələn, daxili cache edilmiş məlumatlar. Bəzən kolleksiyalı property-ləri API contract-a uyğunlaşdırmaq üçün yenidən adlandırmaq tələb olunur. Bəzi hallarda hansı elementlərin saxlanılacağını və ya gözardı ediləcəyini idarə etmək, ya da kolleksiyanı xüsusi şəkildə çevirmək vacibdir ki, nəticə JSON digər servislər üçün anlaşıqlı və “oxunaqlı” olsun.
Xoşbəxtlikdən, System.Text.Json serialization-ı atributlar vasitəsilə həm kolleksiyalara, həm də ayrı-ayrı elementlərə tətbiq edərək sadə və aydın idarə etmə üsulu təklif edir. Bu bölümdə praktik nümunələrlə bu mexanizmi daha dərindən nəzərdən keçirəcəyik.
2. Kolleksiya property-lərini istisna etmək: [JsonIgnore]
Sadə nümunədən başlayaq. Sinifinizdə serialize edilməməli olan kolleksiya ola bilər — məsələn, müvəqqəti, cache edilmiş və ya həssas məlumatlar. Nə etmək lazımdır? Təbii ki, [JsonIgnore]!
Tutaq ki, bizim Library sinifimiz var və ona yalnız sürətli çıxış üçün istifadə olunan List<Book> tipli Cache property-si əlavə etmişik:
using System.Text.Json.Serialization;
public class Library
{
public string Name { get; set; }
public List<Book> Books { get; set; }
[JsonIgnore]
public List<Book> Cache { get; set; } // Serialize olunmur!
}
// İstifadə nümunəsi:
var library = new Library
{
Name = "Baş kitabxana",
Books = new List<Book>
{
new Book { Title = "Sehrli vadı", Author = new Author { Name = "Tuve Yanssen", BirthYear = 1914 } }
},
Cache = new List<Book>
{
new Book { Title = "Milçəklərin sərdarı", Author = new Author { Name = "William Golding", BirthYear = 1911 } }
}
};
string json = JsonSerializer.Serialize(library, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(json); // JSON-da Cache property-si yoxdur!
Serialization nəticəsi təxminən belə olacaq:
{
"Name": "Baş kitabxana",
"Books": [
{
"Title": "Sehrli vadı",
"Author": {
"Name": "Tuve Yanssen",
"BirthYear": 1914
}
}
]
}
Görürsünüz? Xarici dünyaya heç bir “cache” görünmür. [JsonIgnore] olan hər şey gizlidir və etibarlıdır, sanki Wi‑Fi şifrini başında saxlayırsınız.
3. Kolleksiyaların yenidən adlandırılması: [JsonPropertyName]
Tez-tez belə API-larla qarşılaşırsınız: məsələn, JSON-da "items" gözləyirlər, amma C#-da sahə adınız "Books"dir? Yaxud C# sahəsini dəyişmək istəmirsiniz amma JSON-da fərqli ad olmalıdır?
Belə olunur:
using System.Text.Json.Serialization;
public class Library
{
public string Name { get; set; }
[JsonPropertyName("items")]
public List<Book> Books { get; set; }
[JsonIgnore]
public List<Book> Cache { get; set; }
}
// Serialize:
var library = new Library { Name = "Filial №1", Books = new List<Book>() };
string json = JsonSerializer.Serialize(library, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(json);
Nəticə:
{
"Name": "Filial №1",
"items": []
}
Qeyd edin ki, deserialization zamanı da JSON-dakı items C#-dakı Books-ə düzgün map ediləcək — iki tərəfli magiya işləyir.
4. Kolleksiyaların və onların elementlərinin serialization-ını idarə etmək
Bunun üçün JsonIgnoreCondition.WhenWritingNull və/və ya nullable tiplərindən istifadə etmək lazım gələcək.
Bəzən kolleksiya sadəcə optional (ixtiyari) sahə olur. Məsələn, yeni yaradılmış kitabxanada hələ kitablar yoxdur. JSON-da books: null göstərilməsini istəmirsinizsə, bunu opsiyalar vasitəsilə idarə edə bilərsiniz:
var library = new Library { Name = "Boş kitabxana" };
// Books initialize olunmayıb = null
var options = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = true
};
string json = JsonSerializer.Serialize(library, options);
Console.WriteLine(json);
Nəticə:
{
"Name": "Boş kitabxana"
}
Əgər sizin boş siyahınız varsa (amma null deyil), serializer "books": [] verəcək. Bu vacib fərqdir: bəzən sahə null olarsa onu gizlətmək, amma boş siyahını göstərmək lazım olur.
5. Elementlərin property-lərində [JsonIgnore] atributu
Serialization atributları koleksiya elementlərinin içində də işləyir. Siyahıdakı hər obyektin ayrı-ayrı property-lərini gizlədə bilərsiniz.
public class Book
{
public string Title { get; set; }
public Author Author { get; set; }
[JsonIgnore]
public string InternalCode { get; set; }
}
İndi Books kolleksiyasından kitab serialize olunanda InternalCode JSON-da görünməyəcək.
6. “İndekslərlə” və ya nested strukturlarla kolleksiyalara müraciət
Bəzən kolleksiyaları sadəcə array kimi deyil, məsələn “map” (dictionary) kimi serialize etmək lazımdır — əgər hər kitabın unikal identifikatoru varsa. Bu halda elementlər üçün xüsusi atributlara ehtiyac yoxdur, sadəcə dictionary property-si elan edin:
public class Library
{
[JsonPropertyName("catalog")]
public Dictionary<string, Book> BookCatalog { get; set; }
}
Serialize edərkən dictionary açar-dəyər cütlükləri olan obyektə çevriləcək:
var library = new Library
{
BookCatalog = new Dictionary<string, Book>
{
["978-5-699-12345-6"] = new Book { Title = "Lüğət", Author = new Author { Name = "Naməlum", BirthYear = 2000 } }
}
};
JSON:
{
"catalog": {
"978-5-699-12345-6": {
"Title": "Lüğət",
"Author": {
"Name": "Naməlum",
"BirthYear": 2000
}
}
}
}
Belə təqdimat API vasitəsilə açar ilə obyekt arasındakı əlaqəni qorumaq lazım olduqda əlverişlidir.
7. Kolleksiyaların serialization-ını idarə edərkən səhvlər və çətinliklər
Əgər koleksiyada bütün elementlər düzgün initialize olunmayıbsa (məsələn, siyahıda null elementlər varsa), default halda System.Text.Json belə elementləri massivdə null kimi yazacaq.
Hətta əgər DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull təyin olunubsa, massiv içərisindəki null elementlər qalacaq — bu qayda obyektin property-lərinə aiddir, kolleksiyanın içindəkilərə yox. Bunu aradan qaldırmaq üçün kolleksiyanı əvvəlcədən təmizləyin: RemoveAll(b => b == null).
Deserialization zamanı tez-tez baş verən səhvlərdən biri adların uyğun gəlməməsidir. Əgər [JsonPropertyName] yazmağı unutmusunuzsa, sinif JSON-dan Books field-ını gözləyəcək, amma siz JSON-da items göndərmisinizsə, kolleksiya dolmayacaq və boş qalacaq. Adların düzgünlüyünü həmişə yoxlayın!
8. Cədvəl: əsas atributlar harada tətbiq olunur
| Atrubut | Kolleksiyalara tətbiq olunarmı? | Kolleksiya elementlərinə tətbiq olunarmı? | İstifadə nümunələri |
|---|---|---|---|
|
bəli | bəli | Siyahını və ya Book içində bir sahəni gizlətmək |
|
bəli | bəli | Books → items və ya Title → name kimi ad dəyişdirmək |
|
bəli | bəli | Private property-ləri serialization-a daxil etmək |
|
bəli | bəli | Siyahı üçün xüsusi converter təyin etmək |
9. Atributlarla kolleksiyaların serialization sxemi
+-------------+
| Library |
+-------------+
| Name -- "Name" kimi serialize olunur
| Books -- [JsonPropertyName("items")], "items": [...] kimi serialize olunur
| Cache -- [JsonIgnore], serialize olunmur
| BookCatalog -- [JsonPropertyName("catalog")], "catalog": {...} kimi serialize olunur
JSON nəticəsi təxminən belədir:
{
"Name": "Şəhər kitabxanası",
"items": [
{
"Title": "1984",
"Author": {
"Name": "George Orwell",
"BirthYear": 1903
}
},
{
"Title": "Böyük ümidlər",
"Author": {
"Name": "Charles Dickens",
"BirthYear": 1812
}
}
],
"catalog": {
"978-1234567890": {
"Title": "Cthulhu-nun çağırışı",
"Author": {
"Name": "Howard Phillips Lovecraft",
"BirthYear": 1890
}
}
}
}
10. Praktiki əhəmiyyəti və müsahibələrdə, real layihələrdə nəzərə alınmalı xüsusiyyətlər
“Həqiqi” şəraitdə həmişə xarici API contract-ını və serialization tələblərini nəzərə almaq lazımdır. Daxili kolleksiyaları “gizlətməyi”, adların registerini və stilini qorumağı, bəzən isə client versiyasına görə serialization sxemini dinamik dəyişməyi bacarmaq vacibdir.
Müsahibələrdə tez-tez verilən suallar:
- Yalnız müəyyən hissəni necə serialize etmək olar?
- Kolleksiya property-sinin JSON-a düşməməsi necə təmin edilir?
- C# və JSON property adları fərqlidirsə onları necə uyğunlaşdırmaq olar?
- Kolleksiya daxilində konkret elementləri (məsələn, konfidensial məlumatı) serialization-dən gizlətmək olarmı?
Cavablar əsasən atributların və serialization opsiyalarının düzgün istifadəsi ətrafında dönür: [JsonIgnore], [JsonPropertyName], JsonSerializerOptions və kolleksiyanın məzmununu düşünülmüş şəkildə işləmək.
GO TO FULL VERSION