Skip to content

Instantly share code, notes, and snippets.

@thoemmi
Created September 5, 2018 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thoemmi/4cf462690537c2e3042247f265c17e97 to your computer and use it in GitHub Desktop.
Save thoemmi/4cf462690537c2e3042247f265c17e97 to your computer and use it in GitHub Desktop.
JSON Converter for enum flags
public class EnumFlagsConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var x = ((Enum) value).ToString();
var list = new List<string>();
foreach (var v in x.Split(new[] {", "}, StringSplitOptions.RemoveEmptyEntries))
{
list.Add(v);
}
if (list.Count == 1)
{
writer.WriteValue(list[0]);
}
else
{
serializer.Serialize(writer, list);
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
object result = null;
if (reader.TokenType == JsonToken.String)
{
result = Enum.Parse(objectType, (string) reader.Value, ignoreCase: true);
}
else if (reader.TokenType == JsonToken.StartArray)
{
var values = serializer.Deserialize<string[]>(reader);
result = values
.Select(t => (int) Enum.Parse(objectType, t, ignoreCase: true))
.Aggregate((t, a) => a | t);
}
return result;
}
public override bool CanConvert(Type objectType)
{
return objectType.IsEnum && objectType.GetCustomAttribute<FlagsAttribute>() != null;
}
}
public class EnumFlagsConverterTests
{
public EnumFlagsConverterTests()
{
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = new List<JsonConverter> {new EnumFlagsConverter()}
};
}
[Flags]
public enum TestEnum
{
Zero = 0,
One = 1,
Two = 2,
Four = 4,
All = 7
}
public class TestClass
{
public TestEnum Test { get; set; }
}
[Fact]
public void can_serialize_enum_zero()
{
var value = TestEnum.Zero;
var result = JsonConvert.SerializeObject(value);
Assert.Equal("\"Zero\"", result);
}
[Fact]
public void can_serialize_enum_one()
{
var value = TestEnum.One;
var result = JsonConvert.SerializeObject(value);
Assert.Equal("\"One\"", result);
}
[Fact]
public void can_serialize_enum_one_or_two()
{
var value = TestEnum.One | TestEnum.Two;
var result = JsonConvert.SerializeObject(value);
Assert.Equal("[\"One\",\"Two\"]", result);
}
[Fact]
public void can_serialize_enum_one_or_two_or_four()
{
var value = TestEnum.One | TestEnum.Two | TestEnum.Four;
var result = JsonConvert.SerializeObject(value);
Assert.Equal("\"All\"", result);
}
[Fact]
public void can_serialize_enum_all()
{
var value = TestEnum.All;
var result = JsonConvert.SerializeObject(value);
Assert.Equal("\"All\"", result);
}
[Fact]
public void can_serialize_enum_one_and_all()
{
var value = TestEnum.One | TestEnum.All;
var result = JsonConvert.SerializeObject(value);
Assert.Equal("\"All\"", result);
}
[Fact]
public void can_serialize_member()
{
var testClass = new TestClass
{
Test = TestEnum.One | TestEnum.Four
};
var result = JsonConvert.SerializeObject(testClass);
Assert.Equal("{\"Test\":[\"One\",\"Four\"]}", result);
}
[Fact]
public void can_deserialize_enum_zero()
{
var result = JsonConvert.DeserializeObject<TestEnum>("\"Zero\"");
Assert.Equal(TestEnum.Zero, result);
}
[Fact]
public void can_deserialize_enum_one()
{
var result = JsonConvert.DeserializeObject<TestEnum>("\"One\"");
Assert.Equal(TestEnum.One, result);
}
[Fact]
public void can_deserialize_enum_one_lowercase()
{
var result = JsonConvert.DeserializeObject<TestEnum>("\"one\"");
Assert.Equal(TestEnum.One, result);
}
[Fact]
public void can_deserialize_enum_one_or_two()
{
var result = JsonConvert.DeserializeObject<TestEnum>("[\"One\",\"Two\"]");
Assert.Equal(TestEnum.One | TestEnum.Two, result);
}
[Fact]
public void can_deserialize_enum_one_or_two_or_four()
{
var result = JsonConvert.DeserializeObject<TestEnum>("[\"One\",\"Two\",\"Four\"]");
Assert.Equal(TestEnum.All, result);
}
[Fact]
public void can_deserialize_enum_all()
{
var result = JsonConvert.DeserializeObject<TestEnum>("\"All\"");
Assert.Equal(TestEnum.All, result);
}
[Fact]
public void can_deserialize_enum_one_and_all()
{
var result = JsonConvert.DeserializeObject<TestEnum>("[\"One\",\"All\"]");
Assert.Equal(TestEnum.All, result);
}
[Fact]
public void can_deserialize_member()
{
var testClass = new TestClass
{
Test = TestEnum.Two | TestEnum.Four
};
var result = JsonConvert.DeserializeObject<TestClass>("{\"Test\":[\"Two\",\"Four\"]}");
result.Should().BeEquivalentTo(testClass);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment