Skip to content

Commit

Permalink
Deserializer breaking change (dotnet#37112)
Browse files Browse the repository at this point in the history
  • Loading branch information
gewarren authored and IEvangelist committed Oct 2, 2023
1 parent b667031 commit 32486d3
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 2 deletions.
3 changes: 2 additions & 1 deletion docs/core/compatibility/8.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Breaking changes in .NET 8
titleSuffix: ""
description: Navigate to the breaking changes in .NET 8.
ms.date: 06/05/2023
ms.date: 09/13/2023
no-loc: [Blazor, Razor, Kestrel]
---
# Breaking changes in .NET 8
Expand Down Expand Up @@ -132,6 +132,7 @@ If you're migrating an app to .NET 8, the breaking changes listed here might aff
| Title | Type of change | Introduced |
| ------------------------------------------------------------------------------------------- | ----------------- | ---------- |
| [BinaryFormatter disabled for most projects](serialization/8.0/binaryformatter-disabled.md) | Behavioral change | Preview 4 |
| [Reflection-based deserializer resolves metadata eagerly](serialization/8.0/metadata-resolving.md) | Behavioral change | Preview 4 |

## Windows Forms

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Breaking change: BinaryFormatter disabled across most project types"
description: Learn about the .NET 7 breaking change in serialization where serialize and deserialize methods on BinaryFormatter now throw an exception at run time.
description: Learn about the .NET 8 breaking change in serialization where serialize and deserialize methods on BinaryFormatter now throw an exception at run time.
ms.date: 05/01/2023
---
# BinaryFormatter disabled across most project types
Expand Down
73 changes: 73 additions & 0 deletions docs/core/compatibility/serialization/8.0/metadata-resolving.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
title: "Breaking change: Reflection-based deserializer resolves metadata eagerly"
description: Learn about the .NET 8 breaking change in System.Text.Json serialization where the reflection-based deserializer resolves property metadata eagerly.
ms.date: 09/13/2023
---
# Reflection-based deserializer resolves metadata eagerly

The System.Text.Json reflection-based serializer previously used a lazy loading approach to resolve property metadata. That approach made it possible for POCOs that contained unsupported property types to deserialize successfully, provided that the underlying JSON didn't bind to any of the unsupported properties. (This was despite the fact that instances of the same type would fail to *serialize*.)

Starting with .NET 8, the serializer has been changed so that all properties are resolved eagerly in both serialization and deserialization. This change was made to add better support for combining multiple resolvers, which necessitates early analysis of the serialized type graph. A side-effect of this change is that if you depended on the previous behavior, you could start seeing new runtime deserialization errors.

## Previous behavior

The following deserialization code succeeded in .NET 7.

```csharp
var result = JsonSerializer.Deserialize<MyPoco>("""{ "Value": 1 }"""); //, MyContext.Default.MyPoco);
Console.WriteLine(result.Value);

public class MyPoco
{
public int Value { get; set; }

public NestedValue Unsupported { get; set; }
}

public class NestedValue
{
public ReadOnlySpan<byte> Span => Array.Empty<byte>();
}
```

## New behavior

Starting in .NET 8, the same code from the [Previous behavior](#previous-behavior) section throws an <xref:System.InvalidOperationException> at run time.

> System.InvalidOperationException: The type 'System.ReadOnlySpan`1[System.Byte]' of property 'Span' on type 'NestedValue' is invalid for serialization or deserialization because it is a pointer type, is a ref struct, or contains generic parameters that have not been replaced by specific types.
This error is consistent with the error that was thrown even in previous versions if you attempted to serialize an instance of the same type. It's also consistent with the source generator, which produces a compile-time error.

## Version introduced

.NET 8 Preview 4

## Type of breaking change

This change is a [behavioral change](../../categories.md#behavioral-change).

## Reason for change

This change was necessitated by new requirements related to fast-path serialization support in combined source generated contexts (see [dotnet/runtime#71933](https://github.com/dotnet/runtime#71933)).

## Recommended action

If this change is problematic for you, you can:

- Remove the unsupported property from your type.
- Author a custom converter for the unsupported type.
- Add the <xref:System.Text.Json.Serialization.JsonIgnoreAttribute> attribute:

```csharp
public class MyPoco
{
public int Value { get; set; }

[JsonIgnore]
public NestedValue Unsupported { get; set; }
}
```

## Affected APIs

- <xref:System.Text.Json.JsonSerializer.Deserialize%2A?displayProperty=fullName>
4 changes: 4 additions & 0 deletions docs/core/compatibility/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ items:
items:
- name: BinaryFormatter disabled for most projects
href: serialization/8.0/binaryformatter-disabled.md
- name: Reflection-based deserializer resolves metadata eagerly
href: serialization/8.0/metadata-resolving.md
- name: Windows Forms
items:
- name: Anchor layout changes
Expand Down Expand Up @@ -1596,6 +1598,8 @@ items:
items:
- name: BinaryFormatter disabled for most projects
href: serialization/8.0/binaryformatter-disabled.md
- name: Reflection-based deserializer resolves metadata eagerly
href: serialization/8.0/metadata-resolving.md
- name: .NET 7
items:
- name: BinaryFormatter serialization APIs produce compiler errors
Expand Down

0 comments on commit 32486d3

Please sign in to comment.