c# - serialize - stringenumconverter




.NET-serialización JSON de enum como cadena (14)

@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
}

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

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


Aquí está la respuesta para newtonsoft.json

enum Gender { Male, Female }

class Person
{
    int Age { get; set; }

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

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>

Esta es una pregunta antigua, pero pensé que contribuiría por si acaso. En mis proyectos utilizo modelos separados para cualquier solicitud de Json. Un modelo normalmente tendría el mismo nombre que el objeto de dominio con el prefijo "Json". Los modelos se mapean utilizando AutoMapper . Al hacer que el modelo json declare una propiedad de cadena que es una enumeración en la clase de dominio, AutoMapper se resolverá en su presentación de cadena.

En caso de que se lo pregunte, necesito modelos separados para las clases serializadas Json porque el serializador incorporado viene con referencias circulares de lo contrario.

Espero que esto ayude a alguien.


Esta versión de la answer de Stephen no cambia el nombre en el 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; 
        }
    }
}

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 .


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


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://.com/a/2870420/237091 y @ Iggy's https://.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()
        }
    })

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 .


Para .Net Core Web Api: -

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

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


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.





javascriptserializer