As opções PropertyNamingPolicy, PropertyNameCaseInsensitive e Encoder são respeitadas ao serializar e desserializar pares chave-valor

JsonSerializer agora respeita as opções PropertyNamingPolicy e Encoder ao serializar os nomes de propriedade Key e Value de uma instância KeyValuePair<TKey,TValue>. Além disso, JsonSerializer respeita as opções PropertyNamingPolicy e PropertyNameCaseInsensitive ao desserializar as instâncias KeyValuePair<TKey,TValue>.

Descrição das alterações

Serialização

Nas versões do .NET Core 3.x e nas versões 4.6.0-4.7.2 do System.Text.Jsno pacote NuGet, as propriedades de instâncias KeyValuePair<TKey,TValue> são sempre serializadas como "Key" e "Value" exatamente, independentemente de quaisquer opções JsonSerializerOptions.PropertyNamingPolicy e JsonSerializerOptions.Encoder. O exemplo de código a seguir mostra como as propriedades Key e Valuenão têm concatenação com maiúsculas e minúsculas após a serialização, embora a política de nomenclatura de propriedades especificada o determine.

var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
KeyValuePair<int, int> kvp = KeyValuePair.Create(1, 1);
Console.WriteLine(JsonSerializer.Serialize(kvp, options));
// Expected: {"key":1,"value":1}
// Actual: {"Key":1,"Value":1}

A partir do .NET 5, as opções PropertyNamingPolicy e Encoder são respeitadas ao serializar as instâncias KeyValuePair<TKey,TValue>. O exemplo de código a seguir mostra como as propriedades Key e Value têm concatenação com maiúsculas e minúsculas após a serialização, conforme a política de nomenclatura de propriedades especificada.

var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
KeyValuePair<int, int> kvp = KeyValuePair.Create(1, 1);
Console.WriteLine(JsonSerializer.Serialize(kvp, options));
// {"key":1,"value":1}

Desserialização

Nas versões do .NET Core 3.x e nas versões 4.7.x do pacote do NuGet System.Text.Json, um JsonException é gerado quando os nomes de propriedade JSON não são precisamente Key e Value. Por exemplo, se eles não começam com uma letra maiúscula. A exceção é gerada mesmo se uma política de nomenclatura de propriedade especificada permitir expressamente.

var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
string json = @"{""key"":1,""value"":1}";
// Throws JsonException.
JsonSerializer.Deserialize<KeyValuePair<int, int>>(json, options);

A partir do .NET 5, as opções PropertyNamingPolicy e PropertyNameCaseInsensitive são respeitadas ao desserializar usando JsonSerializer. Por exemplo, o snippet de código a seguir mostra a desserialização bem-sucedida de nomes de propriedades Key e Value em letras minúsculas porque a política de nomenclatura de propriedades especificada permite isso.

var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
string json = @"{""key"":1,""value"":1}";

KeyValuePair<int, int> kvp = JsonSerializer.Deserialize<KeyValuePair<int, int>>(json);
Console.WriteLine(kvp.Key); // 1
Console.WriteLine(kvp.Value); // 1

Para acomodar cargas que foram serializadas com versões anteriores, "Key" e "Value" têm um uso de maiúsculas e minúsculas especial para corresponder ao desserializar. Embora os nomes de propriedade Key e Value não tenham concatenação com maiúsculas e minúsculas conforme a opção PropertyNamingPolicy no exemplo de código a seguir, eles desserializam com êxito.

var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
string json = @"{""Key"":1,""Value"":1}";

KeyValuePair<int, int> kvp = JsonSerializer.Deserialize<KeyValuePair<int, int>>(json);
Console.WriteLine(kvp.Key); // 1
Console.WriteLine(kvp.Value); // 1

Versão introduzida

5,0

Motivo da alteração

Comentários substanciais dos clientes indicaram que o PropertyNamingPolicy deve ser respeitado. Para integridade, as opções PropertyNameCaseInsensitive e Encoder também são respeitadas, de modo que as instâncias KeyValuePair<TKey,TValue> sejam tratadas da mesma forma que qualquer outro objeto CRL básico (POCO).

Se essa alteração for disruptiva para você, você poderá usar um conversor personalizado que implemente a semântica desejada.

APIs afetadas