1. Serializasiya zamanı atributlər nəyə lazımdır?
Obyektləri JSON və ya XML-ə serializasiya edəndə, bu, sanki otağınızı robot-tozsoranla skan etmək kimidir. Göz qabağında olan hər şey (public property-lər/field-lər) "torbaya" (fayla və ya sətirə) düşür, qalanı isə gözardı edilir. Amma bəzən siz istəmirsiniz ki, robot cüzdanınızdakı məzmunu ifşa etsin, yaxud əşyaları başqa adla qoymaq istəyirsiniz — məsələn, rusca yox, ingiliscə deyil.
Elə burada atributlər ortaya çıxır! Onlar serializasiya prosesini idarə etməyə imkan verir: artıqları gizlətmək, adları dəyişdirmək, sıralama təyin etmək, obyektin müəyyən hissələrini yox saymaq və ya serializer-ə xüsusi qaydalarınız olduğunu demək. Bu, əşyaların üzərinə yapışdırılan etiketlər kimidir: "toxunma", "xüsusi", "JSON-də yenidən adlandır".
Serializasiyaya nəzarətin tipik vəzifələri
- Çıxış sənədində property-in və ya field-in adını dəyişmək (məsələn, JSON-da FirstName əvəzinə "first_name" etmək)
- Bəzi field/property-ləri serializasiyadan və ya deserializasiyadan gizlətmək (məsələn, şifrələr, daxili sayğaclar)
- Defolt dəyərlərin və ya null-dəyərlərin emalına nəzarət etmək
- Elementlərin sırasını təyin etmək (XML üçün aktualdır)
- XML-elementlər üçün əlavə parametrlər (atributlar) təsvir etmək
Hər bir serializasiya platforması — istər System.Text.Json, istər Newtonsoft.Json və ya XmlSerializer — bu məqsədlər üçün öz atributlarından istifadə edir.
2. System.Text.Json üçün atributlər: müasir və trend
.NET-in klassik JSON serializer-i kifayət qədər faydalı atributlar siyahısını dəstəkləyir, onlar System.Text.Json.Serialization namespace-ində yerləşir.
Ən faydalı atributlar:
| Atribut | Nəyə xidmət edir | İstifadə nümunəsi |
|---|---|---|
|
Property-in adını JSON-da çevirir | |
|
Property-i serializasiyadan tamamilə çıxarır | |
|
Public field-i (yalnız property deyil) serializasiya edir | |
|
Müəyyən şərtlər altında property-i ignore etmək | |
İstifadə nümunələri:
using System.Text.Json.Serialization;
public class Person
{
[JsonPropertyName("first_name")]
public string FirstName { get; set; } // JSON-da ad 'first_name' olacaq
[JsonIgnore]
public string Password { get; set; } // JSON-a düşməyəcək
[JsonPropertyName("born_year")]
public int? YearOfBirth { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string Nickname { get; set; } // Əgər null-disə — JSON-a düşməyəcək
}
Gəlin belə bir insanı serializasiya edək:
var person = new Person
{
FirstName = "Ivan",
Password = "123456",
YearOfBirth = 2000,
Nickname = null
};
string json = JsonSerializer.Serialize(person);
// json: {"first_name":"Ivan","born_year":2000}
Nəzərə alın: həm şifrə, həm də ləqəb JSON-dan itdi! (Şifrə — çünki həmişə ignore edilir, ləqəb isə yalnız null olduqda).
Niyə bu vacibdir? Praktikada tez-tez istəmirsiniz ki, client tərəfi (və ya pis niyyətli) kritik məlumatları görsün: şifrələr, token-lər, sayğaclar, daxili zaman damğaları. [JsonIgnore] və oxşar atributlarla bunu bir sətirdə həll etmək olur.
3. Newtonsoft.Json üçün atributlər: çeviklik lideri
Newtonsoft.Json ilə işləyirsinizsə (sənədləşmə burada), imkanlar daha da genişlənir (və köhnə layihələrə alışmışsınızsa, bir az daha rahat gəlsin).
Əsas atributlar:
| Atribut | Təyinatı |
|---|---|
|
JSON-da property-in adını, eləcə də sıranı, tələb olunmasını və s. təyin edir |
|
Field/Property-i serializasiyadan çıxarır |
|
Deserializasiya zamanı mütləq olmasını tələb edir |
|
Mürəkkəb hallar üçün öz konverterinizi göstərməyə imkan verir |
|
Defolt dəyərlərin serializasiyasına nəzarət edir |
Praktik nümunə:
using Newtonsoft.Json;
public class UserProfile
{
[JsonProperty("login")]
public string Username { get; set; }
[JsonIgnore]
public string InternalNotes { get; set; }
[JsonProperty(Required = Required.Always)]
public string Email { get; set; }
}
JsonProperty-nin əlavə imkanları — Required (məcburilik), Order (sıra) və s. Məsələn:
[JsonProperty("id", Order = 1, Required = Required.Always)]
public int Id { get; set; }
4. XML üçün atributlar: "klassik" stil
XmlSerializer öz atribut arsenalından istifadə edir, onlar System.Xml.Serialization namespace-indədir.
Ən çox rast gəlinənlər:
| Atribut | Nəyə xidmət edir |
|---|---|
|
XML-də element, başqa adla |
|
Property-i XML-element atributuna çevirir |
|
Property və ya field-i XML-serializasiyadan çıxarır |
|
Kolleksiyalar üçün — XML-array-in adını müəyyən edir |
|
Kolleksiyalar üçün — array elementinin adını müəyyən edir |
|
Root XML-teqin adını dəyişir |
Praktik nümunə:
using System.Xml.Serialization;
[XmlRoot("human")]
public class Person
{
[XmlElement("firstname")]
public string Name { get; set; }
[XmlAttribute("years")]
public int Age { get; set; }
[XmlIgnore]
public string Secret { get; set; }
}
var person = new Person { Name = "Anna", Age = 32, Secret = "42" };
Serializasiyadan sonra XML təxminən belə olacaq:
<human years="32"><firstname>Anna</firstname></human>
Diqqət edin ki, Secret field-i XML-ə düşməyib, Age isə nested tag yox, attribute kimi serializə olunub.
5. Faydalı nüanslar
Alt qabıq: atributlar necə işləyir
Serializer sinfinizi gördükdə, o faktiki olaraq reflection ilə "oxunur" (.NET magiyası, daha ətraflı: System.Reflection). Serializer metadataları oxuyur: məsələn, property-də JsonIgnore və ya XmlElement atributu varmı. Buna görə də o ya məlumatı son sənədə əlavə edir, ya da ötürür.
Bu, "data sxemi"ni biznes loqikasından ayırmaq üçün rahat üsuldur. Sizin sinifiniz biznes loqikadır, atributlar isə serializasiya üçün pasport kimidir.
Açar atributların uyğunluq cədvəli
| Funksiya | System.Text.Json | Newtonsoft.Json | XmlSerializer |
|---|---|---|---|
| Adı dəyişmək | |
|
|
| Ignore etmək | |
|
|
| Custom format | |
|
— (IXmlSerializable vasitəsilə, ağrılı) |
| Obyektin root-u | — | — | |
| Kolleksiya | — | — | |
6. Advanced ssenarilər
Bəzən obyektin serializasiyası standart serializer-in etdiyi kimi olmamalıdır. Məsələn, tarixi ISO string yerinə UNIX timestamp kimi saxlamaq istəyirsiniz. Belə hallar üçün öz konverterlərinizi qoşmağa imkan verən atributlar var.
System.Text.Json içində:
public class UnixDateTimeConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> DateTimeOffset.FromUnixTimeSeconds(reader.GetInt64()).UtcDateTime;
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
=> writer.WriteNumberValue(new DateTimeOffset(value).ToUnixTimeSeconds());
}
public class LogEntry
{
[JsonConverter(typeof(UnixDateTimeConverter))]
public DateTime EventTime { get; set; }
}
İndi serializasiyada EventTime sahəsi string yox, ədədə çevriləcək.
Newtonsoft.Json içində:
public class BoolToYesNoConverter : JsonConverter<bool>
{
public override void WriteJson(JsonWriter writer, bool value, JsonSerializer serializer)
=> writer.WriteValue(value ? "yes" : "no");
public override bool ReadJson(JsonReader reader, Type objectType, bool existingValue, bool hasExistingValue, JsonSerializer serializer)
=> (string)reader.Value == "yes";
}
public class Answer
{
[JsonConverter(typeof(BoolToYesNoConverter))]
public bool IsCorrect { get; set; }
}
İndi boolean dəyər "yes" və ya "no" kimi serializə edilir, və əksinə true və ya false-a dönür.
7. Xüsusiyyətlər və tələfələr
Atributlar əlavə edərkən yadda saxlayın: müxtəlif serializer-lər müxtəlif atributlardan istifadə edir. Əgər həm JSON, həm də XML ilə işləyirsinizsə (və ya eyni anda həm Newtonsoft.Json, həm də System.Text.Json istifadə edirsinizsə), lazım olan hər iki atributu qoymağı unutmayın, yoxsa sürpriz ola bilər.
Serializer yalnız atributla override olunmamışsa, property-nin standart adını götürəcək.
İrsiyyətə diqqət edin: subklass-lar public field/property-ləri miras alır və əgər parent-da atribut varsa, o, subklass-da da tətbiq olunacaq. Bu tez-tez təəccüb yaradır, amma belə nəzərdə tutulub.
Tipik səhv: Tez-tez developer-lar təsadüfən serializasiya olunmalı sahəni JsonIgnore ilə işarələyir (və ya əksinə — həssas məlumatları ignore etməyi unudurlar). Və ya məsələn, private field-ə XmlElement qoyub niyə serializer onu görmür deyə təəccüblənirlər — XmlSerializer yalnız public üzvləri emal edir!
GO TO FULL VERSION