I have a .NET 6 program that needs to deserialize a JSON string value (returned by external API) into a .NET enum.
The issue is that there are over 100 possible enum values (and more could be added without my knowledge), but I’m only interested in a few of them. So I would like to define an enum type like this and deserialize all the values that I’m not interested in to MyEnum.Unknown
:
public enum MyEnum
{
Unknown = 0,
Value1,
Value2,
Value3,
// only values that I'm interested in will be defined
}
If I’m using Newtonsoft.Json, I can do this quite easily with a custom JSON converter:
public class DefaultFallbackStringEnumConverter : StringEnumConverter
{
private readonly object _defaultValue;
public DefaultFallbackStringEnumConverter() : this(0)
{
}
public DefaultFallbackStringEnumConverter(object defaultValue)
{
_defaultValue = defaultValue;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
try
{
return base.ReadJson(reader, objectType, existingValue, serializer);
}
catch (JsonException)
{
return _defaultValue;
}
}
}
But with System.Text.Json, I can’t figure out how this can be done easily, because the JsonStringEnumConverter
in STJ is actually a JsonConverterFactory
that doesn’t do the serialization itself (it throws exceptions in all overrides of JsonConverter
as you can see here). Instead the factory creates EnumConverter<T>
s that actually do the work, but EnumConverter<T>
is internal so I can’t even reference or inherit from it in user code.
Any idea how this can be done easily with STJ or is it not possible at all? Thanks a lot for the help!
2
Answers
You can create a custom
JsonConverter
Then add an attribute on the property you want the converter to kick in
You could use the decorator pattern and wrap the
JsonStringEnumConverter
factory in a decorator whoseCreateConverter()
method wraps the returnedEnumConverter<T>
in some inner decorator that catches the exception and returns a default value.The following does that:
Do note that, unlike Json.NET, System.Text.Json does not have an equivalent to Json.NET’s
ConverterParameters
(see issue #54187 for confirmation) so if you need a different default value for a specific enum, you will need to subclassDefaultFallbackStringEnumConverter
for that specific enum, e.g. like so:Then if your model looks like e.g.:
And your JSON looks like:
You will be able to deserialize and re-serialize as follows:
Demo fiddle here.