JavaScriptSerializer - sérialisation JSON de l'énumération sous forme de chaîne

1162

J'ai une classe qui contient une enumpropriété, et lors de la sérialisation de l'objet à l'aide JavaScriptSerializer, mon résultat json contient la valeur entière de l'énumération plutôt que son string"nom". Existe-t-il un moyen d'obtenir l'énumération en tant que stringdans mon json sans avoir à créer de personnalisation JavaScriptConverter? Peut-être y a-t-il un attribut avec lequel je pourrais décorer la enumdéfinition ou la propriété de l'objet?

Par exemple:

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }
    Gender Gender { get; set; }
}

Résultat json souhaité:

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

Idéalement à la recherche d'une réponse avec des classes de framework .NET intégrées, sinon des alternatives possibles (comme Json.net) sont les bienvenues.

Omer Bokhari
la source
8
Changer à quoi? La réponse ayant le plus de votes positifs ne répond pas réellement à la question - oui, elle est utile dans d'autres contextes, d'où les votes, mais elle n'est d'aucune utilité pratique si vous êtes bloqué avec MS JavaScriptSerializer, comme vous l'êtes essentiellement si vous utilisez des méthodes de page et , surtout, comme l'exige la question. La réponse acceptée dit que ce n'est pas possible. Ma réponse alors qu'un peu de piratage fait le travail.
Stephen Kennedy

Réponses:

376

Non, vous ne pouvez utiliser aucun attribut spécial. JavaScriptSerializersérialise 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 le en enumtant que son nom au lieu d'une valeur numérique.


Si vous pouvez utiliser JSON.Net au lieu de JavaScriptSerializervoir la réponse à cette question fournie par OmerBakhari : JSON.net couvre ce cas d'utilisation (via l'attribut [JsonConverter(typeof(StringEnumConverter))]) et bien d'autres non traités par les sérialiseurs .net intégrés. Voici un lien comparant les caractéristiques et fonctionnalités des sérialiseurs .

Matt Dearing
la source
7
@Fabzter - votre solution a fonctionné avec moi en utilisant Json de Newtonsoft
BeemerGuy
1
@BornToCode Json.NET est le sérialiseur qu'ASP.NET utilise par défaut.
BrainSlugs83
12
@ BrainSlugs83 - La question portait sur l'utilisation de JavaScriptSerializer, pas Json.NET (et si vous regardez l'historique des révisions, vous verrez qu'il y a eu une modification pour clarifier cela), si vous utilisez JavaScriptSerializer, l'attribut JsonConverterne fonctionnera pas.
BornToCode
50
Veuillez supprimer ceci comme réponse acceptée car cela ne résout pas le problème, la réponse ci-dessous avec plus de 1000 votes positifs DOIT.
MHGameWork
pourriez-vous me répondre
Yongqiang Chen
2101

J'ai trouvé que Json.NET fournit la fonctionnalité exacte que je recherche avec un StringEnumConverterattribut:

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

[JsonConverter(typeof(StringEnumConverter))]
public Gender Gender { get; set; }

Plus de détails sur disponibles sur la StringEnumConverterdocumentation .

Il existe d'autres endroits pour configurer ce convertisseur de manière plus globale:

  • enum lui-même si vous voulez que enum soit toujours sérialisé / désérialisé en tant que chaîne:

    [JsonConverter(typeof(StringEnumConverter))]  
    enum Gender { Male, Female }
  • Si quelqu'un veut éviter la décoration d'attributs, vous pouvez ajouter le convertisseur à votre JsonSerializer (suggéré par Bjørn Egil ):

    serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); 

    et cela fonctionnera pour chaque énumération qu'il verra pendant cette sérialisation (suggérée par Travis ).

  • ou JsonConverter (suggéré par la banane ):

    JsonConvert.SerializeObject(MyObject, 
        new Newtonsoft.Json.Converters.StringEnumConverter());

De plus, vous pouvez contrôler la casse et si les nombres sont toujours acceptés à l'aide du constructeur StringEnumConverter (NamingStrategy, Boolean) .

Omer Bokhari
la source
9
Suivez par lien pour la description comment l'utiliser dans l'application asp.net mvc james.newtonking.com/archive/2008/10/16/…
RredCat
2
Voici le lien vers cette fonction: james.newtonking.com/projects/json/help/html/…
CAD bloke
61
HttpConfiguration config = GlobalConfiguration.Configuration; config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.Converters.Add (new Newtonsoft.Json.Converters.StringEnumConverter ());
Iggy
1
Il est utile de noter que par défaut ASP.NET MVC n'utilise pas Json.Net comme sérialiseur json et qu'il faut étendre Controllerou remplacer manuellement chaque sérialisation.
Odys
2
Vous pouvez personnaliser le convertisseur (par exemple, pour la camelCasesortie):new StringEnumConverter { CamelCaseText = true }
Seafish
172

Ajoutez ce qui suit à votre global.asax pour la sérialisation 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.StringEnumConverter());
Iggy
la source
4
Pour une raison quelconque, je n'arrive pas à faire fonctionner cela. Fiddler montre un 2 têtu plutôt que «Avertissement», même avec cela en place. En outre - une raison pour laquelle de changer l' Formattingà Indented?
sq33G
5
La troisième ligne de cet exemple a été ajoutée au fichier App_start / webapiconfig.cs et m'a fait une astuce dans un projet ASP.NET Web API 2.1 pour renvoyer des chaînes pour les valeurs d'énumération dans les appels REST (json fomat).
Greg Z.
1
Existe-t-il un moyen de définir cette propriété uniquement par l'étendue de la demande?
Anestis Kivranoglou
@AnestisKivranoglou utilise simplement un sérialiseur json personnalisé par demande avec ses propres paramètres.
BrainSlugs83
3
le premier paramètre de sérialisation du retrait n'est pas lié à la question op.
user3791372
153

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

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

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

Plus d'information sur la page Json.NET

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

System.Runtime.Serialization.EnumMember

attribut, comme ceci:

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

    [EnumMember(Value = "US/Alaska")] 
    USAlaska
}
Juri
la source
6
Je vous remercie! Je cherchais juste [EnumMember].
Poulad
La CamelCaseTextpropriété est désormais marquée comme obsolète. Nouvelle façon d'instancier le convertisseur:new StringEnumConverter(new CamelCaseNamingStrategy())
fiat
Merci beaucoup, faites ma journée! :)
Eldoïr
39

Je n'ai pas pu changer le modèle source comme dans la première réponse (de @ob.), Et je ne voulais pas l'enregistrer globalement comme @Iggy. Donc , je combine https://stackoverflow.com/a/2870420/237091 et @ Iggy https://stackoverflow.com/a/18152942/237091 pour permettre la mise en place du convertisseur de chaîne sur ENUM au cours de la commande serialiseObjet lui - même:

Newtonsoft.Json.JsonConvert.SerializeObject(
    objectToSerialize, 
    Newtonsoft.Json.Formatting.None, 
    new Newtonsoft.Json.JsonSerializerSettings()
    {
        Converters = new List<Newtonsoft.Json.JsonConverter> {
            new Newtonsoft.Json.Converters.StringEnumConverter()
        }
    })
Scott Stafford
la source
cela fonctionne aussi bien si vous avez une propriété comme celle-ci Liste <someEnumType>
Bogdan
34

La combinaison de Omer Bokhari et des réponses d'uri est toujours ma solution car les valeurs que je veux fournir sont généralement différentes de ce que j'ai dans mon énumération spécialement que j'aimerais pouvoir changer mes énumérations si j'en ai besoin.

Donc, si quelqu'un est intéressé, c'est quelque chose comme ceci:

public enum Gender
{
   [EnumMember(Value = "male")] 
   Male,
   [EnumMember(Value = "female")] 
   Female
}

class Person
{
    int Age { get; set; }
    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}
Ashkan Sirous
la source
1
J'utilisais JsonPropertyAttributepour les membres enum et cela fonctionne pour des tâches de désérialisation simples. Malheureusement, lors des réglages manuels avec JTokens, il est ignoré. Heureusement EnumMemberAttributefonctionne comme un charme. Merci!
Prolog
Cela fonctionne avec JavaScriptSerializer?
Stephen Kennedy
31

Cela se fait facilement en ajoutant un ScriptIgnoreattribut à la Genderpropriété, ce GenderStringqui empêche sa sérialisation et en ajoutant une propriété qui est sérialisée:

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

    string GenderString { get { return Gender.ToString(); } }
}
Stephen Kennedy
la source
29
Laissez-moi essayer d'expliquer. Cette solution n'est pas correcte selon les concepteurs. Vous avez modifié le modèle en fonction de l'objectif de la vue. Mais le modèle ne doit contenir que des données et ne se soucie pas des présentations. Vous devez déplacer cette fonctionnalité sur l'autre couche.
RredCat
4
En fait, le modèle est utilisé pour transmettre les données du contrôleur, et ce n'est pas le contrôleur, qui ne se soucie pas de la présentation. L'introduction de la propriété automatisée (GenderString ici) ne casse pas le contrôleur, qui utilise toujours la propriété Gender, mais offre un accès facile pour une vue. Solution logique.
Dima
17
@RredCat Il n'y a rien de mal à avoir des propriétés spécifiques à la vue dans le "modèle de vue". À mon humble avis,
Mariano Desanze
5
@RredCat, même s'il était incorrect selon un modèle, l'OP ne dit rien à ce sujet, c'est donc une bonne réponse. (Même si, philosophiquement, je suis d'accord avec votre point de vue.)
MEMark
10
L'abandon de vélo pédantiquement absurde dans ce fil de commentaires est fascinant.
Mike Mooney
26

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")]
    string GenderString
    {
        get { return this.Gender.ToString(); }
        set 
        { 
            Gender g; 
            this.Gender = Enum.TryParse(value, true, out g) ? g : Gender.Male; 
        }
    }
}
mheyman
la source
3
Je crois que cela est valable pour le DataContractJsonSerializernonJavaScriptSerializer
KCD
Simple et résout le problème pour moi en utilisant des sérialiseurs de framework .NET natifs.
Le sénateur
meilleure solution pour moi car je ne suis pas autorisé à utiliser des bibliothèques tierces (problèmes de conformité ISO)
Daniel Gruszczyk
Ce n'est pas pour le type de sérialiseur en question bien sûr. JavaScriptSerializer sérialise tout ce qui n'est pas ignoré, tandis que DataContractJsonSerializer nécessite des attributs DataMember. Merci pour le cri, mais veuillez noter que vous avez mal orthographié mon nom :)
Stephen Kennedy
25

Voici la réponse pour newtonsoft.json

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}
GuCa
la source
1
Merci pour cette réponse, m'a beaucoup aidé! Si vous souhaitez définir vos énumérations dans PascalCase, mais que vous voulez qu'il soit sérialisé dans camelCase, vous devez ajouter trueà votre type JsonConverter comme ceci:[JsonConverter(typeof(StringEnumConverter), true)]
Peet
25

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

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

st1
la source
fonctionne parfaitement
DevJoe
16

Vous pouvez également ajouter un convertisseur à votre JsonSerializersi vous ne souhaitez pas utiliser d' JsonConverterattribut:

string SerializedResponse = JsonConvert.SerializeObject(
     objToSerialize, 
     new Newtonsoft.Json.Converters.StringEnumConverter()
); 

Cela fonctionnera pour tout enumce qu'il verra pendant cette sérialisation.

JerryGoyal
la source
15

Voici une solution simple qui sérialise une énumération C # côté serveur en JSON et utilise le résultat pour remplir un côté client <select> élément . Cela fonctionne pour les énumérations simples et les énumérations bitflag.

J'ai inclus la solution de bout en bout parce que je pense que la plupart des gens qui souhaitent sérialiser une énumération C # en JSON l'utiliseront probablement aussi pour remplir une liste <select>déroulante.

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
}

Une énumération complexe qui utilise des OR au niveau du bit pour générer un système d'autorisations. Vous ne pouvez donc pas vous fier à 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 demande Get. Il utilise la Response.AsJson()méthode d'assistance 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 type anonyme simple 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)-> $ "<option/>", 
        {
            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

<select id="role" name="role"></select>

HTML après

<select id="role" name="role">
    <option value="0">None</option>
    <option value="2097155">Guest</option>
    <option value="2916367" selected="selected">Reader</option>
    <option value="4186095">Manager</option>
</select>
biofractal
la source
13

Pour le noyau ASP.Net Ajoutez simplement les éléments suivants à votre classe de démarrage:

JsonConvert.DefaultSettings = (() =>
        {
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new StringEnumConverter { AllowIntegerValues = false });
            return settings;
        });
Yahya Hussein
la source
1
Cela fonctionne pour toutes les versions, pas seulement pour le noyau.
bikeman868
11

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

var result = JsonConvert.SerializeObject
            (
                dataObject,
                new JsonSerializerSettings
                {
                    Converters = new [] {new StringEnumConverter()}
                }
            );
Yang Zhang
la source
10

A remarqué qu'il n'y a pas de réponse pour la sérialisation quand il y a un attribut Description.

Voici mon implémentation qui prend en charge l'attribut Description.

public class CustomStringEnumConverter : Newtonsoft.Json.Converters.StringEnumConverter
{
    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.ToString())
            {
                var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
                writer.WriteValue(attribute != null ? attribute.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(CustomStringEnumConverter))]
public FooEnum test { get; set; }
Greg R Taylor
la source
10

Pour .Net Core: -

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));
    ...
}
PeteGO
la source
2
Si c'est celui du Microsoft.AspNetCore.Mvc.Formatters.Jsonpackage NuGet, il semble que ce ne soit qu'une méthode d'extension IMvcCoreBuilder, non IMvcBuilder. Il est donc utilisé comme services.AddMvcCore().AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));.
infl3x
9

Dans .net core 3, cela est désormais possible avec les classes intégrées dans System.Text.Json:

var person = new Person();
// Create and add a converter which will use the string representation instead of the numeric value.
var stringEnumConverter = new System.Text.Json.Serialization.JsonStringEnumConverter();
JsonSerializerOptions opts = new JsonSerializerOptions();
opts.Converters.Add(stringEnumConverter);
// Generate json string.
var json = JsonSerializer.Serialize<Person>(person, opts);

Pour configurer JsonStringEnumConverteravec une décoration d'attribut pour la propriété spécifique:

using System.Text.Json.Serialization;

[JsonConverter(typeof(JsonStringEnumConverter))]
public Gender Gender { get; set; }

Si vous souhaitez toujours convertir l'énumération en chaîne, placez l'attribut sur l'énumération elle-même.

[JsonConverter(typeof(JsonStringEnumConverter))] 
enum Gender { Male, Female }
Björn
la source
9

Asp.Net Core 3 avec System.Text.Json

public void ConfigureServices(IServiceCollection services)
{

    services
        .AddControllers()
        .AddJsonOptions(options => 
           options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())
        );

    //...
 }
Serj-Tm
la source
8

Juste au cas où quelqu'un trouverait ce qui précède insuffisant, j'ai fini par me contenter de cette surcharge:

JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter())
hngr18
la source
C'est une bonne solution pour un cas d'utilisation actuel: je ne veux pas changer les valeurs par défaut des sérialiseurs et j'ai des problèmes avec les attributs, car mes propriétés sont de type IList <EnumType>.
Dirk Brockhaus
5

C'est une vieille question mais j'ai pensé que je contribuerais juste au cas où. Dans mes projets, j'utilise des modèles distincts pour toutes les demandes Json. Un modèle aurait généralement le même nom que l'objet de domaine avec le préfixe "Json". Les modèles sont mappés à l'aide d' AutoMapper . En faisant en sorte que 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ésout à sa présentation 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é contient des références circulaires dans le cas contraire.

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

Ales Potocnik Hahonina
la source
Ravi d'apprendre cette fonctionnalité d'Automapper ;-) L'attribut [ScriptIgnore] supprimera les références circulaires
ledragon
1
Oh. Ne connaissait pas l'attribut. Merci! Pourriez-vous l'utiliser sur votre Pocos? J'ai recouru à l'utilisation de définitions MetadataType pour tous les attributs Poco juste pour les garder propres. L'attribut fonctionnerait-il toujours via les métadonnées?
Ales Potocnik Hahonina
3

Vous pouvez réellement utiliser un JavaScriptConverter pour y parvenir avec le JavaScriptSerializer intégré. En convertissant votre énumération en Uri, vous pouvez l'encoder sous forme de chaîne.

J'ai décrit comment faire cela pour les dates, mais il peut également être utilisé pour les énumérations. Format JSON DateTime personnalisé pour .NET JavaScriptSerializer .

Sebastian Markbåge
la source
Solution très intéressante! Merci d'avoir partagé.
Oliver
1

Je ne sais pas si cela est toujours pertinent, mais j'ai dû écrire directement dans un fichier json et j'ai trouvé les réponses suivantes regroupant plusieurs réponses stackoverflow ensemble

public class LowercaseJsonSerializer
{
    private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        ContractResolver = new LowercaseContractResolver()
    };

    public static void Serialize(TextWriter file, object o)
    {
        JsonSerializer serializer = new JsonSerializer()
        {
            ContractResolver = new LowercaseContractResolver(),
            Formatting = Formatting.Indented,
            NullValueHandling = NullValueHandling.Ignore
        };
        serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
        serializer.Serialize(file, o);
    }

    public class LowercaseContractResolver : DefaultContractResolver
    {
        protected override string ResolvePropertyName(string propertyName)
        {
            return Char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1);
        }
    }
}

Cela garantit que toutes mes clés json sont en minuscules en commençant selon les "règles" json. Le formate proprement en retrait et ignore les valeurs nulles dans la sortie. De plus, en ajoutant un StringEnumConverter, il imprime les énumérations avec leur valeur de chaîne.

Personnellement, je trouve cela le plus propre possible, sans avoir à salir le modèle avec des annotations.

usage:

    internal void SaveJson(string fileName)
    {
        // serialize JSON directly to a file
        using (StreamWriter file = File.CreateText(@fileName))
        {
            LowercaseJsonSerializer.Serialize(file, jsonobject);
        }
    }
kenny
la source
0

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

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

Jon Grant
la source
0

Et pour VB.net, j'ai trouvé les œuvres suivantes:

Dim sec = New Newtonsoft.Json.Converters.StringEnumConverter()
sec.NamingStrategy() = New Serialization.CamelCaseNamingStrategy

Dim JSON_s As New JsonSerializer
JSON_s.Converters.Add(sec)

Dim jsonObject As JObject
jsonObject = JObject.FromObject(SomeObject, JSON_s)
Dim text = jsonObject.ToString

IO.File.WriteAllText(filePath, text)
Benjamin Swedlove
la source
0

Une option légèrement plus évolutive

Face à la même question, nous avons déterminé que nous avions besoin d'une version personnalisée de StringEnumConverterpour nous assurer que nos valeurs d'énumération pouvaient s'étendre au fil du temps sans se casser de manière catastrophique du côté de la désérialisation (voir arrière-plan ci-dessous). En utilisant leSafeEnumConverter suit permet à la désérialisation de se terminer même si la charge utile contient une valeur pour l'énumération qui n'a pas de définition nommée, plus proche du fonctionnement de la conversion int-en-énumération.

Usage:

[SafeEnumConverter]
public enum Colors
{
    Red,
    Green,
    Blue,
    Unsupported = -1
}

ou

[SafeEnumConverter((int) Colors.Blue)]
public enum Colors
{
    Red,
    Green,
    Blue
}

La source:

public class SafeEnumConverter : StringEnumConverter
{
    private readonly int _defaultValue;

    public SafeEnumConverter()
    {
        // if you've been careful to *always* create enums with `0` reserved
        // as an unknown/default value (which you should), you could use 0 here. 
        _defaultValue = -1;
    }

    public SafeEnumConverter(int defaultValue)
    {
        _defaultValue = defaultValue;
    }

    /// <summary>
    /// Reads the provided JSON and attempts to convert using StringEnumConverter. If that fails set the value to the default value.
    /// </summary>
    /// <returns>The deserialized value of the enum if it exists or the default value if it does not.</returns>
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        try
        {
            return base.ReadJson(reader, objectType, existingValue, serializer);
        }
        catch
        {
            return Enum.Parse(objectType, $"{_defaultValue}");
        }
    }

    public override bool CanConvert(Type objectType)
    {
        return base.CanConvert(objectType) && objectType.GetTypeInfo().IsEnum;
    }
}

Contexte

Lorsque nous avons envisagé d'utiliser le StringEnumConverter, le problème que nous avions était que nous avions également besoin de passivité pour les cas où une nouvelle valeur d'énumération était ajoutée, mais tous les clients n'étaient pas immédiatement conscients de la nouvelle valeur. Dans ces cas, le StringEnumConverterpackage avec Newtonsoft JSON renvoie un message JsonSerializationExceptionsimilaire à «Erreur lors de la conversion de la valeur SomeString en type EnumType», puis l' ensemble du processus de désérialisation échoue. C'était une rupture pour nous, car même si le client prévoyait d'ignorer / de rejeter la valeur de la propriété qu'il ne comprenait pas, il devait toujours être capable de désérialiser le reste de la charge utile!

Poussiéreux
la source
-2
        Person p = new Person();
        p.Age = 35;
        p.Gender = Gender.Male;
        //1.  male="Male";
        string male = Gender.Male.ToString();

        p.Gender = Gender.Female;

        //2.  female="Female";
        string female = Enum.GetName(typeof(Gender), p.Gender);

        JObject jobj = new JObject();
        jobj["Age"] = p.Age;
        jobj["Gender"] = male;
        jobj["Gender2"] = female;

        //you result:  josn= {"Age": 35,"Gender": "Male","Gender2": "Female"}
        string json = jobj.ToString();
zilong
la source
-5
new JavaScriptSerializer().Serialize(  
    (from p   
    in (new List<Person>() {  
        new Person()  
        {  
            Age = 35,  
            Gender = Gender.Male  
        }  
    })  
    select new { Age =p.Age, Gender=p.Gender.ToString() }  
    ).ToArray()[0]  
);
Slava
la source