Rezerwa generatora źródła System.Text.Json
W przypadku korzystania z jednej z JsonSerializer metod, które akceptują JsonSerializerOptions, System.Text.Json generator źródła nie będzie już niejawnie wracać do serializacji opartej na odbiciu dla nierozpoznanych typów.
Poprzednie zachowanie
Rozważmy następujący przykład generowania źródła na platformie .NET 6:
JsonSerializer.Serialize(new Poco2(), typeof(Poco2), MyContext.Default);
[JsonSerializable(typeof(Poco1))]
public partial class MyContext : JsonSerializerContext {}
public class Poco1 { }
public class Poco2 { }
Ponieważ MyContext
nie uwzględnia Poco2
w typach możliwych do serializacji, serializacja zakończy się niepowodzeniem z następującym wyjątkiem:
System.InvalidOperationException:
'Metadata for type 'Poco2' was not provided to the serializer. The serializer method used does not
support reflection-based creation of serialization-related type metadata. If using source generation,
ensure that all root types passed to the serializer have been indicated with 'JsonSerializableAttribute',
along with any types that might be serialized polymorphically.
Teraz rozważ następujące wywołanie, które próbuje serializować ten sam typ (MyContext
) przy użyciu JsonSerializerOptions wystąpienia skonstruowanego przez generator źródła:
JsonSerializer.Serialize(new Poco2(), MyContext.Default.Options);
Wystąpienie opcji dyskretnie uwzględnia domyślny program rozpoznawania kontraktów oparty na odbiciu jako mechanizm rezerwowy, a w związku z tym typ serializuje pomyślnie — przy użyciu odbicia.
Ta sama logika rezerwowa ma zastosowanie do JsonSerializerOptions.GetConverter(Type) wystąpień opcji dołączonych do elementu JsonSerializerContext. Poniższa instrukcja zwróci konwerter przy użyciu wbudowanego konwertera odbicia:
JsonConverter converter = MyContext.Default.Options.GetConverter(typeof(Poco2));
Nowe zachowanie
Począwszy od platformy .NET 7, następujące wywołanie kończy się niepowodzeniem z tym samym wyjątkiem (InvalidOperationException), co w przypadku korzystania z JsonSerializerContext przeciążenia:
JsonSerializer.Serialize(new Poco2(), MyContext.Default.Options);
Ponadto następująca instrukcja zakończy się niepowodzeniem z elementem NotSupportedException:
JsonConverter converter = MyContext.Default.Options.GetConverter(typeof(Poco2));
Wprowadzona wersja
.NET 7
Typ zmiany powodującej niezgodność
Ta zmiana może mieć wpływ na zgodność binarną.
Przyczyna wprowadzenia zmiany
Poprzednie zachowanie narusza zasadę najmniejszego zaskoczenia i ostatecznie pokonuje cel generowania źródła. Wraz z wydaniem funkcji, która umożliwia dostosowanie kontraktów serializacji JSON typów, możesz dostosować źródła metadanych kontraktu. Mając to na uwadze, po cichu wprowadzenie alternatywnych źródeł staje się jeszcze mniej pożądane.
Zalecana akcja
Może zależeć od poprzedniego zachowania, celowo lub przypadkowo. Zalecanym przebiegiem akcji jest zaktualizowanie JsonSerializerContext definicji tak, aby zawierała wszystkie zależności typu:
[JsonSerializable(typeof(Poco1))]
[JsonSerializable(typeof(Poco2))]
public partial class MyContext : JsonSerializerContext {}
Dzięki temu aplikacja będzie w pełni korzystać z zalet generowania źródła, w tym bezpieczeństwa przycinania.
Jednak w niektórych przypadkach wprowadzenie takiej zmiany może nie być praktyczne lub możliwe. Mimo że nie jest to zalecane, istnieje kilka sposobów ponownego włączenia rezerwowego odbicia w serializatorze generowanym przez źródło.
Korzystanie z niestandardowego modułu rozpoznawania kontraktów
Możesz użyć nowej funkcji dostosowywania kontraktu, aby utworzyć niestandardowy program rozpoznawania kontraktów, który wraca do rozwiązania opartego na odbiciu, jeśli jest to wymagane:
var options = new JsonSerializerOptions
{
TypeInfoResolver = JsonTypeInfoResolver.Combine(MyContext.Default, new DefaultJsonTypeInfoResolver());
}
JsonSerializer.Serialize(new Poco2(), options); // Contract resolution falls back to the default reflection-based resolver.
options.GetConverter(typeof(Poco2)); // Returns the reflection-based converter.
Używanie przełącznika AppContext
Począwszy od platformy .NET 7, można ponownie włączyć powrót odbicia globalnie przy użyciu dostarczonego przełącznika zgodności AppContext. Dodaj następujący wpis do pliku projektu aplikacji, aby ponownie włączyć rezerwę odbicia dla wszystkich kontekstów wygenerowanych przez źródło w aplikacji. Aby uzyskać więcej informacji na temat używania przełączników AppContext, zobacz artykuł dotyczący ustawień konfiguracji środowiska uruchomieniowego platformy .NET.
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Text.Json.Serialization.EnableSourceGenReflectionFallback" Value="true" />
</ItemGroup>
Dotyczy interfejsów API
- System.Text.Json.JsonSerializerOptions.GetConverter(Type)
- System.Text.Json.JsonSerializer.Serialize(Stream, Object, Type, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.Serialize(Object, Type, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.Serialize(Utf8JsonWriter, Object, Type, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.Serialize<TValue>(TValue, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.Serialize<TValue>(Stream, TValue, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.Serialize<TValue>(Utf8JsonWriter, TValue, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.SerializeAsync(Stream, Object, Type, JsonSerializerOptions, CancellationToken)
- System.Text.Json.JsonSerializer.SerializeAsync<TValue>(Stream, TValue, JsonSerializerOptions, CancellationToken)