Deserializing a JSON Enumerated String to a Different C# Enumerated Type

Scott Brady
Scott Brady
C#

Problem

Recently I had to use a Webhook that returned an enumerated string that was very different from the enum it was supposed to convert to (in this case the JSON used snake case, C# used camel case).

Oddly enough, I knew the solution for this when receiving XML but I was a bit stumped when it came to dealing with JSON.

I could have received the JSON string and then manually mapped out the entire enum within my business logic, but I wanted to handle this during deserialization with decent performance whilst still mapping the enum and its associated string in one easily maintainable location.

Solution

The solution was to use some of the methods and attributes in Newtonsoft.JSON, you know, that package that everything else is dependent on but you never seem to use. This makes use of the JSONConverter class.

Whilst writing the enum back out to JSON wasn't a concern for me, I have also included it in the example below for posterity's sake.

Example

Required nuget package

install-package Newtonsoft.Json

Incoming JSON

{
	"writing_style":"snake_case"
}

C# Enum

public enum WritingStyle {
	SnakeCase,
	CamelCase,
	Unknown
}

C# Entity

Note the two attributes: JsonProperty pointing the incoming JSON attribute to our enum and JsonConverter pointing to our type converter.

public sealed class Dto {
	[JsonProperty("writing_style", Required = Required.Always)]
    [JsonConverter(typeof(WritingStyleTypeConverter))]
	public WritingStyle DtoWritingStyle { get; set; }
}

JSON Converter

public sealed class WritingStyleTypeConverter : JsonConverter {
    public override bool CanConvert(Type objectType) {
        return objectType == typeof(string);
    }

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var value = (string)reader.Value;
switch (value) { case "snake_case": return WritingStyle.SnakeCase; case "camel_case": return WritingStyle.CamelCase; default: return WritingStyle.Unknown; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var value = (WritingStyle)value;
switch(value) { case WritingStyle.SnakeCase: writer.WriteValue("snake_case"); break; case WritingStyle.CamelCase: writer.WriteValue("camel_case"); break; default: return ("unknown"); } } }

It's all pretty straight forward, but for more information on the JSONConverter class, see the official documentation.