user246392
user246392

Reputation: 3027

Default serialization option for reference handler while setting up JsonSerializerContext

I'd like to set the default serialization option for reference handler to ignore cycles. I noticed JsonSourceGenerationOptions does not have a property for reference handler unlike JsonSerializerOptions. How is it possible to do this with JsonSourceGenerationOptions while creating a context?

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}

Alternatively, is there another way to override the default options? I tried overriding GeneratedSerializerOptions but received CS0102: The type already contains a definition for 'GeneratedSerializerOptions' error.

protected override JsonSerializerOptions GeneratedSerializerOptions => new JsonSerializerOptions
{
    ReferenceHandler = ReferenceHandler.IgnoreCycles,
};

Upvotes: 1

Views: 241

Answers (3)

dbc
dbc

Reputation: 117105

In this comment to [API Proposal]: JsonSourceGenerationOptions should support ReferenceHandler #107597, Eirik Tsarpalis of MSFT gives a workaround, which is to pass JsonSerializerOptions with the required ReferenceHandler value into the JsonSerializerContext(JsonSerializerOptions) constructor that is automatically generated for your source generation context, then assign the result to a custom static instance like so:

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
    public static SourceGenerationContext IgnoreCycles { get; } = new(new JsonSerializerOptions 
    { 
        ReferenceHandler = ReferenceHandler.IgnoreCycles,
        WriteIndented = true,
    });
}

Once you have the required static instance, you can use it when serializing e.g. like so:

var forecast = new WeatherForecast { /* Initialize with possibly cyclic property values */ };
var json = JsonSerializer.Serialize(forecast, 
                                    SourceGenerationContext.IgnoreCycles.WeatherForecast);

Upvotes: 0

Guru Stron
Guru Stron

Reputation: 143098

As far as I can see you can't specify reference handler on the context but you can pass the context to the options used for deserialization:

var serializerOptions = new JsonSerializerOptions
{
    TypeInfoResolver = SourceGenerationContext.Default, 
    ReferenceHandler = ReferenceHandler.IgnoreCycles 
};
var jsonString = JsonSerializer.Serialize(fore, serializerOptions);

See also the Source-generation support in ASP.NET Core section of the docs.

JIC full sample app (with <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault> setting):

using System.Text.Json;
using System.Text.Json.Serialization;

Console.WriteLine("Hello, World!");
var forecast = new WeatherForecast();
var myc = new MyClass
{
    Forecast = forecast
};
forecast.MyClass = myc;
var serializerOptions = new JsonSerializerOptions
{
    TypeInfoResolver = SourceGenerationContext.Default, 
    ReferenceHandler = ReferenceHandler.IgnoreCycles 
};
var jsonString = JsonSerializer.Serialize(forecast, serializerOptions);

Console.WriteLine(jsonString);

[JsonSerializable(typeof(WeatherForecast))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}

public class WeatherForecast
{
    public int Type { get; set; }
    public MyClass MyClass { get; set; }
}

public class MyClass
{
    public WeatherForecast Forecast { get; set; }
}

Upvotes: 0

Naseerudeen
Naseerudeen

Reputation: 1

You’re right that JsonSourceGenerationOptions doesn’t directly support setting the ReferenceHandler. However, you can achieve this by customizing the JsonSerializerOptions in your context. Here’s a way to do it without running into the CS0102 error:

Create a custom JsonSerializerOptions property in your partial class. Use this property when serializing or deserializing.

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
    private static readonly JsonSerializerOptions _customOptions = new JsonSerializerOptions
    {
        ReferenceHandler = ReferenceHandler.IgnoreCycles,
        WriteIndented = true
    };

    public static JsonSerializerOptions CustomOptions => _customOptions;
}

Then, when you need to serialize or deserialize, use the CustomOptions.

Upvotes: -1

Related Questions