Skip to content

Commit c98c07b

Browse files
Merge pull request #43135 from dotnet/main
Merge main into live
2 parents 24fc9a4 + f747d15 commit c98c07b

File tree

7 files changed

+71
-13
lines changed

7 files changed

+71
-13
lines changed

docs/core/whats-new/dotnet-9/libraries.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,8 @@ The <xref:System.Json.JsonObject> type now exposes ordered dictionary&ndash;like
544544

545545
:::code language="csharp" source="../snippets/dotnet-9/csharp/Serialization.cs" id="PropertyOrder":::
546546

547+
For more information, see [Manipulate property order](../../../standard/serialization/system-text-json/use-dom.md#manipulate-property-order).
548+
547549
### Customize enum member names
548550

549551
The new <xref:System.Text.Json.Serialization.JsonStringEnumMemberNameAttribute?displayProperty=nameWithType> attribute can be used to customize the names of individual enum members for types that are serialized as strings:

docs/framework/wcf/samples/weakly-typed-json-serialization-sample.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public class PersonalInfo
5353

5454
This can be cumbersome, especially if the client has to handle more than one type of JSON object.
5555

56-
The `JsonObject` type provided by this sample introduces a weakly-typed representation of the deserialized JSON object. `JsonObject` relies on the natural mapping between JSON objects and .NET Framework dictionaries, and the mapping between JSON arrays and .NET Framework arrays. The following code shows the `JsonObject` type.
56+
The `JsonObject` type provided by this sample introduces a weakly typed representation of the deserialized JSON object. `JsonObject` relies on the natural mapping between JSON objects and .NET Framework dictionaries, and the mapping between JSON arrays and .NET Framework arrays. The following code shows the `JsonObject` type.
5757

5858
```csharp
5959
// Instantiation of JsonObject json omitted

docs/standard/serialization/system-text-json/custom-contracts.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ There are two ways to plug into customization. Both involve obtaining a resolver
5050
The <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfo.Kind?displayProperty=nameWithType> property indicates how the converter serializes a given type&mdash;for example, as an object or as an array, and whether its properties are serialized. You can query this property to determine which aspects of a type's JSON contract you can configure. There are four different kinds:
5151

5252
| `JsonTypeInfo.Kind` | Description |
53-
| - | - |
53+
|---------------------|-------------|
5454
| <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfoKind.Object?displayProperty=nameWithType> | The converter will serialize the type into a JSON object and uses its properties. **This kind is used for most class and struct types and allows for the most flexibility.** |
5555
| <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfoKind.Enumerable?displayProperty=nameWithType> | The converter will serialize the type into a JSON array. This kind is used for types like `List<T>` and array. |
5656
| <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfoKind.Dictionary?displayProperty=nameWithType> | The converter will serialize the type into a JSON object. This kind is used for types like `Dictionary<K, V>`. |
@@ -63,7 +63,7 @@ A modifier is an `Action<JsonTypeInfo>` or a method with a <xref:System.Text.Jso
6363
The following table shows the modifications you can make and how to achieve them.
6464

6565
| Modification | Applicable `JsonTypeInfo.Kind` | How to achieve it | Example |
66-
| - | - | - | - |
66+
|--------------|--------------------------------|-------------------|---------|
6767
| Customize a property's value | `JsonTypeInfoKind.Object` | Modify the <xref:System.Text.Json.Serialization.Metadata.JsonPropertyInfo.Get?displayProperty=nameWithType> delegate (for serialization) or <xref:System.Text.Json.Serialization.Metadata.JsonPropertyInfo.Set?displayProperty=nameWithType> delegate (for deserialization) for the property. | [Increment a property's value](#example-increment-a-propertys-value) |
6868
| Add or remove properties | `JsonTypeInfoKind.Object` | Add or remove items from the <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfo.Properties?displayProperty=nameWithType> list. | [Serialize private fields](#example-serialize-private-fields) |
6969
| Conditionally serialize a property | `JsonTypeInfoKind.Object` | Modify the <xref:System.Text.Json.Serialization.Metadata.JsonPropertyInfo.ShouldSerialize?displayProperty=nameWithType> predicate for the property. | [Ignore properties with a specific type](#example-ignore-properties-with-a-specific-type) |
@@ -114,7 +114,7 @@ Besides customizing a contract, there are other ways to influence serialization
114114
- By modifying <xref:System.Text.Json.JsonSerializerOptions>, for example, to set a naming policy or serialize enumeration values as strings instead of numbers.
115115
- By writing a custom converter that does the actual work of writing the JSON and, during deserialization, constructing an object.
116116

117-
Contract customization is an improvement over these pre-existing customizations because you might not have access to the type to add attributes, and writing a custom converter is complex and hurts performance.
117+
Contract customization is an improvement over these pre-existing customizations because you might not have access to the type to add attributes. In addition, writing a custom converter is complex and hurts performance.
118118

119119
## See also
120120

docs/standard/serialization/system-text-json/polymorphism.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: How to serialize properties of derived classes with System.Text.Json
33
description: "Learn how to serialize polymorphic objects while serializing to and deserializing from JSON in .NET."
4-
ms.date: 09/30/2022
4+
ms.date: 10/18/2024
55
no-loc: [System.Text.Json, Newtonsoft.Json]
66
zone_pivot_groups: dotnet-version
77
dev_langs:
@@ -17,7 +17,7 @@ ms.topic: how-to
1717

1818
# How to serialize properties of derived classes with System.Text.Json
1919

20-
In this article, you will learn how to serialize properties of derived classes with the `System.Text.Json` namespace.
20+
In this article, you learn how to serialize properties of derived classes with the `System.Text.Json` namespace.
2121

2222
## Serialize properties of derived classes
2323

@@ -148,7 +148,7 @@ The following example shows the JSON that results from the preceding code:
148148
Beginning with .NET 7, `System.Text.Json` supports polymorphic type hierarchy serialization and deserialization with attribute annotations.
149149

150150
| Attribute | Description |
151-
|--|--|
151+
|-----------|-------------|
152152
| <xref:System.Text.Json.Serialization.JsonDerivedTypeAttribute> | When placed on a type declaration, indicates that the specified subtype should be opted into polymorphic serialization. It also exposes the ability to specify a type discriminator. |
153153
| <xref:System.Text.Json.Serialization.JsonPolymorphicAttribute> | When placed on a type declaration, indicates that the type should be serialized polymorphically. It also exposes various options to configure polymorphic serialization and deserialization for that type. |
154154

@@ -240,7 +240,7 @@ Public Class WeatherForecastWithCity
240240
End Class
241241
```
242242

243-
With the added metadata, specifically, the type discriminator, the serializer can serialize and deserialize the payload as the `WeatherForecastWithCity` type from its base type `WeatherForecastBase`. Serialization will emit JSON along with the type discriminator metadata:
243+
With the added metadata, specifically, the type discriminator, the serializer can serialize and deserialize the payload as the `WeatherForecastWithCity` type from its base type `WeatherForecastBase`. Serialization emits JSON along with the type discriminator metadata:
244244

245245
```csharp
246246
WeatherForecastBase weather = new WeatherForecastWithCity
@@ -289,14 +289,23 @@ WeatherForecastBase value = JsonSerializer.Deserialize<WeatherForecastBase>(json
289289
Console.WriteLine(value is WeatherForecastWithCity); // True
290290
```
291291

292-
> [!NOTE]
293-
> The type discriminator must be placed at the start of the JSON object, grouped together with other metadata properties like `$id` and `$ref`.
294-
295292
```vb
296293
Dim value As WeatherForecastBase = JsonSerializer.Deserialize(json)
297294
Console.WriteLine(value is WeatherForecastWithCity) // True
298295
```
299296

297+
<!--markdownlint-disable MD031-->
298+
> [!NOTE]
299+
> By default, the `$type` discriminator must be placed at the start of the JSON object, grouped together with other metadata properties like `$id` and `$ref`. If you're reading data off an external API that places the `$type` discriminator in the middle of the JSON object, set <xref:System.Text.Json.JsonSerializerOptions.AllowOutOfOrderMetadataProperties?displayProperty=nameWithType> to `true`:
300+
>
301+
> ```csharp
302+
> JsonSerializerOptions options = new() { AllowOutOfOrderMetadataProperties = true };
303+
> JsonSerializer.Deserialize<Base>("""{"Name":"Name","$type":"derived"}""", options);
304+
> ```
305+
>
306+
> Be careful when you enable this flag, as it might result in over-buffering (and out-of-memory failures) when performing streaming deserialization of very large JSON objects.
307+
<!--markdownlint-enable MD031-->
308+
300309
### Mix and match type discriminator formats
301310
302311
Type discriminator identifiers are valid in either `string` or `int` forms, so the following is valid:

docs/standard/serialization/system-text-json/preserve-references.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ The following code illustrates use of the `Preserve` setting.
3737

3838
This feature can't be used to preserve value types or immutable types. On deserialization, the instance of an immutable type is created after the entire payload is read. So it would be impossible to deserialize the same instance if a reference to it appears within the JSON payload.
3939

40-
For value types, immutable types, and arrays, no reference metadata is serialized. On deserialization, an exception is thrown if `$ref` or `$id` is found. However, value types ignore `$id` (and `$values` in the case of collections) to make it possible to deserialize payloads that were serialized by using Newtonsoft.Json. Newtonsoft.Json does serialize metadata for such types.
40+
For value types, immutable types, and arrays, no reference metadata is serialized. On deserialization, an exception is thrown if `$ref` or `$id` is found. However, value types ignore `$id` (and `$values` in the case of collections) to make it possible to deserialize payloads that were serialized by using Newtonsoft.Json, which does serialize metadata for such types.
4141

4242
To determine if objects are equal, System.Text.Json uses <xref:System.Collections.Generic.ReferenceEqualityComparer.Instance%2A?displayProperty=nameWithType>, which uses reference equality (<xref:System.Object.ReferenceEquals(System.Object,System.Object)?displayProperty=nameWithType>) instead of value equality (<xref:System.Object.Equals(System.Object)?displayProperty=nameWithType>) when comparing two object instances.
4343

@@ -47,7 +47,7 @@ The <xref:System.Text.Json.Serialization.ReferenceResolver> class defines the be
4747

4848
### Persist reference metadata across multiple serialization and deserialization calls
4949

50-
By default, reference data is only cached for each call to <xref:System.Text.Json.JsonSerializer.Serialize%2A> or <xref:System.Text.Json.JsonSerializer.Deserialize%2A>. To persist references from one `Serialize`/`Deserialize` call to another one, root the <xref:System.Text.Json.Serialization.ReferenceResolver> instance in the call site of `Serialize`/`Deserialize`. The following code shows an example for this scenario:
50+
By default, reference data is only cached for each call to <xref:System.Text.Json.JsonSerializer.Serialize%2A> or <xref:System.Text.Json.JsonSerializer.Deserialize%2A>. To persist references from one `Serialize` or `Deserialize` call to another one, root the <xref:System.Text.Json.Serialization.ReferenceResolver> instance in the call site of `Serialize`/`Deserialize`. The following code shows an example for this scenario:
5151

5252
* You have a list of `Employee` objects and you have to serialize each one individually.
5353
* You want to take advantage of the references saved in the resolver for the `ReferenceHandler`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System.Linq;
2+
using System.Text.Json;
3+
using System.Text.Json.Nodes;
4+
using System.Text.Json.Schema;
5+
6+
namespace JsonNodePropertyOrder;
7+
8+
public class Program
9+
{
10+
public static void Main()
11+
{
12+
// <Snippet1>
13+
var schema = (JsonObject)JsonSerializerOptions.Default.GetJsonSchemaAsNode(typeof(MyPoco));
14+
15+
JsonNode? idValue;
16+
switch (schema.IndexOf("$id"))
17+
{
18+
// $id property missing.
19+
case < 0:
20+
idValue = (JsonNode)"https://example.com/schema";
21+
schema.Insert(0, "$id", idValue);
22+
break;
23+
24+
// $id property already at the start of the object.
25+
case 0:
26+
break;
27+
28+
// $id exists but not at the start of the object.
29+
case int index:
30+
idValue = schema[index];
31+
schema.RemoveAt(index);
32+
schema.Insert(0, "$id", idValue);
33+
break;
34+
}
35+
// </Snippet1>
36+
}
37+
}
38+
39+
class MyPoco { }

docs/standard/serialization/system-text-json/use-dom.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ The following example illustrates the result of using methods that take a `JsonS
8585

8686
If you need features of `JsonSerializerOptions` other than custom converters, use `JsonSerializer` with strongly typed targets (such as the `Person` class in this example) rather than `JsonNode`.
8787

88+
### Manipulate property order
89+
90+
<xref:System.Text.Json.Nodes.JsonObject> is one of the elements in the payload of a <xref:System.Text.Json.Nodes.JsonNode>, and it represents a mutable JSON object. Even though the type is modelled as an `IDictionary<string, JsonNode>`, where each entry is a property of the object, it encapsulate an implicit property order. However, APIs such as <xref:System.Text.Json.Nodes.JsonObject.Insert(System.Int32,System.String,System.Text.Json.Nodes.JsonNode)> and <xref:System.Text.Json.Nodes.JsonObject.RemoveAt(System.Int32)> effectively model the type as an ordered dictionary by letting you insert and remove items at a specific index. These APIs allow modifications to object instances that can directly influence property order.
91+
92+
The following code shows an example of adding or moving a specific property to the start of the object.
93+
94+
:::code language="csharp" source="snippets/use-dom-utf8jsonreader-utf8jsonwriter/csharp/JsonNodePropertyOrder.cs" id="1":::
95+
8896
### Compare JsonNodes
8997

9098
To compare two `JsonNode` objects for equality, including their descendant elements, use the <xref:System.Text.Json.Nodes.JsonNode.DeepEquals(System.Text.Json.Nodes.JsonNode,System.Text.Json.Nodes.JsonNode)?displayProperty=nameWithType> method.

0 commit comments

Comments
 (0)