Search code examples
c#.net-coreminimal-apis

dotnet 6 minimal API circular serialization


I am new to dotnet, trying out dotnet 6 minimal API. I have two models:

namespace Linker.Models
{
    class Link : BaseEntity
    {
        [MaxLength(2048)]
        public string Url { get; set;} = default!;
        [MaxLength(65536)]
        public string? Description { get; set; }
        [Required]
        public User Owner { get; set; } = default!;
        [Required]
        public Space Space { get; set; } = default!;
    }
}

And:

namespace Linker.Models
{
    class Space : BaseEntity
    {
        public string Name { get; set; } = default!;
        public string Code { get; set; } = default!;
        public User Owner { get; set; } = default!;
        public List<Link> Links { get; set; } = new List<Link>();
    }
}

Now when I try to serialize Space model I get error System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 64. (make sense because Path: $.Links.Space.Links.Space.Links.Space.Links.Space.Links.Space.Links...). Is it posible to prevent dotnet from serializing object this deep? I don't need for dotnet to even try to serialize such a deep relations


Solution

  • You can set ReferenceHandler.Preserve in the JsonSerializerOptions. These docs How to preserve references and handle or ignore circular references in System.Text.Json discuss further.

    For manual serialization/deserialization pass the options to the JsonSerializer:

    JsonSerializerOptions options = new()
    {
        ReferenceHandler = ReferenceHandler.Preserve
    };
    string serialized = JsonSerializer.Serialize(model, options);
    

    Or to configure globally in minimal API:

    using Microsoft.AspNetCore.Http.Json;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Set the JSON serializer options
    builder.Services.Configure<JsonOptions>(options =>
    {
        options.SerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
    });
    

    You could instead ignore the circular references rather than handling them by using ReferenceHandler.IgnoreCycles. The serializer will set the circular references to null, so there's potential for data loss using this method.