JsonStringEnumConverter
is actually a subclass of JsonConverterFactory
. It manufactures a specific JsonConverterEnum
for each concrete enum
type encountered during serialization that, in turn, serializes that specific enum
type as a string.
If you don't want some specific enum
type to be serialized as a string, you can use the decorator pattern and create your own converter factory that decorates a JsonStringEnumConverter
but prevents that enum
type from being converted as follows:
public class OptOutJsonConverterFactory : JsonConverterFactoryDecorator
{
readonly HashSet<Type> optOutTypes;
public OptOutJsonConverterFactory(JsonConverterFactory innerFactory, params Type [] optOutTypes) : base(innerFactory) => this.optOutTypes = optOutTypes.ToHashSet();
public override bool CanConvert(Type typeToConvert) => base.CanConvert(typeToConvert) && !optOutTypes.Contains(typeToConvert);
}
public class JsonConverterFactoryDecorator : JsonConverterFactory
{
readonly JsonConverterFactory innerFactory;
public JsonConverterFactoryDecorator(JsonConverterFactory innerFactory)
{
if (innerFactory == null)
throw new ArgumentNullException(nameof(innerFactory));
this.innerFactory = innerFactory;
}
public override bool CanConvert(Type typeToConvert) => innerFactory.CanConvert(typeToConvert);
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) => innerFactory.CreateConverter(typeToConvert, options);
}
Then use it in options as follows:
options.Converters.Add(new OptOutJsonConverterFactory(new JsonStringEnumConverter(),
// Add here all enum types to serialize as integers:
typeof(SomeEnumNotToSerializeAsAString)
//, ...
));
Notes:
If maintaining a list of enum types to serialize as integers is inconvenient, you could mark the enum types to be serialized as integers with some custom attribute, then exclude types marked with that attribute from within CanConvert(CanConvert(Type typeToConvert)
.
The decorator pattern is required because JsonStringEnumConverter
is sealed.
Mockup fiddle #1 here.
Alternatively, if you don't want some specific enum
property to be serialized as a string, you can apply a converter to the property using JsonConverterAttribute
that ignores the incoming JsonSerializerOptions
and generates a default serialization instead:
/// <summary>
/// Apply this converter to a property to force the property to be serialized with default options.
/// This converter can ONLY be applied to a property; setting it in options or on a type may cause a stack overflow exception!
/// </summary>
/// <typeparam name="T">the property's declared return type</typeparam>
public class SerializePropertyAsDefaultConverter<T> : JsonConverter<T>
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return JsonSerializer.Deserialize<T>(ref reader); // Ignore the incoming options!
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, value); // Ignore the incoming options!
}
}
And apply it to your model as follows:
public class Model
{
public StringEnum StringEnum { get; set; }
[JsonConverter(typeof(SerializePropertyAsDefaultConverter<SomeEnumNotToSerializeAsAString>))]
public SomeEnumNotToSerializeAsAString SomeEnumNotToSerializeAsAString { get; set; }
}
Notes:
Mockup fiddle #2 here.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…