Como personalizar nomes e valores de propriedade com System.Text.Json

Por padrão, os nomes de propriedade e as chaves de dicionário não são alterados na saída JSON, incluindo maiúsculas e minúsculas. Os valores de enumeração são representados como números. E as propriedades são serializadas na ordem em que são definidas. No entanto, é possível personalizar esse comportamento:

  • Especificando nomes de propriedade serializados específicos.
  • Usando uma política de nomenclatura interna, como camelCase, snake_case ou kebab-case, para nomes de propriedade e chaves de dicionário.
  • Usando uma política de nomenclatura personalizada para nomes de propriedade e chaves de dicionário.
  • Serializando valores de enumeração como cadeias de caracteres, com ou sem uma política de nomenclatura.
  • Configurando a ordem das propriedades serializadas.

Observação

A política de nomenclatura padrão da Web é camel case.

Para outros cenários que exigem tratamento especial de nomes e valores de propriedade JSON, você pode implementar conversores personalizados.

Personalizar nomes de propriedades individuais

Para definir o nome das propriedades individuais, use o atributo [JsonPropertyName].

Aqui está um tipo de exemplo para serializar e o JSON resultante:

public class WeatherForecastWithPropertyNameAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyNameAttribute
    Public Property [Date] As DateTimeOffset
    Public Property TemperatureCelsius As Integer
    Public Property Summary As String

    <JsonPropertyName("Wind")>
    Public Property WindSpeed As Integer

End Class
{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot",
  "Wind": 35
}

O nome da propriedade definida por este atributo:

Usar uma política de nomenclatura interna

A tabela a seguir mostra as políticas de nomenclatura internas e como elas afetam os nomes de propriedades.

Política de nomenclatura Descrição Nome da propriedade original Nome da propriedade convertido
CamelCase A primeira palavra começa com um caractere minúsculo.
As palavras sucessivas começam com um caractere maiúsculo.
TempCelsius tempCelsius
KebabCaseLower* As palavras são separadas por hifens.
Todos os caracteres são minúsculos.
TempCelsius temp-celsius
KebabCaseUpper* As palavras são separadas por hifens.
Todos os caracteres são maiúsculos.
TempCelsius TEMP-CELSIUS
SnakeCaseLower* As palavras são separadas por sublinhados.
Todos os caracteres são minúsculos.
TempCelsius temp_celsius
SnakeCaseUpper* As palavras são separadas por sublinhados.
Todos os caracteres são maiúsculos.
TempCelsius TEMP_CELSIUS

* Disponível no .NET 8 e versões posteriores.

P exemplo a seguir mostra como usar o camel case para todos os nomes de propriedade JSON, configurando JsonSerializerOptions.PropertyNamingPolicy como JsonNamingPolicy.CamelCase:

var serializeOptions = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
Dim serializeOptions As JsonSerializerOptions = New JsonSerializerOptions With {
    .PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    .WriteIndented = True
}
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions)

Aqui está uma classe de exemplo para serializar e saída JSON:

public class WeatherForecastWithPropertyNameAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyNameAttribute
    Public Property [Date] As DateTimeOffset
    Public Property TemperatureCelsius As Integer
    Public Property Summary As String

    <JsonPropertyName("Wind")>
    Public Property WindSpeed As Integer

End Class
{
  "date": "2019-08-01T00:00:00-07:00",
  "temperatureCelsius": 25,
  "summary": "Hot",
  "Wind": 35
}

A política de nomenclatura:

  • Aplica-se à serialização e à desserialização.
  • É substituído por atributos [JsonPropertyName]. É por isso que o nome da propriedade JSON Wind no exemplo não está em maiúsculas e minúsculas concatenadas.

Observação

Nenhuma das políticas de nomenclatura internas oferece suporte a letras que são pares substitutos. Para obter mais informações, confira problema #90352 dotnet/runtime.

Usar uma política de nomenclatura de propriedade JSON personalizada

Para usar uma política de nomenclatura de propriedade JSON personalizada, crie uma classe que deriva JsonNamingPolicy e substitui o método ConvertName, conforme mostra o seguinte exemplo:

using System.Text.Json;

namespace SystemTextJsonSamples
{
    public class UpperCaseNamingPolicy : JsonNamingPolicy
    {
        public override string ConvertName(string name) =>
            name.ToUpper();
    }
}
Imports System.Text.Json

Namespace SystemTextJsonSamples

    Public Class UpperCaseNamingPolicy
        Inherits JsonNamingPolicy

        Public Overrides Function ConvertName(name As String) As String
            Return name.ToUpper()
        End Function

    End Class

End Namespace

Em seguida, defina a propriedade JsonSerializerOptions.PropertyNamingPolicy como uma instância da classe de política de nomenclatura:

var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = new UpperCaseNamingPolicy(),
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
Dim options As JsonSerializerOptions = New JsonSerializerOptions With {
    .PropertyNamingPolicy = New UpperCaseNamingPolicy,
    .WriteIndented = True
}
jsonString = JsonSerializer.Serialize(weatherForecast1, options)

Aqui está uma classe de exemplo para serializar e saída JSON:

public class WeatherForecastWithPropertyNameAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyNameAttribute
    Public Property [Date] As DateTimeOffset
    Public Property TemperatureCelsius As Integer
    Public Property Summary As String

    <JsonPropertyName("Wind")>
    Public Property WindSpeed As Integer

End Class
{
  "DATE": "2019-08-01T00:00:00-07:00",
  "TEMPERATURECELSIUS": 25,
  "SUMMARY": "Hot",
  "Wind": 35
}

A política de nomenclatura da propriedade JSON:

  • Aplica-se à serialização e à desserialização.
  • É substituído por atributos [JsonPropertyName]. É por isso que o nome da propriedade JSON Wind no exemplo não está em maiúsculas.

Usar uma política de nomenclatura para chaves de dicionário

Se uma propriedade de um objeto a ser serializado for do tipo Dictionary<string,TValue>, as chaves string poderão ser convertidas usando uma política de nomenclatura, como o camel case. Para fazer isso, defina JsonSerializerOptions.DictionaryKeyPolicy como a política de nomenclatura desejada. O exemplo a seguir usa a política de nomenclatura CamelCase:

var options = new JsonSerializerOptions
{
    DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
Dim options As JsonSerializerOptions = New JsonSerializerOptions With {
    .DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
    .WriteIndented = True
}
jsonString = JsonSerializer.Serialize(weatherForecast, options)

Serializar um objeto com um dicionário chamado TemperatureRanges que tem pares chave-valor "ColdMinTemp", 20 e "HotMinTemp", 40 resultaria em saída JSON como a do seguinte exemplo:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot",
  "TemperatureRanges": {
    "coldMinTemp": 20,
    "hotMinTemp": 40
  }
}

As políticas de nomenclatura para chaves de dicionário se aplicam somente à serialização. Se você desserializar um dicionário, as chaves corresponderão ao arquivo JSON mesmo que você defina JsonSerializerOptions.DictionaryKeyPolicy como uma política de nomenclatura não padrão.

Enumerações como cadeias de caracteres

Por padrão, as enumerações são serializadas como números. Para serializar nomes de enumeração como cadeias de caracteres, use o conversor JsonStringEnumConverter ou JsonStringEnumConverter<TEnum>. Somente JsonStringEnumConverter<TEnum> é compatível com o tempo de execução nativo do AOT.

Por padrão, as enumerações são serializadas como números. Para serializar nomes de enumeração como cadeias de caracteres, use o conversor JsonStringEnumConverter.

Por exemplo, suponha que você precise serializar a seguinte classe que tem uma enumeração:

public class WeatherForecastWithEnum
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public Summary? Summary { get; set; }
}

public enum Summary
{
    Cold, Cool, Warm, Hot
}
Public Class WeatherForecastWithEnum
    Public Property [Date] As DateTimeOffset
    Public Property TemperatureCelsius As Integer
    Public Property Summary As Summary
End Class

Public Enum Summary
    Cold
    Cool
    Warm
    Hot
End Enum

Se o Resumo for Hot, por padrão, o JSON serializado terá o valor numérico 3:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": 3
}

O seguinte código de exemplo serializa os nomes de enumeração em vez dos valores numéricos e converte os nomes em maiúsculas e minúsculas concatenadas:

options = new JsonSerializerOptions
{
    WriteIndented = true,
    Converters =
    {
        new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
    }
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
options = New JsonSerializerOptions With {
    .WriteIndented = True
}
options.Converters.Add(New JsonStringEnumConverter(JsonNamingPolicy.CamelCase))
jsonString = JsonSerializer.Serialize(weatherForecast, options)

O JSON resultante é semelhante ao seguinte exemplo:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "hot"
}

O JsonStringEnumConverter interno também pode desserializar valores de cadeia de caracteres. Ele funciona com ou sem uma política de nomenclatura especificada. O seguinte exemplo mostra a desserialização usando CamelCase:

options = new JsonSerializerOptions
{
    Converters =
    {
        new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
    }
};
weatherForecast = JsonSerializer.Deserialize<WeatherForecastWithEnum>(jsonString, options)!;
options = New JsonSerializerOptions
options.Converters.Add(New JsonStringEnumConverter(JsonNamingPolicy.CamelCase))
weatherForecast = JsonSerializer.Deserialize(Of WeatherForecastWithEnum)(jsonString, options)

Você também pode especificar o conversor a ser usado anotando a enumeração com JsonConverterAttribute. O exemplo a seguir mostra como especificar o JsonStringEnumConverter<TEnum> (disponível no .NET 8 e versões posteriores) usando o atributo JsonConverterAttribute. Por exemplo, suponha que você precise serializar a seguinte classe que tem uma enumeração:

public class WeatherForecastWithPrecipEnum
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public Precipitation? Precipitation { get; set; }
}

[JsonConverter(typeof(JsonStringEnumConverter<Precipitation>))]
public enum Precipitation
{
    Drizzle, Rain, Sleet, Hail, Snow
}

O seguinte código de exemplo serializa os nomes de enumeração, em vez dos valores numéricos:

var options = new JsonSerializerOptions
{
    WriteIndented = true,
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);

O JSON resultante é semelhante ao seguinte exemplo:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Precipitation": "Sleet"
}

Para usar o conversor com geração de origem, confira Serializar campos de enumeração como cadeias de caracteres.

Configurar a ordem das propriedades serializadas

Por padrão, as propriedades são serializadas na ordem em que são definidas na classe. O atributo [JsonPropertyOrder] permite que você especifique a ordem das propriedades na saída JSON da serialização. O valor padrão da propriedade Order é zero. Defina Order como um número positivo para posicionar uma propriedade depois daquelas que têm o valor padrão. Um Order negativo posiciona uma propriedade antes daquelas que têm o valor padrão. As propriedades são escritas na ordem do valor Order mais baixo ao mais alto. Veja um exemplo:

using System.Text.Json;
using System.Text.Json.Serialization;

namespace PropertyOrder
{
    public class WeatherForecast
    {
        [JsonPropertyOrder(-5)]
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        [JsonPropertyOrder(-2)]
        public int TemperatureF { get; set; }
        [JsonPropertyOrder(5)]
        public string? Summary { get; set; }
        [JsonPropertyOrder(2)]
        public int WindSpeed { get; set; }
    }

    public class Program
    {
        public static void Main()
        {
            var weatherForecast = new WeatherForecast
            {
                Date = DateTime.Parse("2019-08-01"),
                TemperatureC = 25,
                TemperatureF = 25,
                Summary = "Hot",
                WindSpeed = 10
            };

            var options = new JsonSerializerOptions { WriteIndented = true };
            string jsonString = JsonSerializer.Serialize(weatherForecast, options);
            Console.WriteLine(jsonString);
        }
    }
}
// output:
//{
//  "Date": "2019-08-01T00:00:00",
//  "TemperatureF": 25,
//  "TemperatureC": 25,
//  "WindSpeed": 10,
//  "Summary": "Hot"
//}

Confira também