Using System.Text.Json source generation in my application isn't providing for size reductions in the app because all the JsonConverters are still being rooted in the app.
Similar to #52662, but now because I have the object Value property in my WeatherForecast class.
Repro
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using ConsoleApp13;
using ConsoleApp13.JsonSourceGeneration;
[assembly: JsonSerializable(typeof(WeatherForecast))]
namespace ConsoleApp13
{
class Program
{
static async Task Main(string[] args)
{
string f = @"{""TemperatureC"":0,""Summary"":""hi""}";
var forecast = JsonSerializer.Deserialize(f, new JsonContext().WeatherForecast);
Console.WriteLine(forecast);
}
}
public record WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public object Value { get; set; }
}
}
dotnet publish -r win-x64 -c Release -p:PublishTrimmed=true -p:DebuggerSupport=false -p:TrimmerSingleWarn=false
View the outputted assemblies, and notice that System.Text.Json.dll is ~275KB and still has all its JsonConverters in it.
Analysis
From looking at the results, the reason everything is still rooted is because of the following call graph:
- The source gen'd JsonContext class for
WeatherForecast has a public JsonTypeInfo<object> Object property that references JsonMetadataServices.ObjectConverter.
JsonMetadataServices.ObjectConverter is a System.Text.Json.Serialization.Converters.ObjectConverter instance.
ObjectConverter takes a direct dependency on JsonNodeConverter.Instance
JsonNodeConverter creates new JsonValue<T>
JsonValue<T>.ToString calls JsonSerializer.Serialize without source gen information
That this point, since JsonSerializer.Serialize is called without source gen information, it now roots all JsonConverters, and the size of the app grows by a lot.
(Note that this pattern exists in ASP.NET Blazor WASM)
cc @layomia @steveharter @marek-safar @vitek-karas @CoffeeFlux
Using System.Text.Json source generation in my application isn't providing for size reductions in the app because all the JsonConverters are still being rooted in the app.
Similar to #52662, but now because I have the
object Valueproperty in myWeatherForecastclass.Repro
dotnet publish -r win-x64 -c Release -p:PublishTrimmed=true -p:DebuggerSupport=false -p:TrimmerSingleWarn=falseView the outputted assemblies, and notice that
System.Text.Json.dllis ~275KB and still has all its JsonConverters in it.Analysis
From looking at the results, the reason everything is still rooted is because of the following call graph:
WeatherForecasthas apublic JsonTypeInfo<object> Objectproperty that referencesJsonMetadataServices.ObjectConverter.JsonMetadataServices.ObjectConverteris aSystem.Text.Json.Serialization.Converters.ObjectConverterinstance.ObjectConvertertakes a direct dependency onJsonNodeConverter.InstanceJsonNodeConvertercreates newJsonValue<T>JsonValue<T>.ToStringcallsJsonSerializer.Serializewithout source gen informationThat this point, since
JsonSerializer.Serializeis called without source gen information, it now roots all JsonConverters, and the size of the app grows by a lot.(Note that this pattern exists in ASP.NET Blazor WASM)
cc @layomia @steveharter @marek-safar @vitek-karas @CoffeeFlux