-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add JsonConverter generator #65
base: main
Are you sure you want to change the base?
Conversation
This PR seems larger than it is, most of the files are generated by unit tests (see the Snapshots directory). |
Hey, sorry for being so slow getting to this! This looks like a nice idea, I'm just not sure if it's out-of-scope for this library 🤔 Have you considered releasing it as a separate package? |
Hey, better late than never 😉 Feel free to close this if you feel it doesn't fit in this repo. I might consider releasing it as a separate package then. |
I'm torn, honestly! 😀 Thing is, the built-in string enum converter already has more options for the conversion and caches everything aggressively in the constructor, so I'm not really sure that this generated converter would necessarily give much benefit over using that one... I would suggest trying to benchmark it first to see if it shows any improvement |
Now it's me that has to apologize for the late reply, I totally missed yours. My environment:
Benchmark results (MacBook Pro M1):
Code used for benchark: using System.ComponentModel.DataAnnotations;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using NetEscapades.EnumGenerators;
// Test
BenchmarkSwitcher
.FromAssembly(typeof(Program).Assembly)
.Run(args);
[EnumExtensions]
[EnumJsonConverter(typeof(TestEnumConverter), CaseSensitive = true, AllowMatchingMetadataAttribute = false)]
[JsonConverter(typeof(TestEnumConverter))]
public enum TestEnum
{
First = 0,
[Display(Name = "2nd")] Second = 1,
Third = 2
}
[EnumExtensions]
[JsonConverter(typeof(JsonStringEnumConverter<TestEnum2>))]
public enum TestEnum2
{
First = 0,
[Display(Name = "2nd")] Second = 1,
Third = 2
}
[MemoryDiagnoser]
public class DeserializeBenchmark
{
private const string EnumsString = """
["Second","Third","First","Second"]
""";
private static readonly Memory<char> EnumsMemory = EnumsString.ToArray().AsMemory();
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
{
Converters = { new JsonStringEnumConverter() }
};
[Benchmark(Baseline = true)]
[MethodImpl(MethodImplOptions.NoInlining)]
public TestEnum[]? JsonStringEnumConverter() =>
JsonSerializer.Deserialize<TestEnum[]>(EnumsString, JsonSerializerOptions);
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public TestEnum2[]? JsonStringEnumConverter2() =>
JsonSerializer.Deserialize<TestEnum2[]>(EnumsString, JsonSerializerOptions);
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public TestEnum[]? JsonStringEnumConverterSpan() =>
JsonSerializer.Deserialize<TestEnum[]>(EnumsMemory.Span, JsonSerializerOptions);
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public TestEnum2[]? JsonStringEnumConverterSpan2() =>
JsonSerializer.Deserialize<TestEnum2[]>(EnumsMemory.Span, JsonSerializerOptions);
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public TestEnum[]? EnumJsonConverter() => JsonSerializer.Deserialize<TestEnum[]>(EnumsString);
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public TestEnum2[]? EnumJsonConverter2() => JsonSerializer.Deserialize<TestEnum2[]>(EnumsString);
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public TestEnum[]? EnumJsonConverterSpan() => JsonSerializer.Deserialize<TestEnum[]>(EnumsMemory.Span);
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public TestEnum2[]? EnumJsonConverterSpan2() => JsonSerializer.Deserialize<TestEnum2[]>(EnumsMemory.Span);
}
[MemoryDiagnoser]
public class SerializeBenchmark
{
private static readonly TestEnum[] BenchmarkEnums =
{
TestEnum.Second,
TestEnum.Third,
TestEnum.First,
TestEnum.Second
};
private static readonly TestEnum2[] BenchmarkEnums2 =
{
TestEnum2.Second,
TestEnum2.Third,
TestEnum2.First,
TestEnum2.Second
};
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
{
Converters = { new JsonStringEnumConverter() }
};
[Benchmark(Baseline = true)]
[MethodImpl(MethodImplOptions.NoInlining)]
public string JsonStringEnumConverter() => JsonSerializer.Serialize(BenchmarkEnums, JsonSerializerOptions);
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public string JsonStringEnumConverter2() => JsonSerializer.Serialize(BenchmarkEnums2, JsonSerializerOptions);
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public string EnumJsonConverter() => JsonSerializer.Serialize(BenchmarkEnums);
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public string EnumJsonConverter2() => JsonSerializer.Serialize(BenchmarkEnums2);
} |
Adds generator for creating
JsonConverters
that uses theEnumExtensions
to serialize and deserialize enum values.#64