Başlatılan özellikleri doldurma

.NET 8'den başlayarak, JSON seri durumdan çıkarıldığında .NET özelliklerini değiştirmek veya doldurmak için bir tercih belirtebilirsiniz. JsonObjectCreationHandling sabit listesi, nesne oluşturma işleme seçeneklerini sağlar:

Varsayılan (değiştirme) davranışı

Seri System.Text.Json durumdan çıkarıcı her zaman hedef türün yeni bir örneğini oluşturur. Ancak, yeni bir örnek oluşturulsa bile, bazı özellikler ve alanlar nesnenin yapımının bir parçası olarak zaten başlatılmış olabilir. Aşağıdaki türü göz önünde bulundurun:

class A
{
    public List<int> Numbers1 { get; } = [1, 2, 3];
    public List<int> Numbers2 { get; set; } = [1, 2, 3];
}

Bu sınıfın bir örneğini oluşturduğunuzda, (ve Numbers2) özelliğinin Numbers1 değeri üç öğe içeren bir listedir (1, 2 ve 3). JSON'un seri durumdan bu türe çıkarılırsa, varsayılan davranış özellik değerlerinin değiştirilmesidir:

  • için Numbers1salt okunur olduğundan (ayarlayıcı olmadığından), listesinde hala 1, 2 ve 3 değerleri vardır.
  • okuma-yazma Numbers2olan için yeni bir liste ayrılır ve JSON'dan değerler eklenir.

Örneğin, aşağıdaki seri durumdan çıkarma kodunu yürütürseniz, 1, Numbers1 2 ve 3 değerlerini ve 4, 5 ve Numbers2 6 değerlerini içerir.

A? a = JsonSerializer.Deserialize<A>("""{"Numbers1": [4,5,6], "Numbers2": [4,5,6]}""");

Doldurma davranışı

.NET 8'den başlayarak, seri durumdan çıkarma davranışını değiştirmek yerine özellikleri ve alanları değiştirmek (doldurmak) için değiştirebilirsiniz:

  • Koleksiyon türü özelliği için nesne temizlenmeden yeniden kullanılır. Koleksiyon öğelerle önceden doldurulmuşsa, seri durumdan çıkarılmış son sonuçta JSON değerleriyle birlikte gösterilir. Örnek için bkz . Koleksiyon özelliği örneği.

  • Özellikleri olan bir nesne olan bir özellik için, değiştirilebilir özellikleri JSON değerlerine güncelleştirilir, ancak nesne başvurusunun kendisi değişmez.

  • Yapı türü özelliği için etkili davranış, değiştirilebilir özellikleri için mevcut değerlerin tutulması ve JSON'dan yeni değerlerin eklenmesidir. Ancak, bir başvuru özelliğinden farklı olarak, nesnenin kendisi bir değer türü olduğundan yeniden kullanılmaz. Bunun yerine, yapının bir kopyası değiştirilir ve ardından özelliğine yeniden atanır. Örnek için bkz . Yapı özelliği örneği.

    Yapı özelliğinin bir ayarlayıcısı olmalıdır; aksi takdirde, çalışma zamanında bir InvalidOperationException oluşturulur.

Not

Doldurma davranışı şu anda parametreli oluşturucuya sahip türler için çalışmıyor. Daha fazla bilgi için bkz . dotnet/runtime issue 92877.

Salt okunur özellikler

Özelliğin başvurdığı örnek değiştirilmediğinden, değiştirilebilir başvuru özelliklerinin doldurulması için özelliğin bir ayarlayıcıya sahip olması gerekmez. Bu davranış, seri durumdan çıkarmanın salt okunur özellikleri de doldurabileceği anlamına gelir.

Not

Örnek değiştirilmiş bir kopyayla değiştirildiğinden yapı özellikleri yine de ayarlayıcı gerektirir.

Koleksiyon özelliği örneği

Değiştirme davranışı örneğinden aynı sınıfı A düşünün, ancak bu kez özellikleri değiştirmek yerine doldurma tercihiyle açıklama ekleyin:

[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
class A
{
    public List<int> Numbers1 { get; } = [1, 2, 3];
    public List<int> Numbers2 { get; set; } = [1, 2, 3];
}

Aşağıdaki seri durumdan çıkarma kodunu yürütürseniz, Numbers2 hem hem de Numbers1 1, 2, 3, 4, 5 ve 6 değerlerini içerir:

A? a = JsonSerializer.Deserialize<A>("""{"Numbers1": [4,5,6], "Numbers2": [4,5,6]}""");

Yapı özelliği örneği

Aşağıdaki sınıf, S1seri durumdan çıkarma davranışı olarak Populateayarlanmış olan bir yapı özelliği içerir. Bu kodu c.S1.Value1 yürüttkten sonra 10 değerine (oluşturucudan) ve c.S1.Value2 5 değerine (JSON'dan) sahip olur.

C? c = JsonSerializer.Deserialize<C>("""{"S1": {"Value2": 5}}""");

class C
{
    public C()
    {
        _s1 = new S
        {
            Value1 = 10
        };
    }

    private S _s1;

    [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
    public S S1
    {
        get { return _s1; }
        set { _s1 = value; }
    }
}

struct S
{
    public int Value1 { get; set; }
    public int Value2 { get; set; }
}

Bunun yerine varsayılan Replace davranış kullanıldıysa, c.S1.Value1 seri durumdan çıkarıldıktan sonra varsayılan değeri 0 olur. Bunun nedeni oluşturucunun C() çağrılıp 10 olarak ayarlanmasıdır c.S1.Value1 , ancak ardından S1 değerinin yeni bir örnekle değiştirilmesi gerekir. (c.S1.Value2 JSON varsayılan değeri değiştirdiğinden 5 olur.)

Nasıl belirtilir?

Değiştirme veya doldurma tercihi belirtmenin birden çok yolu vardır:

  • JsonObjectCreationHandlingAttribute tür veya özellik düzeyinde açıklama eklemek için özniteliğini kullanın. Özniteliği tür düzeyinde ayarlar ve özelliğini Populateolarak ayarlarsanızHandling, davranış yalnızca popülasyon mümkün olduğunda bu özelliklere uygulanır (örneğin, değer türlerinin bir ayarlayıcıya sahip olması gerekir).

    Tür genelinde tercihin olmasını Populateistiyorsanız ancak bu davranıştan bir veya daha fazla özelliği dışlamak istiyorsanız, devralınan davranışı geçersiz kılmak için özniteliği tür düzeyinde ve özellik düzeyinde yeniden ekleyebilirsiniz. Bu düzen aşağıdaki kodda gösterilmiştir.

    // Type-level preference is Populate.
    [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
    class B
    {
        // For this property only, use Replace behavior.
        [JsonObjectCreationHandling(JsonObjectCreationHandling.Replace)]
        public List<int> Numbers1 { get; } = [1, 2, 3];
        public List<int> Numbers2 { get; set; } = [1, 2, 3];
    }
    
  • Genel bir tercih belirtmek için (veya kaynak JsonSourceGenerationOptionsAttribute.PreferredObjectCreationHandlingoluşturma için) ayarlayın JsonSerializerOptions.PreferredObjectCreationHandling .

    var options = new JsonSerializerOptions
    {
        PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate
    };