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.