How to decorate JSON.NET StringEnumConverter
我正在使用一个API,它返回这样的字符串值。
我尝试将这些值放在一个枚举中,因为默认的StringEnumConverter不能完成工作,因此我尝试使用一些其他逻辑来装饰此Converter。 如何确保正确反序列化了这些值?
以下代码是我完成此工作的尝试。 但是,由于base.ReadJson无法将字符串识别为JSON,因此
是否有更好的方法可以执行此操作而不必在StringEnumConverter中实现所有现有逻辑? 如何解决我的方法?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class BkStringEnumConverter : StringEnumConverter { public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.String) { var enumString = reader.Value.ToString(); if (enumString.Contains("-")) { var cleaned = enumString.Split('-').Select(FirstToUpper).Aggregate((a, b) => a + b); reader = new JsonTextReader(new StringReader(cleaned)); } } return base.ReadJson(reader, objectType, existingValue, serializer); } private static string FirstToUpper(string input) { var firstLetter = input.ToCharArray().First().ToString().ToUpper(); return string.IsNullOrEmpty(input) ? input : firstLetter + string.Join("", input.ToCharArray().Skip(1)); } } |
我通过在枚举值上添加EnumMember属性解决了该问题。 Json.NET的默认
例:
1 2 3 4 5 6 7 8 | public enum MyEnum { [EnumMember(Value ="some-enum-value")] SomeEnumValue, Value, [EnumMember(Value ="some-other-value")] SomeOtherValue } |
请注意,您只需要指定属性即可,例如破折号或其他不能在枚举中使用的特殊字符。大写小写由
您可以在
这是我自己使用的设置的示例。
1 2 3 4 5 6 |
您还可以使用以下代码:
1 2 3 4 5 6 7 8 9 10 | [JsonConverter(typeof(StringEnumConverter))] public enum ResposeStatus { [EnumMember(Value ="success value")] Success, [EnumMember(Value ="fail value")] Fail, [EnumMember(Value ="error value")] Error }; |
序列化
在Json.NET 12.0.1中,通过向
New feature - Added support for NamingStrategy to StringEnumConverter
首先,由于Json.NET没有内置的破折号命名策略,因此可以通过将
1 2 3 4 5 6 7 | public class DashCaseNamingStrategy : SnakeCaseNamingStrategy { protected override string ResolvePropertyName(string name) { return base.ResolvePropertyName(name).Replace('_', '-'); } } |
现在,在构造转换器并将其添加到
1 2 3 4 5 6 7 |
使用此方法,
您也可以使用以下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public static string GetDescription(this Enum member) { if (member.GetType().IsEnum == false) throw new ArgumentOutOfRangeException(nameof(member),"member is not enum"); var fieldInfo = member.GetType().GetField(member.ToString()); if (fieldInfo == null) return null; var attributes = fieldInfo.GetCustomAttributes<DescriptionAttribute>(false).ToList(); return attributes.Any() ? attributes.FirstOrDefault()?.Description : member.ToString(); } |
要么
1 2 3 4 5 6 7 8 | public static string GetDescription(this object member) { var type = member.GetType(); var attributes = type.GetCustomAttributes<DescriptionAttribute>(false).ToList(); return attributes.Any() ? attributes.FirstOrDefault()?.Description : member.GetType().Name; } |
枚举应具有destription属性。像这样:
1 2 3 4 5 6 7 8 | public enum MyEnum { [Description("some-enum-value")] And, [Description("some-enum-value")] Or } |
然后您可以像这样使用
1 | MyEnum.GetDescription(); //return"some-enum-value" |