c# stringenumconverter - .NET-serialización JSON de enum como cadena




newtonsoft serialize (18)

No pude cambiar el modelo de origen como en la respuesta superior (de @ob.), Y no quería registrarlo globalmente como @Iggy. Así que combiné https://stackoverflow.com/a/2870420/237091 y @ Iggy's https://stackoverflow.com/a/18152942/237091 para permitir la configuración del convertidor de enumeración de cadenas durante el comando SerializeObject:

Newtonsoft.Json.JsonConvert.SerializeObject(
    objectToSerialize, 
    Newtonsoft.Json.Formatting.None, 
    new Newtonsoft.Json.JsonSerializerSettings()
    {
        Converters = new List<Newtonsoft.Json.JsonConverter> {
            new Newtonsoft.Json.Converters.StringEnumConverter()
        }
    })

Tengo una clase que contiene una propiedad enum , y al serializar el objeto utilizando JavaScriptSerializer , el resultado de mi json contiene el valor entero de la enumeración en lugar de su string "nombre". ¿Hay alguna manera de obtener la enumeración como una string en mi json sin tener que crear un JavaScriptConverter personalizado? Tal vez hay un atributo con el que podría decorar la definición de enum , o propiedad de objeto, con?

Como ejemplo:

enum Gender { Male, Female }

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

Resultado deseado de json:

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

He reunido todas las piezas de esta solución utilizando la biblioteca Newtonsoft.Json . Corrige el problema de enumeración y también hace que el manejo de errores sea mucho mejor, y funciona en los servicios alojados en IIS. Es bastante código, por lo que puede encontrarlo en GitHub aquí: https://github.com/jongrant/wcfjsonserializer/blob/master/NewtonsoftJsonFormatter.cs

Debe agregar algunas entradas a su Web.config para que funcione, puede ver un archivo de ejemplo aquí: https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config


Agregue lo siguiente a su global.asax para la serialización JSON de c # enum como cadena

  HttpConfiguration config = GlobalConfiguration.Configuration;
            config.Formatters.JsonFormatter.SerializerSettings.Formatting =
                Newtonsoft.Json.Formatting.Indented;

            config.Formatters.JsonFormatter.SerializerSettings.Converters.Add
                (new Newtonsoft.Json.Converters.StringEnumConverter());

Aquí hay una solución simple que serializa una enumeración C # del lado del servidor a JSON y usa el resultado para rellenar un elemento <select> lado del cliente. Esto funciona tanto para enumeraciones simples como para enumeraciones bitflag.

He incluido la solución de extremo a extremo porque creo que la mayoría de las personas que desean serializar una enumeración de C # a JSON probablemente también la usarán para completar el menú desplegable <select> .

Aquí va:

Ejemplo Enum

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

Una enumeración compleja que utiliza OR de bit a bit para generar un sistema de permisos. Por lo tanto, no puede confiar en el índice simple [0,1,2 ..] para el valor entero de la enumeración.

Lado del servidor - 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);
};

El código anterior utiliza el marco NancyFX para manejar la solicitud de obtención. Utiliza el método de ayuda de Nancy's Response.AsJson() , pero no se preocupe, puede usar cualquier formateador JSON estándar, ya que la enumeración ya se ha proyectado en un tipo anónimo simple listo para la serialización.

JSON generado

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

Lado del cliente - 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 antes

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

HTML despué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>


No, no hay ningún atributo especial que puedas usar. JavaScriptSerializer serializa enums a sus valores numéricos y no a su representación de cadena. Necesitaría usar una serialización personalizada para serializar la enum como su nombre en lugar de un valor numérico.

Edición: Como lo señaló @OmerBakhari, JSON.net cubre este caso de uso (a través del atributo [JsonConverter(typeof(StringEnumConverter))] ) y muchos otros no manejados por los serializadores .net incorporados. Aquí hay un enlace que compara las características y funcionalidades de los serializadores .


@Iggy answer establece la serialización JSON de c # enum como cadena solo para ASP.NET (API web y así).

Pero para que funcione también con la serialización ad hoc, agregue el siguiente a su clase de inicio (como 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;
});

Más información en la página de Json.NET.

Además, para que su miembro de enumeración sea serializado / deserializado a / desde un texto específico, use la

System.Runtime.Serialization.EnumMember

atributo, como este:

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

    [EnumMember(Value = "US/Alaska")] 
    USAlaska
}

Aquí está la respuesta para newtonsoft.json

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

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

También puede agregar un convertidor a su JsonSerializer si no desea usar el atributo JsonConverter :

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

Funcionará para cada enum que vea durante esa serialización.


Esto se hace fácilmente agregando un atributo ScriptIgnore a la propiedad Gender , haciendo que no se GenderString , y agregando una propiedad GenderString que se serializa:

class Person
{
    int Age { get; set; }

    [ScriptIgnore]
    Gender Gender { get; set; }

    string GenderString { get { return Gender.ToString(); } }
}

La combinación de las respuestas de Omer Bokhari y uri siempre es mi solución, ya que los valores que deseo proporcionar son generalmente diferentes de los que tengo en mi enumeración, especialmente en el caso de que me gustaría poder cambiar mi enumeración si es necesario.

Así que si alguien está interesado, es algo como esto:

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

class Person
{
    int Age { get; set; }
    [JsonConverter(typeof(StringEnumConverter))]
    Gender Gender { get; set; }
}

He encontrado que Json.NET proporciona la funcionalidad exacta que estoy buscando con un atributo StringEnumConverter :

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

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

Más detalles disponibles en la documentación de StringEnumConverter .


ASP.NET Core forma:

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


Notó que no hay respuesta para la serialización cuando hay un atributo Descripción.

Aquí está mi implementación que soporta el atributo Descripción.

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

Enumerar

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

    // Will be serialized as "Applicable"
    Applicable
}

Uso:

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

Para el núcleo de ASP.Net, simplemente agregue lo siguiente a su Clase de inicio:

JsonConvert.DefaultSettings = (() =>
        {
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new StringEnumConverter { AllowIntegerValues = false });
            return settings;
        });

En caso de que alguien encuentre lo anterior insuficiente, terminé resolviéndome con esta sobrecarga:

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

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

También tuve que buscar una solución a este problema y, finalmente, me encontré con moment.js, que es una buena biblioteca que puede analizar este formato de fecha y muchos más.

var d = moment(yourdatestring)

Me ahorró un poco de dolor de cabeza, así que pensé que lo compartiría contigo. :)
Puede encontrar más información al respecto aquí: http://momentjs.com/







c# asp.net json enums javascriptserializer