I have a flag type of enum and I would like it to be serialized not as string but as number. There is no problem about serializing but json.net unable to deserialize it.
public class ForceNumericFlagEnumConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
if (!(Nullable.GetUnderlyingType(objectType) ?? objectType).IsEnum)
return false;
return HasFlagsAttribute(objectType);
}
public override bool CanRead { get { return false; } }
public override bool CanWrite { get { return false; } }
static bool HasFlagsAttribute(Type objectType)
{
return Attribute.IsDefined(Nullable.GetUnderlyingType(objectType) ?? objectType, typeof(System.FlagsAttribute));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class Program
{
public static void Main()
{
try
{
Test(UserCan.ChangeConf | UserCan.ForceOther);
Test(UserCan.DoNothing);
Test(UserCan.ForceOther);
Test(UserCan.DoEverything);
}
catch (Exception ex)
{
Console.WriteLine("Uncaught exception:");
Console.WriteLine(ex);
throw;
}
}
static void Test(UserCan ability)
{
JsonConvert.DefaultSettings = () => GetGlobalJsonSettings();
var settings = GetNEWJsonSettings();
string jsonAbility = JsonConvert.SerializeObject(ability, settings);
Console.WriteLine("\nJSON serialization for {0} \"{1}\":", ability.GetType(), ability);
Console.WriteLine(jsonAbility);
ulong val;
Assert.IsTrue(ulong.TryParse(jsonAbility, out val));
var result1 = JsonConvert.DeserializeObject<UserCan?>(jsonAbility, settings);
var result2 = JsonConvert.DeserializeObject<UserCan>(jsonAbility, settings);
Assert.IsTrue(result1 == ability);
Assert.IsTrue(result2 == ability);
Assert.AreEqual("\"someValue\"", JsonConvert.SerializeObject(NonFlagEnum.SomeValue, settings));
}
public enum NonFlagEnum
{
SomeValue,
}
[Flags]
public enum UserCan : ulong
{
DoNothing = 0,
ChangeConf = 1 << 0,
MonitorOthers = 1 << 1,
ForceOther = 1 << 2,
EditRemoveOthers = 1 << 3,
DoEverything = unchecked((ulong)~0),
}
public static JsonSerializerSettings GetGlobalJsonSettings()
{
JsonSerializerSettings settings = new JsonSerializerSettings
{
Converters = { new StringEnumConverter{ CamelCaseText = true } },
};
return settings;
}
public static JsonSerializerSettings GetNEWJsonSettings()
{
JsonSerializerSettings settings = new JsonSerializerSettings
{
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
NullValueHandling = NullValueHandling.Ignore,
ObjectCreationHandling = ObjectCreationHandling.Replace,
TypeNameHandling = TypeNameHandling.Auto,
Converters = { new ForceNumericFlagEnumConverter() },
};
return settings;
}
}
You can see full code to create error here
https://dotnetfiddle.net/y0GnNf
[Newtonsoft.Json.JsonSerializationException: Error converting value 18446744073709551615 to type 'Program+UserCan'. Path '', line 1, position 20.]