Modalità di generazione di origine in System.Text.Json

La generazione di origine può essere usata in due modalità: basata sui metadati e ottimizzazione della serializzazione. Questo articolo descrive le diverse modalità.

Per informazioni su come usare le modalità di generazione di origine, vedere Come usare la generazione di origine in System.Text.Json.

Modalità basata su metadati

È possibile usare la generazione di origine per spostare il processo di raccolta dei metadati dal runtime alla fase di compilazione. Durante la compilazione, i metadati vengono raccolti e vengono generati i file di codice sorgente. I file di codice sorgente generati vengono compilati automaticamente come parte integrante dell'applicazione. Questa tecnica elimina la raccolta di metadati di runtime, migliorando le prestazioni della serializzazione e della deserializzazione.

I miglioramenti delle prestazioni offerti dalla generazione di origine possono essere sostanziali. Ad esempio, risultati dei test hanno mostrato fino al 40% o più di riduzione del tempo di avvio, riduzione della memoria privata, aumento della velocità effettiva (in modalità di ottimizzazione della serializzazione) e riduzione delle dimensioni dell'app.

Membri e costruttori non pubblici

Per impostazione predefinita, sia la modalità reflection che la modalità di generazione del codice sorgente includono nel contratto di serializzazione solo le proprietà e i campi public.

A partire da .NET 11, la generazione di origine supporta i membri contrassegnati in modo esplicito con l'attributo [JsonInclude]. Il membro può essere private, internalo protected. Supporta anche i metodi di accesso private, internal e protected sulle proprietà contrassegnate con [JsonInclude]. La generazione di origine supporta anche costruttori inaccessibili contrassegnati con [JsonConstructor].

In .NET 11 le funzioni di accesso generate usano UnsafeAccessorAttribute.

Un setter generato dal codice sorgente per una proprietà di sola init viene invocato solo quando il payload JSON contiene tale proprietà. Una proprietà init-only che viene omessa dal payload mantiene il valore del relativo inizializzatore di proprietà.

In .NET 10 e versioni precedenti, la generazione di origine presenta le limitazioni seguenti:

  • La generazione del codice sorgente non supporta membri o metodi di accesso private o protected. Se si contrassegna tale membro con [JsonInclude], il serializzatore genera NotSupportedException in fase di esecuzione.
  • La generazione del codice sorgente supporta solo i membri e gli accessori internal quando sono accessibili al JsonSerializerContext generato nello stesso assembly.
  • La generazione di origine non supporta costruttori inaccessibili al contesto generato, anche quando vengono contrassegnati con [JsonConstructor].

Problemi noti

Per informazioni su altri problemi noti relativi alla generazione di origine, vedere i problemi di GitHub etichettati come "generatore di origine" nel repository dotnet/runtime.

Modalità ottimizzazione della serializzazione (via veloce)

JsonSerializer include molte funzionalità che consentono di personalizzare l'output della serializzazione, ad esempio criteri di denominazione e mantenere i riferimenti. Il supporto per tutte queste funzionalità causa un sovraccarico delle prestazioni. La generazione del codice sorgente può migliorare le prestazioni di serializzazione producendo codice ottimizzato che utilizza direttamente Utf8JsonWriter.

La modalità di ottimizzazione della serializzazione genera metodi di serializzazione fast-path, ma non metadati di serializzazione. La serializzazione fast-path è limitata in ciò che può fare; non supporta la serializzazione asincrona o qualsiasi modalità di deserializzazione.

Inoltre, il codice ottimizzato non supporta tutte le funzionalità di serializzazione supportate JsonSerializer . Il serializzatore rileva se il codice ottimizzato può essere usato ed esegue il fallback al codice di serializzazione predefinito se vengono specificate opzioni non supportate. Ad esempio, JsonNumberHandling.AllowReadingFromString non è applicabile alla scrittura, quindi specificando questa opzione non viene generato un fallback nel codice predefinito.

La tabella seguente illustra le opzioni in JsonSerializerOptions supportate dalla serializzazione fast-path:

Opzione di serializzazione È supportato per il fast-path
AllowTrailingCommas ✔️
Converters ❌
DefaultBufferSize ✔️
DefaultIgnoreCondition ✔️
DictionaryKeyPolicy ❌
Encoder ❌
IgnoreNullValues ❌
IgnoreReadOnlyFields ✔️
IgnoreReadOnlyProperties ✔️
IncludeFields ✔️
MaxDepth ✔️
NumberHandling ❌
PropertyNamingPolicy ✔️
ReferenceHandler ❌
TypeInfoResolver ✔️
WriteIndented ✔️

Le opzioni seguenti non sono supportate perché si applicano solo alla deserializzazione: PropertyNameCaseInsensitive, ReadCommentHandlinge UnknownTypeHandling.

La tabella seguente illustra gli attributi supportati dalla serializzazione fast-path:

Attributo È supportato per il fast-path
JsonConstructorAttribute ❌
JsonConverterAttribute ❌
JsonDerivedTypeAttribute ✔️
JsonExtensionDataAttribute ❌
JsonIgnoreAttribute ✔️
JsonIncludeAttribute ✔️
JsonNumberHandlingAttribute ❌
JsonPolymorphicAttribute ✔️
JsonPropertyNameAttribute ✔️
JsonPropertyOrderAttribute ✔️
JsonRequiredAttribute ✔️

Se per un tipo viene specificata un'opzione o un attributo non supportato, il serializzatore esegue il fallback alla modalità metadati, presupponendo che il generatore di origine sia stato configurato per generare metadati. In tal caso, il codice ottimizzato non viene usato durante la serializzazione di tale tipo, ma potrebbe essere usato per altri tipi. È quindi importante eseguire test delle prestazioni con le opzioni e i carichi di lavoro per determinare il vantaggio che è effettivamente possibile ottenere dalla modalità di ottimizzazione della serializzazione. Inoltre, la possibilità di eseguire il fallback al JsonSerializer codice richiede la modalità metadati. Se si seleziona solo la modalità di ottimizzazione della serializzazione, la serializzazione potrebbe non riuscire per tipi o opzioni che devono eseguire il fallback al codiceJsonSerializer.

Vedi anche