içinde başvuruları koruma ve döngüsel başvuruları işleme veya yoksayma System.Text.Json
Bu makalede. .NET'te JSON'u serileştirmek ve seri durumdan seri durumdan etmek için kullanırken başvuruları koruma ve döngüsel başvuruları işleme veya System.Text.Json yoksayma ile ilgili nasıl bir durum olduğu açıklanmıştır
Başvuruları koruma ve döngüsel başvuruları işleme
Başvuruları korumak ve döngüsel başvuruları işlemek için olarak ReferenceHandler Preserve ayarlayın. Bu ayar aşağıdaki davranışa neden olur:
Serileştirmede:
Karmaşık türler yazarken seri hale getirici meta veri özelliklerini de yazar (
$id,$valuesve$ref).Deserialize'da:
Meta veriler beklenir (zorunlu değildir) ve deserializer bunu anlamaya çalışır.
Aşağıdaki kod, ayarın kullanımını Preserve göstermektedir.
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace PreserveReferences
{
public class Employee
{
public string Name { get; set; }
public Employee Manager { get; set; }
public List<Employee> DirectReports { get; set; }
}
public class Program
{
public static void Main()
{
Employee tyler = new()
{
Name = "Tyler Stein"
};
Employee adrian = new()
{
Name = "Adrian King"
};
tyler.DirectReports = new List<Employee> { adrian };
adrian.Manager = tyler;
JsonSerializerOptions options = new()
{
ReferenceHandler = ReferenceHandler.Preserve,
WriteIndented = true
};
string tylerJson = JsonSerializer.Serialize(tyler, options);
Console.WriteLine($"Tyler serialized:\n{tylerJson}");
Employee tylerDeserialized =
JsonSerializer.Deserialize<Employee>(tylerJson, options);
Console.WriteLine(
"Tyler is manager of Tyler's first direct report: ");
Console.WriteLine(
tylerDeserialized.DirectReports[0].Manager == tylerDeserialized);
}
}
}
// Produces output like the following example:
//
//Tyler serialized:
//{
// "$id": "1",
// "Name": "Tyler Stein",
// "Manager": null,
// "DirectReports": {
// "$id": "2",
// "$values": [
// {
// "$id": "3",
// "Name": "Adrian King",
// "Manager": {
// "$ref": "1"
// },
// "DirectReports": null
// }
// ]
// }
//}
//Tyler is manager of Tyler's first direct report:
//True
Imports System.Text.Json
Imports System.Text.Json.Serialization
Namespace PreserveReferences
Public Class Employee
Public Property Name As String
Public Property Manager As Employee
Public Property DirectReports As List(Of Employee)
End Class
Public NotInheritable Class Program
Public Shared Sub Main()
Dim tyler As New Employee
Dim adrian As New Employee
tyler.DirectReports = New List(Of Employee) From {
adrian}
adrian.Manager = tyler
Dim options As New JsonSerializerOptions With {
.ReferenceHandler = ReferenceHandler.Preserve,
.WriteIndented = True
}
Dim tylerJson As String = JsonSerializer.Serialize(tyler, options)
Console.WriteLine($"Tyler serialized:{tylerJson}")
Dim tylerDeserialized As Employee = JsonSerializer.Deserialize(Of Employee)(tylerJson, options)
Console.WriteLine(
"Tyler is manager of Tyler's first direct report: ")
Console.WriteLine(
tylerDeserialized.DirectReports(0).Manager Is tylerDeserialized)
End Sub
End Class
End Namespace
' Produces output like the following example:
'
'Tyler serialized:
'{
' "$id": "1",
' "Name": "Tyler Stein",
' "Manager": null,
' "DirectReports": {
' "$id": "2",
' "$values": [
' {
' "$id": "3",
' "Name": "Adrian King",
' "Manager": {
' "$ref": "1"
' },
' "DirectReports": null
' }
' ]
' }
'}
'Tyler is manager of Tyler's first direct report:
'True
Bu özellik, değer türlerini veya sabit türleri korumak için kullanılamaz. Deserialization'da, yükün tamamı okunduktan sonra sabit bir tür örneği oluşturulur. Bu nedenle, JSON yükü içinde bir başvuru görünürse aynı örneğinin deserialize olması mümkün olmayacaktır.
Değer türleri, sabit türler ve diziler için başvuru meta verileri seri hale getirilemez. Veya bulunursa, deserialization'da $ref bir özel durum $id oluşturur. Ancak, değer türleri kullanılarak seri hale getirilen yüklerin seri durumdan kaldırabilirsiniz (ve koleksiyonlar $id $values durumunda) yoksayabilirsiniz. Newtonsoft.Json Newtonsoft.Json , bu türler için meta verileri seri hale getirmez.
Nesnelerin eşit olup olmadığını belirlemek için, iki nesne örneğini karşılaştırırken değer eşitliği yerine başvuru eşitliğini System.Text.Json ReferenceEqualityComparer.Instance ( ) kullanan Object.ReferenceEquals(Object, Object) Object.Equals(Object) kullanır.
Başvuruların seri hale nasıl getirilecek ve seriden nasıl kaldır olduğu hakkında daha fazla bilgi için bkz. ReferenceHandler.Preserve .
ReferenceResolversınıfı, serileştirme ve seriden kaldıran başvurular koruma davranışını tanımlar. Özel davranış belirtmek için türetilmiş bir sınıf oluşturun. Bir örnek için bkz. GuidReferenceResolver.
Başvuru meta verilerini birden çok serileştirme ve seriyi kaldır çağrısında kalıcı hale getirme
Varsayılan olarak, başvuru verileri yalnızca veya çağrısı için önbelleğe Serialize alınmış Deserialize olur. Bir çağrıdan diğerine Serialize / Deserialize yapılan başvuruları kalıcı yapmak için, çağrısı ReferenceResolver sitesinde örneğine kök dizine Serialize / Deserialize bakın. Aşağıdaki kod, bu senaryo için bir örnek gösterir:
- listesiniz var
Employeeve her birini tek tek seri hale getirmemiz gerekir. - çözümleyicisinde kaydedilen başvurulardan
ReferenceHandleryararlanmak istediğiniz.
Sınıfı şu Employee şekildedir:
public class Employee
{
public string Name { get; set; }
public Employee Manager { get; set; }
public List<Employee> DirectReports { get; set; }
}
'den türeten ReferenceResolver bir sınıf, başvuruları bir sözlükte depolar:
class MyReferenceResolver : ReferenceResolver
{
private uint _referenceCount;
private readonly Dictionary<string, object> _referenceIdToObjectMap = new ();
private readonly Dictionary<object, string> _objectToReferenceIdMap = new (ReferenceEqualityComparer.Instance);
public override void AddReference(string referenceId, object value)
{
if (!_referenceIdToObjectMap.TryAdd(referenceId, value))
{
throw new JsonException();
}
}
public override string GetReference(object value, out bool alreadyExists)
{
if (_objectToReferenceIdMap.TryGetValue(value, out string referenceId))
{
alreadyExists = true;
}
else
{
_referenceCount++;
referenceId = _referenceCount.ToString();
_objectToReferenceIdMap.Add(value, referenceId);
alreadyExists = false;
}
return referenceId;
}
public override object ResolveReference(string referenceId)
{
if (!_referenceIdToObjectMap.TryGetValue(referenceId, out object value))
{
throw new JsonException();
}
return value;
}
}
sınıfından türeten bir sınıf, bir örneğini tutar ve yalnızca gerektiğinde yeni bir örnek oluşturur ReferenceHandler MyReferenceResolver (bu örnekte adlı Reset bir yöntemde):
class MyReferenceHandler : ReferenceHandler
{
public MyReferenceHandler() => Reset();
private ReferenceResolver _rootedResolver;
public override ReferenceResolver CreateResolver() => _rootedResolver;
public void Reset() => _rootedResolver = new MyReferenceResolver();
}
Örnek kod seri hale getiriciyi çağırarak özelliğinin bir JsonSerializerOptions ReferenceHandler örneğine ayar olduğu bir örneği MyReferenceHandler kullanır. Bu düzeni izledikten sonra, sonsuza kadar büyümesine karşı serileştirmeyi bitirdikten sonra sözlüğü ReferenceResolver sıfırlamayı unutmayın.
var options = new JsonSerializerOptions();
options.WriteIndented = true;
var myReferenceHandler = new MyReferenceHandler();
options.ReferenceHandler = myReferenceHandler;
string json;
foreach (Employee emp in employees)
{
json = JsonSerializer.Serialize(emp, options);
DoSomething(json);
}
// Reset after serializing to avoid out of bounds memory growth in the resolver.
myReferenceHandler.Reset();
System.Text.Json .NET Core 3.1'de yalnızca değere göre serileştirmeyi destekler ve döngüsel başvurular için bir özel durum oluşturur.
Döngüsel başvuruları yoksayma
Döngüsel başvuruları işleme yerine yoksayabilirsiniz. Döngüsel başvuruları yoksaymak için olarak ReferenceHandler IgnoreCycles ayarlayın. Seri hale getirici, aşağıdaki örnekte gösterildiği null gibi döngüsel başvuru özelliklerini olarak ayarlar:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SerializeIgnoreCycles
{
public class Employee
{
public string? Name { get; set; }
public Employee? Manager { get; set; }
public List<Employee>? DirectReports { get; set; }
}
public class Program
{
public static void Main()
{
Employee tyler = new()
{
Name = "Tyler Stein"
};
Employee adrian = new()
{
Name = "Adrian King"
};
tyler.DirectReports = new List<Employee> { adrian };
adrian.Manager = tyler;
JsonSerializerOptions options = new()
{
ReferenceHandler = ReferenceHandler.IgnoreCycles,
WriteIndented = true
};
string tylerJson = JsonSerializer.Serialize(tyler, options);
Console.WriteLine($"Tyler serialized:\n{tylerJson}");
Employee? tylerDeserialized =
JsonSerializer.Deserialize<Employee>(tylerJson, options);
Console.WriteLine(
"Tyler is manager of Tyler's first direct report: ");
Console.WriteLine(
tylerDeserialized?.DirectReports?[0]?.Manager == tylerDeserialized);
}
}
}
// Produces output like the following example:
//
//Tyler serialized:
//{
// "Name": "Tyler Stein",
// "Manager": null,
// "DirectReports": [
// {
// "Name": "Adrian King",
// "Manager": null,
// "DirectReports": null
// }
// ]
//}
//Tyler is manager of Tyler's first direct report:
//False
Yukarıdaki örnekte, Manager döngüsel Adrian King başvuruyu önlemek için altında null serileştirilmiştir. Bu davranış, aşağıdaki avantajlara ReferenceHandler.Preserve sahiptir:
- Yük boyutunu azaltıyor.
- ve dışında seri hale getiriciler için anlanabilir JSON System.Text.Json Newtonsoft.Json oluşturur.
Bu davranışın aşağıdaki dezavantajları vardır:
- Sessiz veri kaybı.
- Veriler JSON'dan kaynak nesneye gidiş dönüş kullanılamaz.
System.Text.Json .NET 5 ve önceki sürümlerinde ReferenceHandler.IgnoreCycles desteklemez.
Ayrıca bkz.
- System.Text.Json Genel bakış
- JSON’u seri hale getirme ve seri halden çıkarma
- JsonSerializerOptions örnekleri örneği
- Büyük/küçük harf duyarlı eşlemeyi etkinleştirme
- Özellik adlarını ve değerlerini özelleştirme
- Özellikleri yoksayma
- Geçersiz JSON’a izin verme
- Taşma JSON'larını işleme veya JsonElement ya da JsonNode kullanma
- Sabit türler ve genel olmayan erişimciler için deserialize
- Polimorfik serileştirme
- 'den'e Newtonsoft.Json geçiş System.Text.Json
- Karakter kodlamasını özelleştirme
- DOM, Utf8JsonReader ve Utf8JsonWriter kullanma
- JSON serileştirme için özel dönüştürücüler yazma
- DateTime ve DateTimeOffset desteği
- Kaynak oluşturma kullanma
- Desteklenen koleksiyon türleri
- System.Text.Json API başvurusu
- System.Text.Json. Serileştirme API'si başvurusu