Comment décorer JSON.NET StringEnumConverter

je consomme une api qui renvoie des valeurs de chaîne comme celle-ci. some-enum-value

j'essaie de mettre ces valeurs dans un enum, puisque le StringEnumConverter par défaut ne fait pas le travail j'essaie de décorer ce convertisseur avec un peu de logique supplémentaire. Comment puis-je m'assurer que les valeurs sont correctement désérialisé?

code suivant est mon essai pour faire ce travail. Cependant, la ligne reader = new JsonTextReader(new StringReader(cleaned)); est en train de tout casser depuis la base.ReadJson ne reconnaît pas la chaîne comme JSON.

y a-t-il une meilleure façon de le faire sans avoir à implémenter toute la logique d'excision dans StringEnumConverter? Comment corriger mon approche?

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));
    }
}
22
demandé sur A-Sharabiani 2014-04-07 13:15:43

3 réponses

j'ai résolu le problème en ajoutant des attributs Enum member sur mes valeurs enum. Les Json.NET default StringEnumConverter traite parfaitement ces attributs.

Exemple:

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

Veuillez noter que vous n'avez qu'à spécifier les attributs en cas de tirets ou autres caractères spéciaux vous pouvez pas l'utiliser dans votre enum. La minuscule en majuscules est traitée par StringEnumConverter. Donc si le service renvoie une valeur comme someenumvalue vous devriez l'utiliser comme ça dans l'enum Someenumvalue. Si vous préférez SomeEnumValue vous devez utiliser le EnumMember l'attribut. Dans le cas où le service retourne comme ceci someEnumValue vous pouvez simplement l'utiliser comme ceci SomeEnumValue (il fonctionne hors de la boîte lorsque vous utilisez la propriété CamelCaseText).

Vous pouvez facilement spécifier vos convertisseurs et d'autres paramètres dans le JsonSerializerSettings.

Voici un exemple de paramètres que j'utilise moi-même.

new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
    Converters = new List<JsonConverter> { new StringEnumConverter { CamelCaseText = true } },
    NullValueHandling = NullValueHandling.Ignore
};
49
répondu Marco Franssen 2014-04-08 13:43:07

vous pouvez aussi utiliser ce code:

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

Lors de la sérialisation JsonConvert.Serialize(), utilisera le texte à l'intérieur du EnumMember.

18
répondu A-Sharabiani 2016-06-23 20:28:40

u peut Également utiliser ces méthodes:

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();
        }

ou

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;
        }

et enum devrait avoir describption l'attribut. Comme ceci:

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

    }

Et que vous pouvez utiliser votre enum comme ceci:

MyEnum.GetDescription(); //return "some-enum-value"
0
répondu Maksym Labutin 2018-02-02 13:56:21