c# - Cómo decorar JSON.NET StringEnumConverter
enums (3)
Resolví el problema agregando atributos EnumMember en mis valores de enumeración. El StringEnumConverter predeterminado de StringEnumConverter
trata perfectamente estos atributos.
Ejemplo:
public enum MyEnum
{
[EnumMember("some-enum-value")]
SomeEnumValue,
Value,
[EnumMember("some-other-value")]
SomeOtherValue
}
Tenga en cuenta que solo tiene que especificar los atributos en caso de guiones u otros caracteres especiales que no pueda usar en su enumeración. La minúscula en minúsculas es tratada por el StringEnumConverter
. Entonces, si el servicio devuelve un valor como someenumvalue
, debería usarlo así en la enumeración Someenumvalue
. Si prefieres SomeEnumValue
debes usar el atributo EnumMember
. En caso de que el servicio lo devuelva de esta someEnumValue
, puede usarlo de esta manera SomeEnumValue
( SomeEnumValue
. SomeEnumValue
).
Puede especificar fácilmente sus convertidores y otras configuraciones en JsonSerializerSettings
.
Aquí hay un ejemplo de la configuración que uso yo mismo.
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Converters = new List<JsonConverter> { new StringEnumConverter { CamelCaseText = true } },
NullValueHandling = NullValueHandling.Ignore
};
Estoy consumiendo una api que devuelve valores de cadena como este. some-enum-value
Intento colocar estos valores en una enumeración, ya que el StringEnumConverter predeterminado no hace el trabajo. Intento decorar este Convertidor con alguna lógica adicional. ¿Cómo puedo asegurarme de que los valores están correctamente deserializados?
El siguiente código es mi prueba para hacer este trabajo. Sin embargo, el reader = new JsonTextReader(new StringReader(cleaned));
línea reader = new JsonTextReader(new StringReader(cleaned));
está rompiendo todo desde la base. ReadJson no puede reconocer la cadena como JSON.
¿Hay una mejor manera de hacer esto sin tener que implementar toda la lógica existente en StringEnumConverter? ¿Cómo arreglar mi enfoque?
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));
}
}
También puedes usar este código:
[JsonConverter(typeof(StringEnumConverter))]
public enum ResposeStatus
{
[EnumMember(Value = "success value")]
Success,
[EnumMember(Value = "fail value")]
Fail,
[EnumMember(Value = "error value")]
Error
};
Al serializar JsonConvert.Serialize()
, usará el texto dentro de EnumMember
.
También puedes usar estos métodos:
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();
}
o
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;
}
y la enumeración debe tener el atributo desctription . Me gusta esto:
public enum MyEnum
{
[Description("some-enum-value")]
And,
[Description("some-enum-value")]
Or
}
Y entonces puedes usar tu enum
esta manera:
MyEnum.GetDescription(); //return "some-enum-value"