Condividi tramite


Come personalizzare nomi e valori delle proprietà con System.Text.Json

Per impostazione predefinita, i nomi delle proprietà e le chiavi del dizionario rimangono invariati nell'output JSON, incluso il case. I valori di enumerazione sono rappresentati come numeri e le proprietà vengono serializzate nell'ordine in cui sono definite. È tuttavia possibile personalizzare tale comportamento utilizzando uno dei seguenti metodi:

  • Specificare nomi di proprietà serializzate e di membri dell'enumerato.
  • Uso di un criterio di denominazione predefinito, ad esempio camelCase, snake_case o kebab-case, per i nomi delle proprietà e le chiavi del dizionario.
  • Uso di un criterio di denominazione personalizzato per i nomi delle proprietà e le chiavi del dizionario.
  • Serializzazione dei valori di enumerazione come stringhe, con o senza una politica di denominazione.
  • Configurazione dell'ordine delle proprietà serializzate.

Nota

Il criterio di denominazione Web predefinito è camel case.

Suggerimento

È possibile usare l'assistenza per intelligenza artificiale per creare un oggetto con proprietà di serializzazione personalizzate.

Per altri scenari che richiedono una gestione speciale dei nomi e dei valori delle proprietà JSON, è possibile implementare convertitori personalizzati.

Personalizzare i nomi delle singole proprietà

Per impostare il nome delle singole proprietà, usare l'attributo [JsonPropertyName].

Di seguito è riportato un tipo di esempio per serializzare e ottenere il JSON risultante:

public class WeatherForecastWithPropertyName
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyName
    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
}

Il nome della proprietà impostato da questo attributo:

Usare un criterio di denominazione predefinito

La tabella seguente illustra i criteri di denominazione predefiniti e il modo in cui influiscono sui nomi delle proprietà.

Criteri di denominazione Descrizione Nome della proprietà originale Nome della proprietà convertito
CamelCase La prima parola inizia con un carattere minuscolo.
Le parole successive iniziano con un carattere maiuscolo.
TempCelsius tempCelsius
KebabCaseLower* Le parole sono separate da trattini.
Tutti i caratteri sono minuscoli.
TempCelsius temp-celsius
KebabCaseUpper* Le parole sono separate da trattini.
Tutti i caratteri sono maiuscoli.
TempCelsius TEMP-CELSIUS
SnakeCaseLower* Le parole sono separate da trattini bassi.
Tutti i caratteri sono minuscoli.
TempCelsius temp_celsius
SnakeCaseUpper* Le parole sono separate da trattini bassi.
Tutti i caratteri sono maiuscoli.
TempCelsius TEMP_CELSIUS

* Disponibile in .NET 8 e versioni successive.

L'esempio seguente illustra come usare il case camel per tutti i nomi di proprietà JSON impostando JsonSerializerOptions.PropertyNamingPolicy su 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)

Ecco una classe di esempio per serializzare e l'output JSON:

public class WeatherForecastWithPropertyName
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyName
    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
}

Il criterio di denominazione:

  • Si applica alla serializzazione e deserializzazione.
  • Viene sovrascritto dagli attributi [JsonPropertyName]. Questo è il motivo per cui il nome della proprietà JSON Wind riportato nell'esempio non è in camel case.

Nota

Nessuno dei criteri di denominazione predefiniti supporta lettere che sono coppie surrogate. Per ottenere ulteriori informazioni, vedere Problema dotnet/runtime 90352.

Usare un criterio di denominazione delle proprietà JSON personalizzato

Per usare un criterio di denominazione delle proprietà JSON personalizzato, creare una classe che deriva da JsonNamingPolicy ed eseguirne l'override del metodo ConvertName, come illustrato nell'esempio seguente:

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

Impostare quindi la proprietà JsonSerializerOptions.PropertyNamingPolicy su un'istanza della classe dei criteri di denominazione:

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)

Ecco una classe di esempio per serializzare e l'output JSON:

public class WeatherForecastWithPropertyName
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
    [JsonPropertyName("Wind")]
    public int WindSpeed { get; set; }
}
Public Class WeatherForecastWithPropertyName
    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
}

Il criterio di denominazione delle proprietà JSON:

  • Si applica alla serializzazione e deserializzazione.
  • Viene sovrascritto dagli attributi [JsonPropertyName]. Questo è il motivo per cui il nome della proprietà JSON Wind riportato nell'esempio non è scritto in maiuscolo.

Usare un criterio di denominazione per le chiavi del dizionario

Se una proprietà di un oggetto da serializzare è di tipo Dictionary<string,TValue>, le chiavi string possono essere convertite usando criteri di denominazione, ad esempio camel case. A tale scopo, impostare JsonSerializerOptions.DictionaryKeyPolicy sui criteri di denominazione desiderati. L'esempio seguente usa il criterio di denominazione 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)

Serializzare un oggetto con un dizionario denominato TemperatureRanges con coppie chiave-valore "ColdMinTemp", 20 e "HotMinTemp", 40 produrrebbe un output JSON simile all'esempio seguente:

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

I criteri di denominazione per le chiavi del dizionario si applicano solo alla serializzazione. Se si deserializza un dizionario, le chiavi corrisponderanno al file JSON anche se si imposta JsonSerializerOptions.DictionaryKeyPolicy su un criterio di denominazione non predefinito.

Enumerazioni come stringhe

Le enumerazioni vengono serializzate come numeri per impostazione predefinita. Per serializzare i nomi delle enumerazioni come stringhe, usare il convertitoreJsonStringEnumConverter o JsonStringEnumConverter<TEnum>. Solo JsonStringEnumConverter<TEnum> è supportato dal runtime AOT nativo.

Si supponga, ad esempio, di dover serializzare la classe seguente che possiede un enum:

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 riepilogo è Hot, per impostazione predefinita il codice JSON serializzato ha il valore numerico 3:

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

Il seguente codice di esempio serializza i nomi delle enum anziché i valori numerici e converte i nomi in camel case.

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)

Il codice JSON risultante è simile al seguente esempio:

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

Il valore predefinito JsonStringEnumConverter può deserializzare anche i valori stringa. Funziona con o senza un criterio di denominazione specificato. Nell'esempio seguente viene illustrata la deserializzazione 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)

JsonConverterAttribute

È anche possibile specificare il convertitore da usare annotando l'enumerazione con JsonConverterAttribute. Nell'esempio seguente viene illustrato come specificare JsonStringEnumConverter<TEnum> (disponibile in .NET 8 e versioni successive) usando l'attributo JsonConverterAttribute. Si supponga, ad esempio, di dover serializzare la classe seguente che possiede un enum:

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
}

Il codice seguente serializza i nomi delle enumerazioni anziché i valori numerici:

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

Il codice JSON risultante ha l'aspetto seguente:

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

Nomi di membri di enumerazione personalizzati

A partire da .NET 9, è possibile personalizzare i nomi dei singoli membri dell'enumerazione per i tipi che vengono serializzati come stringhe. Per personalizzare un nome di membro enum, annotarlo con l'attributo JsonStringEnumMemberName.

Si supponga, ad esempio, di dover serializzare la classe seguente che presenta un'enumerazione con un nome di membro personalizzato.

public class WeatherForecastWithEnumCustomName
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public CloudCover? Sky { get; set; }
}

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum CloudCover
{
    Clear,
    [JsonStringEnumMemberName("Partly cloudy")]
    Partial,
    Overcast
}

Il codice seguente serializza i nomi delle enumerazioni anziché i valori numerici:

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

Il codice JSON risultante ha l'aspetto seguente:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Sky": "Partly cloudy"
}

Generazione di fonte

Per usare il convertitore con la generazione del codice sorgente, consultare Serializzare i campi enumerazione come stringhe.

Configurare l'ordine delle proprietà serializzate

Per impostazione predefinita, le proprietà vengono serializzate nell'ordine in cui sono definite nella classe di appartenenza. L'attributo [JsonPropertyOrder] consente di specificare l'ordine delle proprietà nell'output JSON dalla serializzazione. Il valore predefinito della proprietà Order è zero. Impostare Order su un numero positivo per posizionare una proprietà dopo quelle con il valore predefinito. Una proprietà negativa Order posiziona una proprietà prima di quelle con il valore predefinito. Le proprietà vengono scritte in ordine dal valore Order più basso al più alto. Ecco un esempio:

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

Usare l'intelligenza artificiale per personalizzare la modalità di serializzazione dei nomi delle proprietà

È possibile usare strumenti di intelligenza artificiale, ad esempio GitHub Copilot, per applicare modelli di modifiche alla modalità di serializzazione del codice.

Si supponga che la dichiarazione di classe abbia proprietà che seguono PascalCasinge che lo standard JSON per il progetto sia snake_casing. È possibile usare l'intelligenza artificiale per aggiungere gli attributi [JsonPropertyName] necessari a ogni proprietà della classe. È possibile usare Copilot per apportare queste modifiche con una richiesta di chat simile alla seguente:

Update #ClassName:
when the property name contains more than one word,
change the serialized property name to use underscores between words.
Use built-in serialization attributes.

Ecco una versione più completa dell'esempio che include una classe semplice.

Take this C# class: 
public class WeatherForecast
{
    public DateTime Date { get; set; }
    public int TemperatureC { get; set; }
    public int TemperatureF { get; set; }
    public string? Summary { get; set; }
    public int WindSpeed { get; set; }
}
When the property name contains more than one word,
change the serialized property name to use underscores between words.
Use built-in serialization attributes.

GitHub Copilot è supportato dall'IA, quindi sono possibili sorprese ed errori. Per altre informazioni, vedere domande frequenti su Copilot.

Vedi anche