Bu ayarlar en iyi örnek ile izah edilebilir. Şirketteki çalışanların hiyerarşisini temsil etmek istediğimizi varsayalım. Bu yüzden basit bir sınıf böyle yapmak: Angela Bob ve Charles:
class Employee
{
public string Name { get; set; }
public List<Employee> Subordinates { get; set; }
}
Bu şimdiye kadar sadece üç çalışanı olan küçük bir şirkettir. Angela patrondur, Bob ve Charles onun astlarıdır. en bu ilişkiyi açıklamak için verileri kuralım:
[
{
"Name": "Angela Anderson",
"Subordinates": [
{
"Name": "Bob Brown",
"Subordinates": null
},
{
"Name": "Charles Cooper",
"Subordinates": null
}
]
},
{
"Name": "Bob Brown",
"Subordinates": null
},
{
"Name": "Charles Cooper",
"Subordinates": null
}
]
: ... biz JSON çalışanların listesini seri halinde
Employee angela = new Employee { Name = "Angela Anderson" };
Employee bob = new Employee { Name = "Bob Brown" };
Employee charles = new Employee { Name = "Charles Cooper" };
angela.Subordinates = new List<Employee> { bob, charles };
List<Employee> employees = new List<Employee> { angela, bob, charles };
string json = JsonConvert.SerializeObject(employees, Formatting.Indented);
Console.WriteLine(json);
... bu çıktıyı almak
Şimdiye kadar çok iyi. Onları temsil eden nesneler ana çalışanların listesi ve astlarının Angela'nın listesiyle hem başvurulan çünkü Bob ve Charles için bilgi JSON tekrarlanır Ancak, fark edeceksiniz. Belki şu an için sorun değil.
Şimdi biz de kendi astlarına ilaveten her İşçinin amiri takip etmek için bir yol olsun isterim herhalde. Bu yüzden ... Bir Supervisor
özellik eklemek için
class Employee
{
public string Name { get; set; }
public Employee Supervisor { get; set; }
public List<Employee> Subordinates { get; set; }
}
bizim Employee
modelini değiştirmek ... ve göstermek için bizim kurulum koduna bir çift daha satırları ekleyin Angela Charles ve Bob raporu:
Employee angela = new Employee { Name = "Angela Anderson" };
Employee bob = new Employee { Name = "Bob Brown" };
Employee charles = new Employee { Name = "Charles Cooper" };
angela.Subordinates = new List<Employee> { bob, charles };
bob.Supervisor = angela; // added this line
charles.Supervisor = angela; // added this line
List<Employee> employees = new List<Employee> { angela, bob, charles };
Ama şimdi biraz sorunumuz var. nesne grafiği içinde referans halka (ör angela
referanslar bob
ise bob
referanslar angela
) sahip olduğu için, biz çalışan listeyi seri deneyin zaman, bir JsonSerializationException
olacaktır. Bu sorunu çözmek bir yolu böyle Ignore
için ReferenceLoopHandling
ayarlayarak geçerli: etapta bu ayarda
JsonSerializerSettings settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(employees, settings);
, aşağıdaki JSON olsun: Eğer JSON incelerseniz
[
{
"Name": "Angela Anderson",
"Supervisor": null,
"Subordinates": [
{
"Name": "Bob Brown",
"Subordinates": null
},
{
"Name": "Charles Cooper",
"Subordinates": null
}
]
},
{
"Name": "Bob Brown",
"Supervisor": {
"Name": "Angela Anderson",
"Supervisor": null,
"Subordinates": [
{
"Name": "Charles Cooper",
"Subordinates": null
}
]
},
"Subordinates": null
},
{
"Name": "Charles Cooper",
"Supervisor": {
"Name": "Angela Anderson",
"Supervisor": null,
"Subordinates": [
{
"Name": "Bob Brown",
"Subordinates": null
}
]
},
"Subordinates": null
}
]
, bu Bu ayarın ne olduğu açık olmalıdır: serializer, serileştirme işleminde olan bir nesneye bir referansla karşılaştığı her zaman, sadece o üyeyi atlar. (Bu sonsuz bir döngüye girmesini seri hale engeller.) JSON üst kısmında astlarının Angela'nın listesinde Bob ne de Charles de bir danışman gösterdiğini görebilirsiniz. JSON'un alt kısmında, Bob ve Charles her ikisi de Angela'yı amir olarak gösterir, ancak bu noktada astlarının listesinin hem Bob hem de Charles'ı içermediğine dikkat edin.
Bu JSON ile çalışmak ve hatta bazı nesnelerle orijinal nesne hiyerarşisini yeniden yapılandırmak mümkün olsa da, açıkça optimal değildir. Hala yerine ayarlayarak PreserveReferencesHandling
kullanarak nesne referanslarını korurken Biz JSON tekrarlanan bilgileri ortadan kaldırabilir:
JsonSerializerSettings settings = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(employees, settings);
Şimdi aşağıdaki JSON olsun:
[
{
"$id": "1",
"Name": "Angela Anderson",
"Supervisor": null,
"Subordinates": [
{
"$id": "2",
"Name": "Bob Brown",
"Supervisor": {
"$ref": "1"
},
"Subordinates": null
},
{
"$id": "3",
"Name": "Charles Cooper",
"Supervisor": {
"$ref": "1"
},
"Subordinates": null
}
]
},
{
"$ref": "2"
},
{
"$ref": "3"
}
]
Bildirimi şimdi her nesne olmuştur JSON'da bir sıralı $id
değeri atandı. Bir nesnenin ilk göründüğü zaman, tam olarak serileştirilirken, sonraki referanslar, orijinal nesneyi karşılık gelen $id
ile yeniden gönderen özel bir $ref
özelliğiyle değiştirilir. Bu ayar geçerli olduğunda, JSON çok daha özlüdür ve Json.Net/Web API tarafından üretilen $id
ve $ref
notasyonunu anlayan bir kitaplık kullandığınızı varsayarak, hiçbir ek iş gerekmeden orijinal nesne hiyerarşisine geri gönderilebilir.
Peki neden bir ayar veya diğerini seçmelisiniz? Bu sizin ihtiyaçlarınız doğrultusunda. JSON, $id
/$ref
biçimini anlamayan bir istemci tarafından tüketilecek ve bu, eksik veri içeren yerlerde tolere edebilirse, ReferenceLoopHandling.Ignore
kullanmayı tercih edersiniz. Daha kompakt JSON arıyorsanız ve verileri serileştirmek için Json.Net veya Web API'sini (veya başka bir uyumlu kütüphane) kullanacaksanız, PreserveReferencesHandling.Objects
'u kullanmayı tercih edersiniz. Verileriniz, yinelenen referans içermeyen yönlendirilmiş bir asiklik grafikse, o zaman ayarlara da ihtiyacınız yoktur.
Dokümanlar ne dedi? Bunun hakkında ne belirsizdi? – nvoigt