diff --git a/Remora.Rest/Json/StringEnumConverter.cs b/Remora.Rest/Json/StringEnumConverter.cs
index 5cd94ed..eb2ae91 100644
--- a/Remora.Rest/Json/StringEnumConverter.cs
+++ b/Remora.Rest/Json/StringEnumConverter.cs
@@ -59,7 +59,7 @@ public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSe
switch (reader.TokenType)
{
- case JsonTokenType.String:
+ case JsonTokenType.String or JsonTokenType.PropertyName:
{
var value = reader.GetString();
if (value is null)
@@ -117,4 +117,23 @@ public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOpt
writer.WriteStringValue(_enumsToNames[value]);
}
+
+ ///
+ public override TEnum ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ => this.Read(ref reader, typeToConvert, options);
+
+ ///
+ public override void WriteAsPropertyName(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options)
+ {
+ if (_asInteger)
+ {
+ writer.WritePropertyName(Enum.GetUnderlyingType(typeof(TEnum)).IsUnsigned()
+ ? Convert.ToUInt64(value).ToString()
+ : Convert.ToInt64(value).ToString());
+
+ return;
+ }
+
+ writer.WritePropertyName(_enumsToNames[value]);
+ }
}
diff --git a/Tests/Remora.Rest.Tests/Tests/Json/StringEnumConverterTests.cs b/Tests/Remora.Rest.Tests/Tests/Json/StringEnumConverterTests.cs
new file mode 100644
index 0000000..a2aabe4
--- /dev/null
+++ b/Tests/Remora.Rest.Tests/Tests/Json/StringEnumConverterTests.cs
@@ -0,0 +1,154 @@
+//
+// SPDX-FileName: StringEnumConverterTests.cs
+// SPDX-FileCopyrightText: Copyright (c) Jarl Gullberg
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+using System.Collections.Generic;
+using System.Text.Json;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Remora.Rest.Json;
+using Remora.Rest.Json.Policies;
+using Remora.Rest.Tests.Data.DataObjects;
+using Xunit;
+
+namespace Remora.Rest.Tests.Json;
+
+///
+/// Tests for .
+///
+public class StringEnumConverterTests
+{
+ ///
+ /// Tests that the converter can serialize a dictionary where the key is an enum.
+ ///
+ [Fact]
+ public void CanSerializeDictionaryKeyAsInteger()
+ {
+ // Arrange
+ var services = new ServiceCollection()
+ .Configure
+ (
+ json =>
+ {
+ json.PropertyNamingPolicy = new SnakeCaseNamingPolicy();
+ json.Converters.Add(new StringEnumConverter(asInteger: true));
+ })
+ .BuildServiceProvider();
+
+ var dictionary = new Dictionary
+ {
+ { StringifiedEnum.First, "first" },
+ { StringifiedEnum.Second, "second" },
+ { StringifiedEnum.Third, "third" },
+ };
+
+ var jsonOptions = services.GetRequiredService>().Value;
+
+ // Act
+ var result = JsonSerializer.Serialize(dictionary, jsonOptions);
+ var expected = "{\"0\":\"first\",\"1\":\"second\",\"2\":\"third\"}";
+
+ // Assert
+ Assert.Equal(expected, result);
+ }
+
+ ///
+ /// Tests that the converter can serialize a dictionary where the key is an enum.
+ ///
+ [Fact]
+ public void CanSerializeDictionaryKeyAsString()
+ {
+ // Arrange
+ var services = new ServiceCollection()
+ .Configure
+ (
+ json =>
+ {
+ json.PropertyNamingPolicy = new SnakeCaseNamingPolicy();
+ json.Converters.Add(new StringEnumConverter(json.PropertyNamingPolicy));
+ })
+ .BuildServiceProvider();
+
+ var dictionary = new Dictionary
+ {
+ { StringifiedEnum.First, "first" },
+ { StringifiedEnum.Second, "second" },
+ { StringifiedEnum.Third, "third" },
+ };
+
+ var jsonOptions = services.GetRequiredService>().Value;
+
+ // Act
+ var result = JsonSerializer.Serialize(dictionary, jsonOptions);
+ var expected = "{\"first\":\"first\",\"second\":\"second\",\"third\":\"third\"}";
+
+ // Assert
+ Assert.Equal(expected, result);
+ }
+
+ ///
+ /// Tests that the converter can read a dictionary where the key is an enum.
+ ///
+ [Fact]
+ public void CanDeserializeDictionaryKeyAsInteger()
+ {
+ // Arrange
+ var services = new ServiceCollection()
+ .Configure
+ (
+ json =>
+ {
+ json.PropertyNamingPolicy = new SnakeCaseNamingPolicy();
+ json.Converters.Add(new StringEnumConverter(asInteger: true));
+ })
+ .BuildServiceProvider();
+
+ var jsonOptions = services.GetRequiredService>().Value;
+
+ var json = "{\"0\":\"first\",\"1\":\"second\",\"2\":\"third\"}";
+
+ // Act
+ var result = JsonSerializer.Deserialize>(json, jsonOptions);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal(3, result.Count);
+ Assert.Equal("first", result[StringifiedEnum.First]);
+ Assert.Equal("second", result[StringifiedEnum.Second]);
+ Assert.Equal("third", result[StringifiedEnum.Third]);
+ }
+
+ ///
+ /// Tests that the converter can read a dictionary where the key is an enum.
+ ///
+ [Fact]
+ public void CanDeserializeDictionaryKeyAsString()
+ {
+ // Arrange
+ var services = new ServiceCollection()
+ .Configure
+ (
+ json =>
+ {
+ json.PropertyNamingPolicy = new SnakeCaseNamingPolicy();
+ json.Converters.Add(new StringEnumConverter(json.PropertyNamingPolicy));
+ })
+ .BuildServiceProvider();
+
+ var jsonOptions = services.GetRequiredService>().Value;
+
+ var json = "{\"first\":\"first\",\"second\":\"second\",\"third\":\"third\"}";
+
+ // Act
+ var result = JsonSerializer.Deserialize>(json, jsonOptions);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal(3, result.Count);
+ Assert.Equal("first", result[StringifiedEnum.First]);
+ Assert.Equal("second", result[StringifiedEnum.Second]);
+ Assert.Equal("third", result[StringifiedEnum.Third]);
+ }
+}