Comment personnaliser les noms et valeurs de propriétés avec System.Text.Json

Par défaut, les noms de propriétés et les clés de dictionnaire sont inchangés dans la sortie JSON, y compris la casse. Les valeurs d’énumération sont représentées sous forme de nombres. De plus, les propriétés sont sérialisées dans l’ordre dans lequel elles sont définies. Vous pouvez toutefois personnaliser ces comportements en :

  • Spécifiant des noms de propriétés sérialisées spécifiques.
  • Utilisant une stratégie d’attribution de noms intégrée, telle que les mots en casse mixte (camelCase), les mots séparés par des caractères de soulignement (snake_case) ou par des tirets (kebab-case), pour les noms de propriétés et les clés de dictionnaire.
  • Utilisant une stratégie d’attribution de noms personnalisée pour les noms de propriétés et les clés de dictionnaire.
  • Sérialisant les valeurs d’énumération sous forme de chaînes, avec ou sans stratégie d’attribution de noms.
  • Configurant l’ordre des propriétés sérialisées.

Remarque

La stratégie d’attribution de noms des valeurs web par défaut est la casse mixte.

Pour les autres scénarios qui nécessitent une gestion spéciale des noms et des valeurs de propriétés JSON, vous pouvez implémenter des convertisseurs personnalisés.

Personnaliser les noms de propriétés individuelles

Pour définir le nom de propriétés individuelles, utilisez l’attribut [JsonPropertyName].

Voici un exemple de type à sérialiser et de JSON résultant :

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
}

Nom de propriété défini par cet attribut :

Utiliser une stratégie d’attribution de noms intégrée

Le tableau ci-dessous montre les stratégies d’attribution de noms intégrées et leur impact sur les noms de propriétés.

Stratégie d’affectation de noms Description Nom de propriété d’origine Nom de propriété converti
CamelCase Le premier mot commence par un caractère minuscule.
Les mots successifs commencent par un caractère majuscule.
TempCelsius tempCelsius
KebabCaseLower* Les mots sont séparés par des tirets.
Tous les caractères sont minuscules.
TempCelsius temp-celsius
KebabCaseUpper* Les mots sont séparés par des tirets.
Tous les caractères sont majuscules.
TempCelsius TEMP-CELSIUS
SnakeCaseLower* Les mots sont séparés par des traits de soulignement.
Tous les caractères sont minuscules.
TempCelsius temp_celsius
SnakeCaseUpper* Les mots sont séparés par des traits de soulignement.
Tous les caractères sont majuscules.
TempCelsius TEMP_CELSIUS

* Disponible dans .NET 8 et versions ultérieures.

L’exemple ci-dessous montre comment utiliser la casse mixte pour tous les noms de propriétés JSON en définissant JsonSerializerOptions.PropertyNamingPolicy sur 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)

Voici un exemple de classe à sérialiser et une sortie 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
}

La stratégie d’attribution de noms :

  • S’applique à la sérialisation et à la désérialisation.
  • Est remplacé par des attributs [JsonPropertyName]. C’est pourquoi le nom de propriété JSON Wind dans l’exemple n’est pas en casse mixte.

Remarque

Aucune des stratégies d’attribution de noms intégrées ne prend en charge les lettres qui sont des paires de substitution. Pour plus d’informations, consultez le problème dotnet/runtime 90352.

Utiliser une stratégie de nommage de propriétés JSON personnalisée

Pour utiliser une stratégie de nommage de propriétés JSON personnalisée, créez une classe qui dérive de JsonNamingPolicy et remplace la méthode ConvertName, comme indiqué dans l’exemple suivant :

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

Définissez ensuite la propriété JsonSerializerOptions.PropertyNamingPolicy sur une instance de votre classe de stratégie d’affectation de noms :

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)

Voici un exemple de classe à sérialiser et une sortie 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
}

Stratégie de nommage de propriétés JSON :

  • S’applique à la sérialisation et à la désérialisation.
  • Est remplacé par des attributs [JsonPropertyName]. C’est pourquoi le nom de propriété JSON Wind dans l’exemple n’est pas en majuscules.

Utiliser une stratégie d’attribution de noms pour les clés de dictionnaire

Si une propriété d’un objet à sérialiser est de type Dictionary<string,TValue>, les clés string peuvent être converties à l’aide d’une stratégie d’attribution de noms (casse mixte, par exemple). Pour ce faire, définissez JsonSerializerOptions.DictionaryKeyPolicy votre stratégie d’attribution de noms souhaitée. L’exemple suivant utilise la stratégie d’attribution de noms 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)

Sérialiser un objet avec un dictionnaire nommé TemperatureRanges qui a des paires clé-valeur "ColdMinTemp", 20 et "HotMinTemp", 40 entraînerait une sortie JSON semblable à l’exemple suivant :

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

Les stratégies d’attribution de noms pour les clés de dictionnaire s’appliquent uniquement à la sérialisation. Si vous désérialisez un dictionnaire, les clés correspondent au fichier JSON même si vous définissez JsonSerializerOptions.DictionaryKeyPolicy sur une stratégie d’attribution de noms autre que par défaut.

Énumérations sous forme de chaînes

Par défaut, les énumérations sont sérialisées en tant que nombres. Pour sérialiser des noms d’énumération sous forme de chaînes, utilisez le convertisseur JsonStringEnumConverter ou JsonStringEnumConverter<TEnum>. Seul JsonStringEnumConverter<TEnum> est pris en charge par le runtime AOT natif.

Par défaut, les énumérations sont sérialisées en tant que nombres. Pour sérialiser des noms d’énumération sous forme de chaînes, utilisez le convertisseur JsonStringEnumConverter.

Par exemple, supposons que vous deviez sérialiser la classe suivante qui a une énumération :

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

Si le résumé est Hot, par défaut, le JSON sérialisé a la valeur numérique 3 :

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

L’exemple de code suivant sérialise les noms d’énumération au lieu des valeurs numériques et convertit les noms en casse mixte :

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)

Le JSON obtenu ressemble à l’exemple suivant :

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

Le composant intégré JsonStringEnumConverter peut également désérialiser les valeurs de chaîne. Il fonctionne avec ou sans stratégie d’attribution de noms spécifiée. L’exemple suivant illustre la désérialisation à l’aide de 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)

Vous pouvez également spécifier le convertisseur à utiliser en annotant votre énumération avec JsonConverterAttribute. L’exemple ci-dessous montre comment spécifier JsonStringEnumConverter<TEnum> (disponible dans .NET 8 et versions ultérieures) à l’aide de l’attribut JsonConverterAttribute. Par exemple, supposons que vous deviez sérialiser la classe suivante qui a une énumération :

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
}

L’exemple de code suivant sérialise les noms d’énumération au lieu des valeurs numériques :

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

Le JSON obtenu ressemble à l’exemple suivant :

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

Pour utiliser le convertisseur avec la génération de source, consultez la section Sérialiser les champs d’énumération sous forme de chaînes.

Configurer l’ordre des propriétés sérialisées

Par défaut, les propriétés sont sérialisées dans l’ordre dans lequel elles sont définies dans leur classe. L’attribut [JsonPropertyOrder] vous permet de spécifier l’ordre des propriétés dans la sortie JSON de la sérialisation. La valeur par défaut de la propriété Order est zéro. Définissez Order sur un nombre positif pour positionner une propriété après celles qui ont la valeur par défaut. Une valeur négative Order positionne une propriété avant celles qui ont la valeur par défaut. Les propriétés sont écrites dans l’ordre, de la valeur Order la plus faible à la plus élevée. Voici un exemple :

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"
//}

Voir aussi