Skip to content
Prev Previous commit
Next Next commit
Add PR suggestions.
  • Loading branch information
jozkee committed Dec 3, 2019
commit 095d5a9e1dd5101cdf12a30e5c46afb85ce6751e
62 changes: 53 additions & 9 deletions src/libraries/System.Text.Json/docs/ReferenceHandling_spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ The current solution to deal with cycles in the object graph while serializing i
# Proposal

```cs
namespace System.Text.Json
{
public partial class JsonSerializerOptions
{
public ReferenceHandling ReferenceHandling { get; set; } = ReferenceHandling.Default;
}
}

namespace System.Text.Json.Serialization
{
/// <summary>
Expand All @@ -63,14 +71,6 @@ namespace System.Text.Json.Serialization
public static ReferenceHandling Ignore { get; }
}
}

namespace System.Text.Json
{
public partial class JsonSerializerOptions
{
public ReferenceHandling ReferenceHandling { get; set; } = ReferenceHandling.Default;
}
}
```
See also the [internal implementation details](https://gist.github.com/Jozkee/b0922ef609f7a942f00ac2c93a976ff1).

Expand Down Expand Up @@ -111,7 +111,45 @@ Notes:

# Examples

Let's assume you have the following class:
## Using Default on Deserialize
```cs
class Employee
{
[JsonPropertyName("$id")]
public string Identifier { get; set; }
public Employee Manager { get; set; }

[JsonExtensionData]
public IDictionary<string, object> ExtensionData { get; set; }
}

private const string json =
@"{
""$id"": ""1"",
""Name"": ""Angela"",
""Manager"": {
""$id"": ""2"",
""Name"": ""Bob"",
""Manager"": {
""$ref"": ""2""
}
}
}";
```

```cs
public static void ReadObject()
{
Employee angela = JsonSerializer.Deserialize<Employee>(json);
Console.WriteLine(angela.Identifier) //prints: "1".
Console.WriteLine(angela.Manager.Identifier) //prints: "2".
Console.WriteLine(angela.Manager.Manager.ExtensionData["$ref"]) //prints: "2".
}
```

Note how you can annotate .Net properties to use properties that are meant for metadata and are added to the `JsonExtensionData` overflow dictionary, in case there is any, when opting-out of the `ReferenceHanding.Preserve` feature.

For the next samples let's assume you have the following class:
```cs
class Employee
{
Expand All @@ -126,6 +164,9 @@ class Employee
private Employee bob = new Employee { Name = "Bob" };
private Employee angela = new Employee { Name = "Angela" };

angela.Manager = bob;
bob.Subordinates = new List<Employee>{ angela };

public static void WriteObject()
{
string json = JsonSerializer.Serialize(angela, options);
Expand Down Expand Up @@ -604,6 +645,9 @@ Since these types are created with the help of an internal converter, and they a

With that said, the deserializer will throw when it reads `$id` on any of these types; but regardless of that, when writing those types, they are going to be preserved as any other collection type (`{ "$id": "1", "$values": [...] }`) since those types can still being parsed into a collection type that it is supported.

Note: By the same principle, `Newtonsoft.Json` does not support parsing JSON arrays into immutables as well.
Note 2: When using immutable types and `ReferenceHandling.Preserve`, you will not be able to generate payloads that are capables of round-tripping.

* **Immutable types**: i.e: `ImmutableList` and `ImmutableDictionary`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* **Immutable types**: i.e: `ImmutableList` and `ImmutableDictionary`
* **Immutable types**: e.g. `ImmutableList` and `ImmutableDictionary`

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always though i.e. stands for "in example".

* **System.Array**

Expand Down