You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/standard/serialization/system-text-json/converters-how-to.md
+36Lines changed: 36 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -355,6 +355,42 @@ When the sample code calls the serializer, it uses a <xref:System.Text.Json.Json
355
355
356
356
The preceding example only does serialization, but a similar approach can be adopted for deserialization.
357
357
358
+
### ReferenceResolver limitations with custom converters
359
+
360
+
When using <xref:System.Text.Json.Serialization.ReferenceHandler.Preserve%2A>, there's an important limitation to be aware of when working with custom converters: **reference handling state is not preserved when the serializer calls into custom converters**. This means that if you have a custom converter for a type that's part of an object graph being serialized or deserialized with reference preservation enabled, the converter won't have access to the current <xref:System.Text.Json.Serialization.ReferenceResolver> instance.
361
+
362
+
Consider this scenario:
363
+
364
+
```csharp
365
+
publicclassParent
366
+
{
367
+
publicChildChild1 { get; set; }
368
+
publicChildChild2 { get; set; }
369
+
}
370
+
371
+
[JsonConverter(typeof(ChildConverter))]
372
+
publicclassChild
373
+
{
374
+
publicstringName { get; set; }
375
+
}
376
+
```
377
+
378
+
If `Child1` and `Child2` reference the same object instance, and you serialize `Parent` with `ReferenceHandler.Preserve`, the custom `ChildConverter` won't be able to participate in the reference handling. The converter will be called for each `Child` instance separately, without knowledge of whether the object has already been serialized elsewhere in the graph.
379
+
380
+
#### Current workarounds and limitations
381
+
382
+
Currently, there's no direct way to access the active `ReferenceResolver` from within a custom converter. Calling `ReferenceHandler.CreateResolver()` throws an exception because the resolver has already been created earlier in the serialization process.
383
+
384
+
If you need both custom conversion logic and reference preservation, consider these approaches:
385
+
386
+
1.**Implement reference handling in the converter itself**: Manually track object references within your converter using a static or thread-local dictionary, but be aware this has limitations and complexity.
387
+
388
+
2.**Use a different serialization approach**: Consider whether you can restructure your data or use alternative serialization strategies that don't require both custom converters and reference preservation simultaneously.
389
+
390
+
3.**Avoid custom converters for reference types in the object graph**: If possible, use custom converters only for leaf nodes or value types that don't participate in reference cycles.
391
+
392
+
This limitation is tracked in the .NET runtime repository as [issue #51715](https://github.com/dotnet/runtime/issues/51715), with plans for improvement tracked in [issue #42163](https://github.com/dotnet/runtime/issues/42163).
393
+
358
394
## Other custom converter samples
359
395
360
396
The [Migrate from Newtonsoft.Json to System.Text.Json](migrate-from-newtonsoft.md) article contains additional samples of custom converters.
0 commit comments