Skip to content

Commit

Permalink
manipulate property order
Browse files Browse the repository at this point in the history
  • Loading branch information
gewarren committed Oct 17, 2024
1 parent 6d63bec commit 0abce52
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 4 deletions.
2 changes: 2 additions & 0 deletions docs/core/whats-new/dotnet-9/libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,8 @@ The <xref:System.Json.JsonObject> type now exposes ordered dictionary&ndash;like

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

For more information, see [Manipulate property order](../../../standard/serialization/system-text-json/use-dom.md#manipulate-property-order).

### Customize enum member names

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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public class PersonalInfo

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

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.
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.

```csharp
// Instantiation of JsonObject json omitted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ There are two ways to plug into customization. Both involve obtaining a resolver
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:

| `JsonTypeInfo.Kind` | Description |
| - | - |
|---------------------|-------------|
| <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.** |
| <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. |
| <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>`. |
Expand All @@ -63,7 +63,7 @@ A modifier is an `Action<JsonTypeInfo>` or a method with a <xref:System.Text.Jso
The following table shows the modifications you can make and how to achieve them.

| Modification | Applicable `JsonTypeInfo.Kind` | How to achieve it | Example |
| - | - | - | - |
|--------------|--------------------------------|-------------------|---------|
| 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) |
| 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) |
| 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) |
Expand Down Expand Up @@ -114,7 +114,7 @@ Besides customizing a contract, there are other ways to influence serialization
- By modifying <xref:System.Text.Json.JsonSerializerOptions>, for example, to set a naming policy or serialize enumeration values as strings instead of numbers.
- By writing a custom converter that does the actual work of writing the JSON and, during deserialization, constructing an object.

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.
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.

## See also

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Schema;

namespace JsonNodePropertyOrder;

public class Program
{
public static void Main()
{
// <Snippet1>
var schema = (JsonObject)JsonSerializerOptions.Default.GetJsonSchemaAsNode(typeof(MyPoco));

JsonNode? idValue;
switch (schema.IndexOf("$id"))
{
// $id property missing.
case < 0:
idValue = (JsonNode)"https://example.com/schema";
schema.Insert(0, "$id", idValue);
break;

// $id property already at the start of the object.
case 0:
break;

// $id exists but not at the start of the object.
case int index:
idValue = schema[index];
schema.RemoveAt(index);
schema.Insert(0, "$id", idValue);
break;
}
// </Snippet1>
}
}

class MyPoco { }
8 changes: 8 additions & 0 deletions docs/standard/serialization/system-text-json/use-dom.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ The following example illustrates the result of using methods that take a `JsonS

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`.

### Manipulate property order

<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.

The following code shows an example of adding or moving a specific property to the start of the object.

:::code language="csharp" source="snippets/use-dom-utf8jsonreader-utf8jsonwriter/csharp/JsonNodePropertyOrder.cs" id="1":::

### Compare JsonNodes

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.
Expand Down

0 comments on commit 0abce52

Please sign in to comment.