.NET – Sérialisation JSON de enum sous forme de chaîne

J’ai une classe qui contient une propriété enum et lors de la sérialisation de l’object à l’aide de JavaScriptSerializer , mon résultat json contient la valeur entière de l’énumération plutôt que sa ssortingng “name”. Existe-t-il un moyen d’obtenir l’enum sous forme de ssortingng dans mon json sans avoir à créer un JavaScriptConverter personnalisé? Peut-être y a-t-il un atsortingbut avec lequel je pourrais décorer la définition d’ enum , ou la propriété d’object, avec?

Par exemple:

 enum Gender { Male, Female } class Person { int Age { get; set; } Gender Gender { get; set; } } 

Résultat souhaité:

 { "Age": 35, "Gender": "Male" } 

Non, il n’y a pas d’atsortingbut spécial que vous pouvez utiliser. JavaScriptSerializer sérialise les enums à leurs valeurs numériques et non à leur représentation sous forme de chaîne. Vous devez utiliser une sérialisation personnalisée pour sérialiser l’ enum au lieu de la valeur numérique.

Edit: Comme indiqué par @OmerBakhari, JSON.net couvre ce cas d’utilisation (via l’atsortingbut [JsonConverter(typeof(SsortingngEnumConverter))] ) et bien d’autres non gérés par les sérialiseurs .net intégrés. Voici un lien comparant les fonctionnalités et les fonctionnalités des sérialiseurs .

J’ai trouvé que Json.NET fournit la fonctionnalité exacte que je recherche avec un atsortingbut SsortingngEnumConverter :

 using Newtonsoft.Json; using Newtonsoft.Json.Converters; [JsonConverter(typeof(SsortingngEnumConverter))] public Gender Gender { get; set; } 

Plus de détails à disponible sur la documentation SsortingngEnumConverter .

Ajoutez ce qui suit à votre sérialisation global.asax pour JSON de c # enum en tant que chaîne

  HttpConfiguration config = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.Converters.Add (new Newtonsoft.Json.Converters.SsortingngEnumConverter()); 

@Iggy answer définit la sérialisation JSON de c # enum sous forme de chaîne uniquement pour ASP.NET (API Web, etc.).

Mais pour que cela fonctionne également avec la sérialisation ad hoc, ajoutez les suites à votre classe de démarrage (comme Global.asax Application_Start)

 //convert Enums to Ssortingngs (instead of Integer) globally JsonConvert.DefaultSettings = (() => { var settings = new JsonSerializerSettings(); settings.Converters.Add(new SsortingngEnumConverter { CamelCaseText = true }); return settings; }); 

Plus d’informations sur la page Json.NET

De plus, pour que votre membre enum puisse sérialiser / désérialiser vers / depuis un texte spécifique, utilisez le

System.Runtime.Serialization.EnumMember

atsortingbut, comme ceci:

 public enum time_zone_enum { [EnumMember(Value = "Europe/London")] EuropeLondon, [EnumMember(Value = "US/Alaska")] USAlaska } 

Je n’ai pas pu changer le modèle source comme dans la réponse supérieure (de @ob.), Et je ne voulais pas l’enregistrer globalement comme @Iggy. J’ai donc combiné https://stackoverflow.com/a/2870420/237091 et https://stackoverflow.com/a/18152942/237091 de @ Iggy pour permettre la configuration du convertisseur de chaîne enum lors de la commande SerializeObject elle-même:

 Newtonsoft.Json.JsonConvert.SerializeObject( objectToSerialize, Newtonsoft.Json.Formatting.None, new Newtonsoft.Json.JsonSerializerSettings() { Converters = new List { new Newtonsoft.Json.Converters.SsortingngEnumConverter() } }) 

Cela se fait facilement en ajoutant un atsortingbut ScriptIgnore à la propriété Gender , ce qui empêche sa sérialisation et ajoute une propriété GenderSsortingng qui est sérialisée:

 class Person { int Age { get; set; } [ScriptIgnore] Gender Gender { get; set; } ssortingng GenderSsortingng { get { return Gender.ToSsortingng(); } } } 

Cette version de la réponse de Stephen ne change pas le nom dans le JSON:

 [DataContract( Namespace = "http://schemas.datacontract.org/2004/07/Whatever")] class Person { [DataMember] int Age { get; set; } Gender Gender { get; set; } [DataMember(Name = "Gender")] ssortingng GenderSsortingng { get { return this.Gender.ToSsortingng(); } set { Gender g; this.Gender = Enum.TryParse(value, true, out g) ? g : Gender.Male; } } } 

Voici la réponse pour newtonsoft.json

 enum Gender { Male, Female } class Person { int Age { get; set; } [JsonConverter(typeof(SsortingngEnumConverter))] Gender Gender { get; set; } } 

Voici une solution simple qui sérialise un enum C # côté serveur en JSON et utilise le résultat pour remplir un élément côté client. Cela fonctionne à la fois pour les énumérations simples et les énumérations de bitflag.

J’ai inclus la solution de bout en bout car je pense que la plupart des personnes souhaitant sérialiser un enum C # en JSON l’utiliseront probablement pour remplir un menu déroulant .

Voici:

Exemple d’énumération

 public enum Role { None = Permission.None, Guest = Permission.Browse, Reader = Permission.Browse| Permission.Help , Manager = Permission.Browse | Permission.Help | Permission.Customise } 

Enum complexe qui utilise des OU binarys pour générer un système d’permissions. Donc, vous ne pouvez pas compter sur l’index simple [0,1,2 ..] pour la valeur entière de l’énumération.

Côté serveur – C #

 Get["/roles"] = _ => { var type = typeof(Role); var data = Enum .GetNames(type) .Select(name => new { Id = (int)Enum.Parse(type, name), Name = name }) .ToArray(); return Response.AsJson(data); }; 

Le code ci-dessus utilise le framework NancyFX pour gérer la requête Get. Il utilise la méthode d’assistance Response.AsJson() de Nancy – mais ne vous inquiétez pas, vous pouvez utiliser n’importe quel formateur JSON standard, car l’énumération a déjà été projetée dans un simple type anonyme prêt pour la sérialisation.

JSON généré

 [ {"Id":0,"Name":"None"}, {"Id":2097155,"Name":"Guest"}, {"Id":2916367,"Name":"Reader"}, {"Id":4186095,"Name":"Manager"} ] 

Côté client – CoffeeScript

 fillSelect=(id, url, selectedValue=0)-> $select = $ id $option = (item)-> $ "", { value:"#{item.Id}" html:"#{item.Name}" selected:"selected" if item.Id is selectedValue } $.getJSON(url).done (data)->$option(item).appendTo $select for item in data $ -> fillSelect "#role", "/roles", 2916367 

HTML avant

  

HTML après

  

Vous pouvez créer JsonSerializerSettings avec l’appel à JsonConverter.SerializeObject comme ci-dessous:

 var result = JsonConvert.SerializeObject ( dataObject, new JsonSerializerSettings { Converters = new [] {new SsortingngEnumConverter()} } ); 

La combinaison des réponses d ‘Omer Bokhari et d’ uri est toujours ma solution puisque les valeurs que je veux fournir sont généralement différentes de celles que j’ai dans ma liste, en particulier que j’aimerais pouvoir changer mes énumérations si nécessaire.

Donc, si quelqu’un est intéressé, c’est quelque chose comme ça:

 public enum Gender { [EnumMember(Value = "male")] Male, [EnumMember(Value = "female")] Female } class Person { int Age { get; set; } [JsonConverter(typeof(SsortingngEnumConverter))] Gender Gender { get; set; } } 

Vous pouvez également append un convertisseur à votre JsonSerializer si vous ne souhaitez pas utiliser l’atsortingbut JsonConverter :

 ssortingng SerializedResponse = JsonConvert.SerializeObject( objToSerialize, new Newtonsoft.Json.Converters.SsortingngEnumConverter() ); 

Il fonctionnera pour chaque enum qu’il voit lors de cette sérialisation.

Pour .Net Core Web Api: –

 public void ConfigureServices(IServiceCollection services) { ... services.AddJsonFormatters(f => f.Converters.Add(new SsortingngEnumConverter())); ... } 

Remarqué qu’il n’y a pas de réponse pour la sérialisation lorsqu’il existe un atsortingbut Description.

Voici mon implémentation qui prend en charge l’atsortingbut Description.

 public class CustomSsortingngEnumConverter : Newtonsoft.Json.Converters.SsortingngEnumConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { Type type = value.GetType() as Type; if (!type.IsEnum) throw new InvalidOperationException("Only type Enum is supported"); foreach (var field in type.GetFields()) { if (field.Name == value.ToSsortingng()) { var atsortingbute = Atsortingbute.GetCustomAtsortingbute(field, typeof(DescriptionAtsortingbute)) as DescriptionAtsortingbute; writer.WriteValue(atsortingbute != null ? atsortingbute.Description : field.Name); return; } } throw new ArgumentException("Enum not found"); } } 

Enum:

 public enum FooEnum { // Will be serialized as "Not Applicable" [Description("Not Applicable")] NotApplicable, // Will be serialized as "Applicable" Applicable } 

Usage:

 [JsonConverter(typeof(CustomSsortingngEnumConverter))] public FooEnum test { get; set; } 

C’est une vieille question mais je pensais que je consortingbuerais juste au cas où. Dans mes projets, j’utilise des modèles distincts pour toutes les requêtes Json. Un modèle aurait généralement le même nom que l’object domaine avec le préfixe “Json”. Les modèles sont mappés à l’aide d’ AutoMapper . Si le modèle json déclare une propriété de chaîne qui est une énumération sur la classe de domaine, AutoMapper se résoudra à sa présentation sous forme de chaîne.

Au cas où vous vous poseriez la question, j’ai besoin de modèles distincts pour les classes sérialisées Json, car le sérialiseur intégré génère des références circulaires autrement.

J’espère que cela aide quelqu’un.

Vous pouvez réellement utiliser un JavaScriptConverter pour y parvenir avec le JavaScriptSerializer intégré. En convertissant votre enum en Uri, vous pouvez l’encoder comme une chaîne.

J’ai décrit comment faire cela pour les dates, mais il peut aussi être utilisé pour les énumérations.

http://blog.calyptus.eu/seb/2011/12/custom-datetime-json-serialization/

Au cas où quelqu’un trouverait ce qui précède insuffisant, j’ai fini par régler cette surcharge:

 JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.SsortingngEnumConverter()) 

Méthode ASP.NET Core:

 public class Startup { public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.SsortingngEnumConverter()); }); } } 

https://gist.github.com/regisdiogo/27f62ef83a804668eb0d9d0f63989e3e

J’ai rassemblé tous les éléments de cette solution en utilisant la bibliothèque Newtonsoft.Json . Il corrige le problème enum et améliore également la gestion des erreurs, et il fonctionne dans les services hébergés par IIS. C’est beaucoup de code, donc vous pouvez le trouver sur GitHub ici: https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs

Vous devez append des entrées à votre Web.config pour le faire fonctionner, vous pouvez voir un exemple de fichier ici: https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config

 new JavaScriptSerializer().Serialize( (from p in (new List() { new Person() { Age = 35, Gender = Gender.Male } }) select new { Age =p.Age, Gender=p.Gender.ToSsortingng() } ).ToArray()[0] );