Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A partir do .NET 8, você pode especificar uma preferência para substituir ou preencher as propriedades do .NET quando o JSON for desserializado. A JsonObjectCreationHandling enumeração fornece as opções de tratamento de criação de objeto:
Comportamento padrão (substituir)
O System.Text.Json desserializador sempre cria uma nova instância do tipo de destino. No entanto, mesmo que uma nova instância seja criada, algumas propriedades e campos já podem ser inicializados como parte da construção do objeto. Considere o seguinte tipo:
class A
{
public List<int> Numbers1 { get; } = [1, 2, 3];
public List<int> Numbers2 { get; set; } = [1, 2, 3];
}
Quando você cria uma instância dessa classe, o Numbers1 valor da propriedade (e Numbers2) é uma lista com três elementos (1, 2 e 3). Se você desserializar JSON para esse tipo, o comportamento padrão é que os valores de propriedade sejam substituídos:
- Para
Numbers1, como é somente leitura (sem setter), ele ainda tem os valores 1, 2 e 3 em sua lista. - Para
Numbers2, que é de leitura e escrita, uma nova lista é alocada e os valores do JSON são adicionados.
Por exemplo, se você executar o código de desserialização a seguir, Numbers1 conterá os valores 1, 2 e 3 e Numbers2 conterá os valores 4, 5 e 6.
A? a = JsonSerializer.Deserialize<A>("""{"Numbers1": [4,5,6], "Numbers2": [4,5,6]}""");
Comportamento de população
A partir do .NET 8, você pode alterar o comportamento de desserialização para modificar (preencher) essas propriedades e campos em vez de substituí-los.
Para uma propriedade do tipo coleção, o objeto é reutilizado sem ser limpo. Se a coleção for pré-preenchida com elementos, elas serão mostradas no resultado desserializado final juntamente com os valores do JSON. Para obter um exemplo, consulte o exemplo da propriedade Collection.
Para uma propriedade que é um objeto com propriedades, suas propriedades mutáveis são atualizadas para os valores JSON, mas a referência de objeto em si não é alterada.
Para uma propriedade de tipo de struct, o comportamento efetivo é que, para suas propriedades mutáveis, todos os valores existentes são mantidos e novos valores do JSON são adicionados. No entanto, ao contrário de uma propriedade de referência, o objeto em si não é reutilizado, pois é um tipo de valor. Em vez disso, uma cópia do struct é modificada e reatribuída à propriedade. Para obter um exemplo, consulte o exemplo da propriedade Struct.
Uma propriedade struct deve ter um setter; caso contrário, um InvalidOperationException é lançado em runtime.
Observação
O comportamento de população atualmente não funciona para tipos que têm um construtor parametrizado. Para obter mais informações, consulte o problema do dotnet/runtime 92877.
Propriedades somente leitura
Para preencher as propriedades de referência que são mutáveis, uma vez que a instância em que a propriedade faz referência não é substituída, a propriedade não precisa ter um setter. Esse comportamento significa que a desserialização pode também preencher propriedades somente leitura.
Observação
As propriedades de struct ainda exigem setters porque a instância é substituída por uma cópia modificada.
Exemplo de propriedade de coleção
Considere a mesma classe A do exemplo de comportamento de substituição , mas desta vez anotado com uma preferência para preencher propriedades em vez de substituí-las:
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
class A
{
public List<int> Numbers1 { get; } = [1, 2, 3];
public List<int> Numbers2 { get; set; } = [1, 2, 3];
}
Se você executar o seguinte código de desserialização, tanto Numbers1 quanto Numbers2 contêm os valores 1, 2, 3, 4, 5 e 6:
A? a = JsonSerializer.Deserialize<A>("""{"Numbers1": [4,5,6], "Numbers2": [4,5,6]}""");
Exemplo da propriedade Struct
A classe a seguir contém uma propriedade struct, S1cujo comportamento de desserialização é definido como Populate. Depois de executar esse código, c.S1.Value1 tem um valor de 10 (do construtor) e c.S1.Value2 tem um valor de 5 (do JSON).
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; }
}
Se o comportamento padrão Replace fosse usado, c.S1.Value1 teria seu valor padrão de 0 após a desserialização. Isso ocorre porque o construtor C() seria chamado, definindo c.S1.Value1 como 10, mas o valor de S1 seria substituído por uma nova instância. (c.S1.Value2 ainda seria 5, já que o JSON substitui o valor padrão.)
Como especificar
Há várias maneiras de especificar uma preferência para substituir ou preencher:
Use o atributo JsonObjectCreationHandlingAttribute para anotar no nível do tipo ou da propriedade. Se você definir o atributo no nível do tipo e definir sua Handling propriedade como Populate, o comportamento só se aplicará às propriedades em que a população for possível (por exemplo, os tipos de valor devem ter um setter).
Se quiser que a preferência de todo o tipo seja Populate, mas quiser excluir uma ou mais propriedades desse comportamento, você poderá adicionar o atributo no nível do tipo e novamente no nível da propriedade para substituir o comportamento herdado. Esse padrão é mostrado no código a seguir.
// 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]; }Defina JsonSerializerOptions.PreferredObjectCreationHandling (ou, para a geração de origem, JsonSourceGenerationOptionsAttribute.PreferredObjectCreationHandling) para especificar uma preferência global.
var options = new JsonSerializerOptions { PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate };