2014-09-03 12 views
5

Voglio serializzare un tipo enum, in modo che restituisca una matrice con l'enumerazione come un oggetto che contiene sia il "valore", "nome" e un'annotazione dati valore. Ho bisogno di aiuto con la serializzazione. Ecco quello che ho fatto finora: L'enum:serializzazione Json.NET personalizzata di un tipo enum con annotazione dati

public enum Status 
{ 
    [Display(Name="Active status")] 
    Active = 1, 
    [Display(Name = "Deactive status")] 
    Deactive = 2, 
    [Display(Name = "Pending status")] 
    Pending = 3 
} 

L'oggetto DTO che dovrebbe essere serializzato:

public class ProjectDto 
{ 
    public Type StatusEnum { get; set; } 

    public Status CurrentStatus { get; set; } 
} 

Assegnazione di valori:

var project = new ProjectDto 
{ 
    CurrentStatus = Status.Active, 
    StatusEnum = typeof (Status) 
}; 
var output = JsonConvert.SerializeObject(project); 

per ottenere i valori dall'enum che utilizzo:

Enum.GetNames(typeof(Status)) //To get the names in the enum 
Enum.GetValues(typeof(Status)) //To get the values in the enum 

Per ottenere il valore del nome dei dati di annotazione è un po 'più complicato, ma ho trovato aiuto in questo articolo: http://geeksharp.com/2011/11/02/power-up-your-enumerations/ Hanno creato un metodo di supporto che otterrà il valore scritto nella annotazioni dati utilizzando:

public static string GetAttributeValue<T>(this Enum e, 
    Func<T, object> selector) where T : Attribute 
{ 
    var output = e.ToString(); 
    var member = e.GetType().GetMember(output).First(); 
    var attributes = member.GetCustomAttributes(typeof(T), false); 

    if (attributes.Length > 0) 
    { 
     var firstAttr = (T)attributes[0]; 
     var str = selector(firstAttr).ToString(); 
     output = string.IsNullOrWhiteSpace(str) ? output : str; 
    } 

    return output; 
} 

E è possibile ottenere il valore utilizzando:

.GetAttributeValue<DisplayAttribute>(y => y.Name) 

uscita dovrebbe essere qualcosa di simile

{ 
    statusEnum: [ 
     { "value": "1", "name": "Active", "label": "Active status" }, 
     { "value": "2", "name": "Deactive", "label": "Deactive status" }, 
     { "value": "3", "name": "Pending", "label": "Pending status" } 
    ], 
    currentStatus: { "value": "1", "name": "Active", "label": "Active status" } 
} 

come accennato Ho bisogno di aiuto per creare il serial JSON.NET personalizzato e deserializzare per ottenere l'output desiderato. Qualsiasi aiuto sarebbe aperto.

+1

La proprietà 'CurrentStatus' è in realtà una matrice? Inoltre, come è 'StatusEnum', che è di tipo' System.Type', essendo serializzato su un oggetto simile? –

+1

Scusate buona cattura. Mi sono perso il fatto che avevo confuso statusEnum e currentStatus sull'output, ora risolto.statusEnum dovrebbe rappresentare il tipo di enum di stato con tutti i suoi valori mentre currentStatus dovrebbe rappresentare il singolo valore enum che è stato "selezionato" –

risposta

7

Ok, questo può probabilmente essere ripulito un po ', ma vorrei scrivere due convertitori personalizzati: uno per il tipo Enum, e un altro per il valore enum:

ho creato una classe personalizzata per serializzare nella fine risultato desiderato:

public class EnumValue 
{ 
    public int Value { get; set; } 

    public string Name { get; set; } 

    public string Label { get; set; } 
} 

oltre ad una classe statica che fa parte del lavoro di gambe per la creazione di istanze di quel tipo da Enum s e valori enum:

public static class EnumHelpers 
{ 
    public static EnumValue GetEnumValue(object value, Type enumType) 
    { 
     MemberInfo member = enumType.GetMember(value.ToString())[0]; 

     DisplayAttribute attribute = 
      member.GetCustomAttribute<DisplayAttribute>(); 

     return new EnumValue 
     { 
      Value = (int)value, 
      Name = Enum.GetName(enumType, value), 
      Label = attribute.Name 
     }; 
    } 

    public static EnumValue[] GetEnumValues(Type enumType) 
    { 
     Array values = Enum.GetValues(enumType); 

     EnumValue[] result = new EnumValue[values.Length]; 

     for (int i = 0; i < values.Length; i++) 
     { 
      result[i] = GetEnumValue(
       values.GetValue(i), 
       enumType); 
     } 

     return result; 
    } 
} 

Quindi ci sono due classi di convertitori. Questo primo serializza System.Type nell'oggetto che si voleva:

public class EnumTypeConverter : JsonConverter 
{ 
    public override void WriteJson(
     JsonWriter writer, 
     object value, 
     JsonSerializer serializer) 
    { 
     if (value == null) 
     { 
      writer.WriteNull(); 
      return; 
     } 

     EnumValue[] values = EnumHelpers.GetEnumValues((Type)value); 

     serializer.Serialize(writer, values); 
    } 

    public override object ReadJson(
     JsonReader reader, 
     Type objectType, 
     object existingValue, 
     JsonSerializer serializer) 
    { 
     throw new NotSupportedException(); 
    } 

    public override bool CanRead { get { return false; } } 

    public override bool CanConvert(Type objectType) 
    { 

     return typeof(Type).IsAssignableFrom(objectType); 
    } 
} 

E poi c'è quella che serializza il valore enum attuale:

public class EnumValueConverter : JsonConverter 
{ 
    public override void WriteJson(
     JsonWriter writer, 
     object value, 
     JsonSerializer serializer) 
    { 
     if (value == null) 
     { 
      writer.WriteNull(); 
      return; 
     } 

     EnumValue result = EnumHelpers.GetEnumValue(value, value.GetType()); 

     serializer.Serialize(writer, result); 
    } 

    public override object ReadJson(
     JsonReader reader, 
     Type objectType, 
     object existingValue, 
     JsonSerializer serializer) 
    { 
     throw new NotSupportedException(); 
    } 

    public override bool CanRead { get { return false; } } 

    public override bool CanConvert(Type objectType) 
    { 

     return objectType.IsEnum; 
    } 
} 

Ecco come si usa i contenuti:

var pr = new ProjectDto(); 
pr.CurrentStatus = Status.Active; 
pr.StatusEnum = typeof(Status); 

var settings = new JsonSerializerSettings(); 
settings.Converters = new JsonConverter[] 
{ 
    new EnumTypeConverter(), 
    new EnumValueConverter() 
}; 
settings.Formatting = Newtonsoft.Json.Formatting.Indented; 

string serialized = JsonConvert.SerializeObject(pr, settings); 

Esempio:https://dotnetfiddle.net/BVp7a2

+0

Grazie amico, questo era quello che stavo cercando! Qualche suggerimento sul motivo per cui le linee di separazione vengono \ r \ n? –

+2

@ArneHB: intendi nel JSON generato o nei valori di proprietà? Puoi rimuovere le interruzioni di riga rimuovendo l'opzione di formattazione 'Indented'. –

+0

@AndrewWhitetaker Mi dispiace amico mio, ero un po 'troppo innescato dal commento prima di rendermi conto che ho provato a serializzarlo due volte. Grazie per l'aiuto, la sua soluzione pulita e piacevole! Ho spostato i convertitori in modo che ora lavori in modo globale su tutte le serializzazioni JSON –

Problemi correlati