2014-04-07 9 views
16

Ich bin eine API essen, die String-Werte wie folgt zurückgibt. some-enum-valueWie dekoriere ich JSON.NET StringEnumConverter

Ich versuche, diese Werte in eine Enumeration zu setzen, da der Standard-StringEnumConverter nicht den Job macht, den ich versuche, diesen Konverter mit etwas zusätzlicher Logik zu dekorieren. Wie kann ich sicherstellen, dass die Werte korrekt deserialisiert sind?

Der folgende Code ist mein Versuch, diese Arbeit zu erledigen. Die Zeile reader = new JsonTextReader(new StringReader(cleaned)); bricht jedoch die ganze Sache seit der Base.ReadJson kann die Zeichenfolge als JSON nicht erkennen.

Gibt es einen besseren Weg, dies zu tun, ohne die gesamte existierende Logik in StringEnumConverter implementieren zu müssen? Wie kann ich meinen Ansatz korrigieren?

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

Antwort

39

Ich löste das Problem, indem ich EnumMember-Attribute zu meinen Enum-Werten hinzufügte. Der Json.NET Standard StringEnumConverter behandelt perfekt diese Attribute.

Beispiel:

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

Bitte beachten Sie, dass Sie nur die Attribute bei Striche oder andere Sonderzeichen angeben müssen Sie nicht in Ihrem ENUM nutzen können. Der Großbuchstabe wird von der StringEnumConverter behandelt. Wenn der Dienst also einen Wert wie someenumvalue zurückgibt, sollten Sie ihn wie folgt in der Enumeration Someenumvalue verwenden. Wenn Sie SomeEnumValue bevorzugen, sollten Sie das Attribut EnumMember verwenden. Wenn der Service es so zurückgibt someEnumValue können Sie es einfach so verwenden SomeEnumValue (Es funktioniert aus der Box, wenn Sie die CamelCaseText-Eigenschaft verwenden).

Sie können Ihre Konverter und andere Einstellungen einfach in der JsonSerializerSettings angeben.

Hier ist ein Beispiel für die Einstellungen, die ich selbst verwende.

new JsonSerializerSettings 
{ 
    ContractResolver = new CamelCasePropertyNamesContractResolver(), 
    Converters = new List<JsonConverter> { new StringEnumConverter { CamelCaseText = true } }, 
    NullValueHandling = NullValueHandling.Ignore 
}; 
+0

Hallo, bitte können Sie zur Verfügung stellen Beispielprojekt, weil es nicht für mich arbeiten. Vielen Dank. –

+0

nur die JsonSerializerSettings zu Ihrem JsonConverter –

+1

Kleiner Kommentar. Wenn Sie nicht den StringEnumConverter, sondern den Standardwert von json.net verwenden, funktioniert der enumMember nicht. – dampee

11

Sie können auch diesen Code verwenden:

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

Wenn JsonConvert.Serialize() Serialisierung, wird der Text innerhalb des EnumMember verwenden.

+0

Ja, Sie können, aber wie in meinem letzten Kommentar zu der angenommenen Antwort angegeben, ist es einfacher, die serializeSettings zu verwenden. So müssen Sie diese Attribute nicht überall verderben. –

0

Auch u kann diese Methoden verwenden:

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

oder

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

und Enum Desctription haben sollte Attribut. Wie folgt aus:

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

    } 

Und als können Sie verwenden, um Ihre enum wie folgt aus:

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