c# - enum - newtonsoft json serialize vb net
.NET-serialización JSON de enum como cadena (21)
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" }
@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
}
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
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í 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>
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())
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;
}
}
}
Esto se hace fácilmente agregando un atributo ScriptIgnore
a la propiedad Gender
, haciendo que no se GenderString
, y agregando una propiedad GenderString
que sí se serializa:
class Person
{
int Age { get; set; }
[ScriptIgnore]
Gender Gender { get; set; }
string GenderString { get { return Gender.ToString(); } }
}
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
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; }
}
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 .
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 .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;
});
Puede crear JsonSerializerSettings con la llamada a JsonConverter.SerializeObject como se muestra a continuación:
var result = JsonConvert.SerializeObject
(
dataObject,
new JsonSerializerSettings
{
Converters = new [] {new StringEnumConverter()}
}
);
Puede usar un JavaScriptConverter para lograr esto con el JavaScriptSerializer incorporado. Al convertir su enumeración a un Uri, puede codificarla como una cadena.
He descrito cómo hacer esto para las fechas, pero también se puede usar para las enumeraciones.
http://blog.calyptus.eu/seb/2011/12/custom-datetime-json-serialization/
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.
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]
);