2013-08-31 16 views
16

ho un'enumerazione definita con C#, dove sto memorizzare i suoi valori come caratteri, come questo:Deserialize carattere JSON come enumerazione

public enum CardType 
{ 
    Artist = 'A', 
    Contemporary = 'C', 
    Historical = 'H', 
    Musician = 'M', 
    Sports = 'S', 
    Writer = 'W' 
} 

Sto tentando di deserializzare utilizzando JSON.NET, ma l'incoming JSON è stato scritto utilizzando il valore cHAR (stringa) invece del valore int dell'enumerazione, in questo modo:

[{"CardType","A"},{"CardType", "C"}] 

E 'possibile definire un qualche tipo di convertitore che mi permetterà di analizzare manualmente il carattere al enum valore?

Ho provato a creare un JsonConverter, ma non sono sicuro di come farlo, pur applicandolo solo a questa proprietà e non all'intero oggetto analizzato. ecco cosa ho provato:

public class EnumerationConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     serializer.Serialize(writer, value); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
     { 
      return null; 
     } 

     int value = serializer.Deserialize<int>(reader); 
     return (CardType)value; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType.IsSubclassOf(typeof(string)); 
    } 
} 

La logica potrebbe essere sbagliato e posso risolvere questo, ma il problema è ReadJson() non viene chiamato a tutti.

CanConvert è, ma sembra di essere chiamato per ogni proprietà, non solo quella di proprietà ho definito per:

public class Card 
{ 
      private CardType type; 
     [JsonConverter(typeof(EnumerationConverter))] 
     public CardType Type 
     { 
      get { return type; } 
      set { type = value; } 
     } 
} 

Sono sicuro che ho fatto questo in modo non corretto, ma sto avendo problemi a trovare la documentazione su come fare questo per un singolo campo ...

Cosa mi manca?

+0

Puoi pubblicare una classe campione che ha la proprietà 'CardType' dove il deserilization fallisce? – nemesv

+0

puoi pubblicare l'enum completo. Sono sicuro che non puoi dichiarare enum come hai definito sopra – dharam

+0

la classe in cui è deserializzata ha solo una proprietà CardType per ricevere il valore deserializzato, non c'è niente oltre alla dichiarazione. Per quanto riguarda il valore enum, questa è effettivamente la definizione completa dell'ENUM. la classe Card ha una proprietà di tipo CardType per la memorizzazione del valore di tipo enumerato. – SelAromDotNet

risposta

16

non si necessario necessità un'usanza JsonConverter è possibile utilizzare il built-in StringEnumConverter con la combinazione del EnumMemberAttribute (dall'assemblaggio System.Runtime.Serialization).

Senza lo EnumMemberAttribute utilizza i nomi enum in modo Artista, Contemporaneo, ecc. Quindi è necessario modificare i nomi con esso sul valore A, C, ecc.

Ma non è la soluzione più bella perché si deve ripetere i valori due volte, ma funziona:

[JsonConverter(typeof(StringEnumConverter))] 
public enum CardType 
{ 
    [EnumMember(Value = "A")] 
    Artist = 'A', 
    [EnumMember(Value = "C")] 
    Contemporary = 'C', 
    [EnumMember(Value = "H")] 
    Historical = 'H', 
    [EnumMember(Value = "M")] 
    Musician = 'M', 
    [EnumMember(Value = "S")] 
    Sports = 'S', 
    [EnumMember(Value = "W")] 
    Writer = 'W' 
} 
+0

wow questa sembra una soluzione ideale, e sicuramente funziona alla grande, grazie! – SelAromDotNet

+1

Come deserializzare il precedente? Ho problemi nel deserializzare questo. Es: servizio ha questo enum: [EnumMember (Value = "Contemp")] = contemporanee 'C', codice di interfaccia utente ha questo enum: [EnumMember (Value = "Contemp")] contemporanea = 'C ' Quindi, mentre deserializza, non è in grado di trovare "Contemp" .. C'è un modo per farlo? o semplicemente scambiare Enum e Valore a, [EnumMember (Value = "ontemporary")] Contemp = 'C', –

3

Questo codice funziona perfettamente:

CardType[] array = { CardType.Artist, CardType.Contemporary }; 
string s = JsonConvert.SerializeObject(array); 
var array2 = JsonConvert.DeserializeObject<CardType[]>(s); 

Aggiornamento:
Che dire di out-of-box StringEnumConverter:

[JsonConverter(typeof(StringEnumConverter))] 
public CardType Type { get; set; } 
+0

sì, mi dispiace di aver sbagliato, il JSON non viene generato da una serializzazione, si tratta di una stringa JSON personalizzata, che utilizza il valore char al posto dell'int. per favore vedi la descrizione aggiornata e grazie per il tuo aiuto! – SelAromDotNet

0

Si può solo aggiungere SerializerSettings.Converters.Add (nuova StringEnumConverter());

alla classe BrowserJsonFormatter

public class BrowserJsonFormatter : JsonMediaTypeFormatter 
{ 
    public BrowserJsonFormatter() 
    { 
     SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 
     SerializerSettings.Formatting = Formatting.Indented; 
     SerializerSettings.NullValueHandling = NullValueHandling.Ignore; 
     SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
     SerializerSettings.Converters.Add(new EmptyToNullConverter()); 
     SerializerSettings.Converters.Add(new StringEnumConverter()); 
     //SerializerSettings.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate; 
    } 

    public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) 
    { 
     base.SetDefaultContentHeaders(type, headers, mediaType); 
     headers.ContentType = new MediaTypeHeaderValue("application/json"); 
    } 
}