1. Giriş
Əgər sizin tələblər default davranışla üst-üstə düşürsə, hər şey yaxşıdır. Amma çox vaxt müştəri (və ya üçüncü tərəf backend) öz formatını tələb edir: hər yerdə camelCase, tarixlər — ISO 8601, null-ların ötürülməsi/skipp edilməsi, custom konverterlər və integratorun digər xoşbəxtlikləri.
Belə olan yerdə səhnəyə bizim yeni dostumuz gəlir — sinif JsonSerializerOptions.
Əgər serializasiya bir mətbəx olsaydı, bu sinif sizin ədviyyatlarınız, qazançlarınız və sirli inqridiyentlərinizdir ki, serializasiyanı öz zövqünüzə görə dadlandırasınız.
Necə istifadə etmək olar JsonSerializerOptions
Serializasiya və ya deserializasiya prosesini custom etmək üçün sadəcə options obyektini serializer metodlarına ötürürük:
using System.Text.Json;
var options = new JsonSerializerOptions
{
// Burada sizin sazlamalar olacaq
};
string json = JsonSerializer.Serialize(myObject, options);
var obj = JsonSerializer.Deserialize<MyType>(json, options);
Belə pattern hər yerdə rast gəlinir: siz JsonSerializerOptions yaradırsınız, onları öz zövqünüzə görə sazlayırsınız (aşağıya baxın) və serializer metodlarına Serialize/Deserialize verirsiniz.
Vacib: Eyni JsonSerializerOptions obyekti bir neçə serializasiya üçün təkrar istifadə oluna bilər (və hətta belə etmək məsləhətdir).
2. Əsas sazlamalar JsonSerializerOptions
Gəlin bu sinifin ən populyar "pərlərini" və "switch"lərini nəzərdən keçirək.
JSON formatlanması — WriteIndented
Sizi bir sətirlik JSON-lar gözünüzü qamaşdırır? Problem deyil — gözəl indentasiya üçün WriteIndented-i açın!
var options = new JsonSerializerOptions
{
WriteIndented = true // Gözəl, "insan üçün" JSON
};
var person = new Person { Name = "Anna", Age = 30 };
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json);
Çıxış:
{
"Name": "Anna",
"Age": 30
}
WriteIndented = true yoxdursa, darıxdırıcı {"Name":"Anna","Age":30} alacaqsınız. Production-da adətən "minified" JSON istifadə olunur (kiçik olur), debug və loglar üçün isə formatlanmış.
Case-naming — PropertyNamingPolicy
Tez-tez API tələb edir ki, property adları camelCase stilində olsun (məsələn, firstName əvəzinə FirstName). .NET-də property-lər adətən PascalCase olur, buna görə PropertyNamingPolicy faydalıdır:
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
var person = new Person { Name = "Oleg", Age = 25 };
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json); // {"name":"Oleg","age":25}
Əgər xüsusi stil lazımdırsa (məsələn, hamısı BÖYÜK hərflərlə), öz JsonNamingPolicy implementasiyanızı yaza bilərsiniz. Adətən CamelCase kifayətdir.
3. Property-lərin ignor edilməsi
null-dəyərləri ötürmək ya yox — DefaultIgnoreCondition
Bəzən istəyirsiniz ki, dəyəri boş (null) olan sahələr ümumiyyətlə JSON-a düşməsin. Səbəbi — daha kompakt JSON, yaxud xarici sistem null-ları qəbul etmir.
Bu üçün DefaultIgnoreCondition-dən istifadə edin:
using System.Text.Json.Serialization;
var options = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
var person = new Person { Name = null, Age = 22 };
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json); // {"Age":22}
Əgər yalnız null-ları deyil, həm də default dəyərləri (məsələn, int=0) ignor etmək istəyirsinizsə, WhenWritingDefault-dən istifadə edin:
options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault;
Private property-ləri ignor etmək — IncludeFields və [JsonInclude]
Default üzrə yalnız public və açıq setter-ə malik property-lər serializasiya olunur. Əgər həm də fields-ları serializasiya etmək istəyirsinizsə:
var options = new JsonSerializerOptions
{
IncludeFields = true
};
Sinif nümunəsi:
public class Item
{
public string Name;
public int Id { get; set; }
}
var item = new Item { Name = "Book", Id = 12 };
string json = JsonSerializer.Serialize(item, options);
// {"Name":"Book","Id":12}
Private field/property-lərin serializasiyası üçün [JsonInclude] atributundan da istifadə etmək olar, amma bu ayrıca mühazirənin mövzusudur.
4. Dəyərlərin konvertasiyası
Tarixlərin formatlanması — Converters
Default olaraq System.Text.Json tarixləri sərt şəkildə ISO 8601-də serializasiya edir (məsələn, "2023-12-27T15:30:45.123Z"), və bu demək olar ki, həmişə rahatdır. Amma bəzən tarix/vaxt formatı xüsusi olmalıdır.
Bunun üçün öz konverterlərinizi əlavə edirsiniz. Sadə nümunə:
using System.Text.Json;
using System.Text.Json.Serialization;
public class CustomDateTimeConverter : JsonConverter<DateTime>
{
private string _format = "yyyyMMdd";
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var date = reader.GetString();
return DateTime.ParseExact(date, _format, null);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(_format));
}
}
// Konverterdən istifadə
var options = new JsonSerializerOptions();
options.Converters.Add(new CustomDateTimeConverter());
var dateObj = new { Date = new DateTime(2022, 1, 5) };
string json = JsonSerializer.Serialize(dateObj, options); // {"Date":"20220105"}
5. Faydalı incəliklər
Deserializasiya zamanı property adlarının registerini nəzərə almamaq — PropertyNameCaseInsensitive
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var json = "{\"name\":\"Vasya\",\"age\":33}";
var person = JsonSerializer.Deserialize<Person>(json, options);
// person.Name == "Vasya"
Yerləşmə (nesting) və obyektlərin maksimum səviyyəsinin idarəsi — MaxDepth
var options = new JsonSerializerOptions
{
MaxDepth = 32 // Default 64
};
Amma əgər obyektləriniz sonsuz dərinlikdə ola bilərsə — məsələn, valideyn və uşaqa referans verən ağac — modeli başqa cür dizayn etmək daha yaxşıdır.
JSON-də şərhlər — ReadCommentHandling (deserializasiya)
JSON rəsmi olaraq şərhləri dəstəkləmir, amma bəzən "//" tipli "kreativ" fayllarla rastlaşırlar.
var options = new JsonSerializerOptions
{
ReadCommentHandling = JsonCommentHandling.Skip
};
string json = "{\n \"Name\": \"Ivan\", // İstifadəçinin adı\n \"Age\": 30\n}";
var person = JsonSerializer.Deserialize<Person>(json, options);
Xüsusi simvolların dəstəyi — Encoder
Bəzən serializatorun simvolları necə escape etməsini idarə etmək lazımdır (məsələn, kiril hərflərini \uXXXX-ə çevirməmək üçün). Öz encoderinizi göstərə bilərsiniz:
using System.Text.Encodings.Web;
var options = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
Diqqətlə istifadə edin, yoxsa emoji/ideogrammalarınız gözlənilmədən Unicode-sekvensiyalara "gedə" bilər!
6. Serializasiya sazlanmasında tipik səhvlər
Səhv №1: public setter-in unutulması. Field və ya property serializasiya olunmur, çünki onun public setter-i yoxdur, ya da o private-dır.
Səhv №2: null-ların yanlış ignor edilməsi. DefaultIgnoreCondition açıq olduqda, null olan property-lər JSON-a düşməyəcək, halbuki siz bunu gözləmirdiniz.
Səhv №3: tarix formatının səhv olması. Tarix gözlənildiyi kimi serializasiya olunmur — custom konverter (JsonConverter) əlavə edin.
Səhv №4: property-lərin sabit sıra ilə olacağını gözləmək. JSON standartı sahələrin sıra qaydasını zəmanət etmir. Əgər API sıralama tələb edirsə, modeli dəyişmək və ya üçüncü tərəf kitabxanasından istifadə etmək lazım gələcək.
Səhv №5: serializasiya və deserializasiya zamanı fərqli sazlamalar. Əgər yazma və oxuma üçün eyni JsonSerializerOptions-u istifadə etmirsinizsə, adların registeri və formatlarla bağlı problemlər yarana bilər.
GO TO FULL VERSION