如何装饰JSON.NET StringEnumConverter

我正在使用一个api,返回这样的字符串值。 some-enum-value

我尝试将这些值放在枚举中,因为默认的StringEnumConverter没有完成这项工作,我尝试用一​​些额外的逻辑来装饰这个转换器。 如何确保正确反序列化值?

以下代码是我尝试完成这项工作。 但是行reader = new JsonTextReader(new StringReader(cleaned)); 因为base.ReadJson无法将字符串识别为JSON,所以打破了整个事情。

有没有更好的方法来实现这一点,而无需在StringEnumConverter中实现所有的强制逻辑? 如何解决我的方法?

 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默认的StringEnumConverter完美地处理这些属性。

例:

 public enum MyEnum { [EnumMember("some-enum-value")] SomeEnumValue, Value, [EnumMember("some-other-value")] SomeOtherValue } 

请注意,您只需要在破折号或其他特殊字符的情况下指定属性,您不能在枚举中使用。 大写的小写由StringEnumConverter处理。 因此,如果服务返回类似someenumvalue的值,您应该在enum Someenumvalue使用它。 如果您更喜欢SomeEnumValue ,则应使用EnumMember属性。 如果服务返回它像someEnumValue你可以像这样使用它SomeEnumValue (当你使用CamelCaseText属性时它开箱即用)。

您可以在JsonSerializerSettings轻松指定转换器和其他设置。

以下是我自己使用的设置示例。

 new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver(), Converters = new List { new StringEnumConverter { CamelCaseText = true } }, NullValueHandling = NullValueHandling.Ignore }; 

您也可以使用此代码:

 [JsonConverter(typeof(StringEnumConverter))] public enum ResposeStatus { [EnumMember(Value = "success value")] Success, [EnumMember(Value = "fail value")] Fail, [EnumMember(Value = "error value")] Error }; 

序列化JsonConvert.Serialize() ,将使用EnumMember的文本。

你也可以使用这种方法:

 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(false).ToList(); return attributes.Any() ? attributes.FirstOrDefault()?.Description : member.ToString(); } 

要么

 public static string GetDescription(this object member) { var type = member.GetType(); var attributes = type.GetCustomAttributes(false).ToList(); return attributes.Any() ? attributes.FirstOrDefault()?.Description : member.GetType().Name; } 

和枚举应该有desctription属性。 像这样:

 public enum MyEnum { [Description("some-enum-value")] And, [Description("some-enum-value")] Or } 

而且你可以像这样使用你的enum

 MyEnum.GetDescription(); //return "some-enum-value"