Reputation: 14555
I am getting an exception:
> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.InvalidOperationException: TypeInfoResolver 'JsonBenchmark.DataSourceGenerationContext' did not provide property metadata for type 'JsonBenchmark.Data'.
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_NoMetadataForTypeProperties(IJsonTypeInfoResolver resolver, Type type)
at System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.Deserialize(Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo`1 jsonTypeInfo, Nullable`1 actualByteCount)
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo`1 jsonTypeInfo)
at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonTypeInfo`1 jsonTypeInfo)
at JsonBenchmark.Benchmark.SystemTextJsonDeserializeSourceGenerator() in C:\Users\Ricardo.Peres\source\repos\JsonBenchmark\JsonBenchmark\Benchmark.cs:line 66
at BenchmarkDotNet.Toolchains.InProcess.NoEmit.BenchmarkActionFactory.BenchmarkActionVoid.WorkloadActionUnroll(Int64 repeatCount)
at BenchmarkDotNet.Engines.Engine.Measure(Action`1 action, Int64 invokeCount)
at BenchmarkDotNet.Engines.Engine.RunIteration(IterationData data)
at BenchmarkDotNet.Engines.EngineFactory.Jit(Engine engine, Int32 jitIndex, Int32 invokeCount, Int32 unrollFactor)
at BenchmarkDotNet.Engines.EngineFactory.CreateReadyToRun(EngineParameters engineParameters)
at BenchmarkDotNet.Toolchains.InProcess.NoEmit.InProcessNoEmitRunner.Runnable.RunCore(IHost host, BenchmarkCase benchmarkCase)
at InvokeStub_Runnable.RunCore(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
--- End of inner exception stack trace ---
at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at BenchmarkDotNet.Toolchains.InProcess.NoEmit.InProcessNoEmitRunner.Run(IHost host, BenchmarkCase benchmarkCase)
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at BenchmarkDotNet.Toolchains.Results.ExecuteResult.LogIssues(ILogger logger, BuildResult buildResult)
at BenchmarkDotNet.Running.BenchmarkRunnerClean.RunExecute(ILogger logger, BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, IToolchain toolchain, BuildResult buildResult, IResolver resolver, IDiagnoser diagnoser, Int32 launchIndex)
at BenchmarkDotNet.Running.BenchmarkRunnerClean.Execute(ILogger logger, BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, IToolchain toolchain, BuildResult buildResult, IResolver resolver)
at BenchmarkDotNet.Running.BenchmarkRunnerClean.RunCore(BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, ILogger logger, IResolver resolver, BuildResult buildResult)
at BenchmarkDotNet.Running.BenchmarkRunnerClean.Run(BenchmarkRunInfo benchmarkRunInfo, Dictionary`2 buildResults, IResolver resolver, ILogger logger, EventProcessor eventProcessor, List`1 artifactsToCleanup, String resultsFolderPath, String logFilePath, Int32 totalBenchmarkCount, StartedClock& runsChronometer, Int32& benchmarksToRunCount, TaskbarProgress taskbarProgress)
at BenchmarkDotNet.Running.BenchmarkRunnerClean.Run(BenchmarkRunInfo[] benchmarkRunInfos)
at BenchmarkDotNet.Running.BenchmarkSwitcher.RunWithDirtyAssemblyResolveHelper(String[] args, IConfig config, Boolean askUserForInput)
at BenchmarkDotNet.Running.BenchmarkSwitcher.Run(String[] args, IConfig config)
at JsonBenchmark.Program.Main(String[] args) in C:\Users\Ricardo.Peres\source\repos\JsonBenchmark\JsonBenchmark\Program.cs:line 7
The exception is: "System.InvalidOperationException: TypeInfoResolver 'JsonBenchmark.DataSourceGenerationContext' did not provide property metadata for type 'JsonBenchmark.Data'."
When I try to serialize/deserialize a simple class:
public class Data
{
public int Id { get; set; }
public required string Name { get; set; }
public DateTime Timestamp { get; set; }
}
Using a source generator (System.Text.Json
):
[JsonSerializable(typeof(Data), GenerationMode = JsonSourceGenerationMode.Serialization)]
internal partial class DataSourceGenerationContext : JsonSerializerContext { }
The code itself runs when not running as a benchmark:
var data = new Data { Id = 1, Name = ".NET Serialization Benchmark", Timestamp = DateTime.Now };
var json = "{\"Id\":1,\"Name\":\"Ricardo\",\"Timestamp\":\"2025-02-17T13:45:53.2140627+00:00\"}";
System.Text.Json.JsonSerializer.Serialize(data);
System.Text.Json.JsonSerializer.Deserialize<Data>(json);
System.Text.Json.JsonSerializer.Serialize(data, DataSourceGenerationContext.Default.Data);
System.Text.Json.JsonSerializer.Deserialize(json, DataSourceGenerationContext.Default.Data);
But fails when I run it as part of a benchmark using BenchmarkDotNet:
public static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
The failing code is either of: JsonSerializer.Serialize(data); JsonSerializer.Serialize(data, typeof(Data), DataSourceGenerationContext.Default);
According to all documentation I read, this should work, and, in fact, it does, just not as a benchmark. I am using .NET 9.
If I have, on my project (.csproj) file this:
<PropertyGroup>
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>
Buf it I take it out, the result is the same. The code that fails is:
JsonSerializer.Deserialize(json, DataSourceGenerationContext.Default.Data);
It says that the DataSourceGenerationContext
class does not provide metadata for type Data
, which seems weird, because it should be generated by the source generator.
If, however, I set the GenerationMode
property to JsonSourceGenerationMode.Metadata
, on the JsonSerializableAttribute
it works. But I wanted to use JsonSourceGenerationMode.Serialization
because of the performance increase.
Upvotes: 1
Views: 29
Reputation: 14555
I think I found out: as per this ticket, deserialization using JsonSourceGenerationMode.Serialization
is not yet implemented! The alternative is to stick with the default.
Upvotes: 1