JavaScriptSerializer: serialización JSON de enumeración como cadena
Frecuentes
Visto 527,712 veces
1232
Tengo una clase que contiene un enum
propiedad, y al serializar el objeto usando JavaScriptSerializer
, mi resultado json contiene el valor entero de la enumeración en lugar de su string
"nombre". ¿Hay alguna forma de obtener la enumeración como string
en mi json sin tener que crear un personalizado JavaScriptConverter
? Quizás hay un atributo que podría decorar el enum
definición, o propiedad del objeto, con?
Como un ejemplo:
enum Gender { Male, Female }
class Person
{
int Age { get; set; }
Gender Gender { get; set; }
}
Resultado deseado de json:
{ "Age": 35, "Gender": "Male" }
Lo ideal es buscar una respuesta con clases de marco .NET integradas, si no es posible, las alternativas (como Json.net) son bienvenidas.
27 Respuestas
425
No, no hay ningún atributo especial que pueda utilizar. JavaScriptSerializer
serializa enums
a sus valores numéricos y no a su representación de cadena. Debería utilizar la serialización personalizada para serializar el enum
como su nombre en lugar de valor numérico.
Si puede usar JSON.Net en lugar de JavaScriptSerializer
que ver responder a esta pregunta proporcionada por 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 integrados. Aquí hay un enlace que compara características y funcionalidades de los serializadores..
Respondido el 25 de Septiembre de 19 a las 22:09
@Fabzter - su solución funcionó conmigo usando Newtonsoft's Json - BeemerGuy
@BornToCode Json.NET es el serializador que ASP.NET usa por defecto. - BrainSlugs83
@ BrainSlugs83: la pregunta era sobre el uso de JavaScriptSerializer, no Json.NET (y si observa el historial de revisiones, verá que hubo una edición para aclarar eso), si usa JavaScriptSerializer el atributo JsonConverter
no va a funcionar. - BornToCode
¿Podrías responderme? Yongqiang Chen
"Json.NET es el serializador que ASP.NET usa por defecto" - Esto no era cierto cuando se hizo o respondió la pregunta. (pero lo más importante es la claridad de la respuesta) - Ryanwebjackson
2169
He encontrado que Json.NET proporciona la funcionalidad exacta que estoy buscando con un StringEnumConverter
atributo:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
[JsonConverter(typeof(StringEnumConverter))]
public Gender Gender { get; set; }
Más detalles en disponible en StringEnumConverter
documentación.
Hay otros lugares para configurar este convertidor de manera más global:
enum en sí mismo si desea que enum siempre se serialice / deserialice como cadena:
[JsonConverter(typeof(StringEnumConverter))] enum Gender { Male, Female }
En caso de que alguien quiera evitar la decoración de atributos, puede agregar el convertidor a su JsonSerializer (sugerido por Bjorn Egil):
serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
y funcionará para cada enumeración que vea durante esa serialización (sugerida por Travis).
o JsonConverter (sugerido por plátano):
JsonConvert.SerializeObject(MyObject, new Newtonsoft.Json.Converters.StringEnumConverter());
Además, puede controlar el uso de mayúsculas y minúsculas y si los números aún se aceptan utilizando StringEnumConverter (NamingStrategy, Boolean) constructor.
Respondido el 25 de Septiembre de 19 a las 22:09
Siga el enlace para obtener una descripción de cómo usarlo en la aplicación asp.net mvc james.newtonking.com/archive/2008/10/16/… - rredcat
Aquí está el enlace a esa función: james.newtonking.com/projects/json/help/html/… - Tipo CAD
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
Es útil tener en cuenta que, por defecto, ASP.NET MVC no usa Json.Net como serializador json y es necesario extender Controller
o anular manualmente cada serialización. - odys
Puede personalizar el convertidor (por ejemplo, para camelCase
producción): new StringEnumConverter { CamelCaseText = true }
- Pescado de mar
176
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());
Respondido 09 ago 13, 19:08
Por alguna razón, no estoy logrando que esto funcione. Fiddler muestra un 2 terco en lugar de 'Advertencia', incluso con esto en su lugar. Además, cualquier motivo para cambiar el Formatting
a Indented
? - sq33G
La tercera línea de este ejemplo se agregó al archivo App_start / webapiconfig.cs y me hizo un truco en un proyecto ASP.NET Web API 2.1 para devolver cadenas para valores de enumeración en llamadas REST (json fomat). - greg z
¿Hay alguna forma de establecer esta propiedad solo por el alcance de la solicitud? - Anestis Kivranoglou
@AnestisKivranoglou solo usa un serializador json personalizado por solicitud con su propia configuración. - BrainSlugs83
la primera configuración de serializador de sangría no está relacionada con la pregunta op. - user3791372
160
@Iggy answer establece la serialización JSON de c # enum como una cadena solo para ASP.NET (API web, etc.).
Pero para que funcione también con la serialización ad hoc, agregue lo 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 Json.NET
Además, para que su miembro enum serialice / deserialice hacia / desde un texto específico, use el
System.Runtime.Serialization.EnumMember
atributo, como este:
public enum time_zone_enum
{
[EnumMember(Value = "Europe/London")]
EuropeLondon,
[EnumMember(Value = "US/Alaska")]
USAlaska
}
respondido 24 nov., 14:11
¡Gracias! Solo estaba buscando [EnumMember]
. - Poulad
La CamelCaseText
la propiedad ahora está marcada como obsoleta. Nueva forma de instanciar el convertidor: new StringEnumConverter(new CamelCaseNamingStrategy())
- hágase
Muchas gracias, me alegró el día! :) - Eldoïr
el JsonConvert que coloca en ConfigureServices o en Configure en NET CORE 2? - desarrollador learn999
43
No pude cambiar el modelo de origen como en la respuesta principal (de @ob.), Y no quería registrarlo globalmente como @Iggy. Así que combiné https://stackoverflow.com/a/2870420/237091 y @ Iggy https://stackoverflow.com/a/18152942/237091 para permitir la configuración del convertidor de enumeración de cadenas durante el comando SerializeObject en sí:
Newtonsoft.Json.JsonConvert.SerializeObject(
objectToSerialize,
Newtonsoft.Json.Formatting.None,
new Newtonsoft.Json.JsonSerializerSettings()
{
Converters = new List<Newtonsoft.Json.JsonConverter> {
new Newtonsoft.Json.Converters.StringEnumConverter()
}
})
contestado el 23 de mayo de 17 a las 12:05
esto también funciona bien si tiene una propiedad como esta Lista - Bogdan
Como mencionó @Bogdan, esta fue la solución para que yo hiciera un List<AnEnumType>
propiedad serializar con el valor de cadena de cada valor Enum en lugar del valor numérico. - Juan Washam
37
La combinación de las respuestas de Omer Bokhari y uri es siempre mi solución, ya que los valores que quiero proporcionar suelen ser diferentes de los que tengo en mi enumeración, especialmente porque me gustaría poder cambiar mis enumeraciones si es necesario.
Entonces, 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; }
}
Respondido 16 ago 17, 11:08
Estaba usando JsonPropertyAttribute
para miembros de enumeración y funciona para tareas de deserialización simples. Lamentablemente, durante los ajustes manuales con JToken
s se ignora. Felizmente EnumMemberAttribute
Funciona de maravilla. ¡Gracias! - Prólogo
31
Esto se hace fácilmente agregando un ScriptIgnore
atribuir a la Gender
propiedad, lo que hace que no se serialice y agregue un GenderString
propiedad que sí ser serializado:
class Person
{
int Age { get; set; }
[ScriptIgnore]
Gender Gender { get; set; }
string GenderString { get { return Gender.ToString(); } }
}
Respondido 21 Feb 18, 13:02
Déjame intentar explicar. Esta solución no es correcta según los paters de diseño. Modificó el modelo de acuerdo con el propósito de la vista. Pero el modelo solo tiene que contener datos y no se preocupan por las presentaciones. Tienes que mover esta funcionalidad a la otra capa. - rredcat
En realidad, Model se usa para pasar datos del controlador, y es el controlador, al que no le importa la presentación. La introducción de la propiedad automatizada (GenderString aquí) no interrumpe el controlador, que todavía usa la propiedad de género, pero proporciona un acceso fácil para una vista. Solución lógica. - Dima
@RredCat No hay nada de malo en tener propiedades específicas de vista en el "modelo de vista". En mi humilde opinión, el error sería no dividir el modelo de vista del modelo de dominio: blogs.msdn.com/b/simonince/archive/2010/01/26/… - mariano desanze
@RredCat, incluso si fuera incorrecto de acuerdo con algún patrón, el OP no dice nada al respecto, por lo que esta es una respuesta correcta. (Incluso si filosóficamente estoy de acuerdo con tu punto). MEMARCA
El desprendimiento de bicicletas pedante y absurdo en este hilo de comentarios es fascinante. - mike mooney
28
Forma de 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
Respondido el 19 de junio de 18 a las 09:06
27
Esta versión de Stephen https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be 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;
}
}
}
contestado el 23 de mayo de 17 a las 12:05
Creo que esto es válido para el DataContractJsonSerializer
no JavaScriptSerializer
- KCD
Simple y me resuelve el problema usando serializadores nativos de .NET Framework. - El senador
la mejor solución para mí, ya que no puedo usar bibliotecas de terceros (problemas de cumplimiento de ISO) - Daniel Gruszczyk
Por supuesto, esto no es para el tipo de serializador en cuestión. JavaScriptSerializer serializa todo lo que no se ignora, mientras que DataContractJsonSerializer requiere atributos DataMember. Gracias por el saludo, pero tenga en cuenta que ha escrito mal mi nombre :) - Stephen Kennedy
25
Aquí está la respuesta para newtonsoft.json
enum Gender { Male, Female }
class Person
{
int Age { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
Gender Gender { get; set; }
}
Respondido 21 Abr '15, 10:04
Gracias por esta respuesta, ¡me ayudó mucho! Si desea definir sus enumeraciones en PascalCase, pero desea que se serialice en camelCase, debe agregar true
a su tipo JsonConverter de esta manera: [JsonConverter(typeof(StringEnumConverter), true)]
- Peet
23
En .net core 3 esto ahora es posible con las clases integradas en System.Text.Json (editar: System.Text.Json también está disponible como paquete NuGet para .net core 2.0 y .net framework 4.7.2 y versiones posteriores de acuerdo con la documentos):
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);
Para configurar JsonStringEnumConverter
con decoración de atributos para la propiedad específica:
using System.Text.Json.Serialization;
[JsonConverter(typeof(JsonStringEnumConverter))]
public Gender Gender { get; set; }
Si desea convertir siempre la enumeración como cadena, coloque el atributo en la enumeración.
[JsonConverter(typeof(JsonStringEnumConverter))]
enum Gender { Male, Female }
Respondido el 14 de Septiembre de 20 a las 13:09
17
También puede agregar un convertidor a su JsonSerializer
si no quieres usar JsonConverter
atributo:
string SerializedResponse = JsonConvert.SerializeObject(
objToSerialize,
new Newtonsoft.Json.Converters.StringEnumConverter()
);
Funcionará para todos enum
ve durante esa serialización.
Respondido 13 Jul 16, 14:07
16
Asp.Net Core 3 con System.Text.Json
public void ConfigureServices(IServiceCollection services)
{
services
.AddControllers()
.AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())
);
//...
}
respondido 11 nov., 19:00
15
Aquí hay una solución simple que serializa una enumeración C # del lado del servidor en JSON y usa el resultado para completar una enumeración del lado del cliente <select>
elemento. 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 # en JSON probablemente también la usarán para completar una <select>
desplegable.
Aquí va:
Ejemplo de enumeración
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 bit a bit para generar un sistema de permisos. Entonces 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 usa el marco NancyFX para manejar la solicitud Get. Utiliza el de Nancy Response.AsJson()
método auxiliar, 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>
Respondido el 22 de Septiembre de 14 a las 15:09
15
Para ASP.Net core Simplemente agregue lo siguiente a su Clase de inicio:
JsonConvert.DefaultSettings = (() =>
{
var settings = new JsonSerializerSettings();
settings.Converters.Add(new StringEnumConverter { AllowIntegerValues = false });
return settings;
});
Respondido 17 Oct 18, 06:10
12
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()}
}
);
Respondido el 17 de junio de 15 a las 13:06
10
Se dio cuenta de que no hay respuesta para la serialización cuando hay un atributo Descripción.
Aquí está mi implementación que admite 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");
}
}
enumeración:
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; }
respondido 05 mar '16, 08:03
10
Para .Net Core: -
public void ConfigureServices(IServiceCollection services)
{
...
services.AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));
...
}
Respondido el 04 de Septiembre de 19 a las 22:09
Si este es el de la Microsoft.AspNetCore.Mvc.Formatters.Json
Paquete NuGet, parece ser solo un método de extensión en IMvcCoreBuilder
no, IMvcBuilder
. Entonces se usa como services.AddMvcCore().AddJsonFormatters(f => f.Converters.Add(new StringEnumConverter()));
. - infl3x
8
En caso de que alguien considere que lo anterior es insuficiente, terminé conformándome con esta sobrecarga:
JsonConvert.SerializeObject(objToSerialize, Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter())
Respondido el 27 de junio de 16 a las 09:06
Esta es una buena solución para un caso de uso actual mío: no quiero cambiar los valores predeterminados de los serializadores y tengo problemas para usar atributos, porque mis propiedades son de tipo IList . - dirk brockhaus
5
Esta es una vieja pregunta, pero pensé en contribuir por si acaso. En mis proyectos, uso 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 usando AutoMapper. Al hacer que el modelo json declare una propiedad de cadena que es una enumeración en la clase de dominio, AutoMapper resolverá su presentación de cadena.
En caso de que se lo pregunte, necesito modelos separados para las clases serializadas de Json porque, de lo contrario, el serializador incorporado tiene referencias circulares.
Espero que esto ayude a alguien.
respondido 27 mar '12, 16:03
Es bueno saber que la característica de Automapper ;-) El atributo [ScriptIgnore] eliminará las referencias circulares - dragón led
Oh. No sabía nada del atributo. ¡Gracias! ¿Usarías eso en tus Pocos? He recurrido al uso de definiciones de MetadataType para cualquier atributo de Poco solo para mantenerlos limpios. ¿Seguiría funcionando el atributo a través de metadatos? - Ales Potocnik Hahonina
3
De hecho, puede usar un JavaScriptConverter para lograr esto con el JavaScriptSerializer incorporado. Al convertir su enumeración en un Uri, puede codificarlo como una cadena.
Describí cómo hacer esto para las fechas, pero también se puede usar para enumeraciones. Formato JSON de fecha y hora personalizado para .NET JavaScriptSerializer.
Respondido 19 ago 19, 14:08
¡Solución muy interesante! Gracias por compartir. - Oliver
1
No estoy seguro de si esto sigue siendo relevante, pero tuve que escribir directamente en un archivo json y se me ocurrió lo siguiente juntando varias respuestas de stackoverflow.
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);
}
}
}
Asegura que todas mis claves json están en minúsculas comenzando de acuerdo con las "reglas" de json. Formatea con sangría limpia e ignora los nulos en la salida. Además, al agregar un StringEnumConverter, imprime enumeraciones con su valor de cadena.
Personalmente, encuentro que esto es lo más limpio que se me ocurrió, sin tener que ensuciar el modelo con anotaciones.
uso:
internal void SaveJson(string fileName)
{
// serialize JSON directly to a file
using (StreamWriter file = File.CreateText(@fileName))
{
LowercaseJsonSerializer.Serialize(file, jsonobject);
}
}
Respondido el 19 de diciembre de 18 a las 08:12
1
Y para VB.net encontré los siguientes trabajos:
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)
contestado el 15 de mayo de 19 a las 22:05
0
He reunido todas las piezas de esta solución usando el Newtonsoft.Json
Biblioteca. Soluciona el problema de la enumeración y también hace que el manejo de errores sea mucho mejor, y funciona en 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
Tienes que agregar algunas entradas a tu Web.config
para que funcione, puede ver un archivo de ejemplo aquí:
https://github.com/jongrant/wcfjsonserializer/blob/master/Web.config
Respondido 12 Jul 16, 11:07
0
Una opción un poco más preparada para el futuro
Ante la misma pregunta, determinamos que necesitábamos una versión personalizada de StringEnumConverter
para asegurarnos de que nuestros valores de enumeración puedan expandirse con el tiempo sin romperse catastróficamente en el lado de la deserialización (consulte los antecedentes a continuación). Utilizando la SafeEnumConverter
a continuación permite que finalice la deserialización incluso si la carga útil contiene un valor para la enumeración que no tiene una definición con nombre, más cerca de cómo funcionaría la conversión de int-a-enum.
Uso:
[SafeEnumConverter]
public enum Colors
{
Red,
Green,
Blue,
Unsupported = -1
}
or
[SafeEnumConverter((int) Colors.Blue)]
public enum Colors
{
Red,
Green,
Blue
}
Fuente:
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;
}
}
Antecedentes
Cuando miramos el uso de StringEnumConverter
, el problema que teníamos es que también necesitábamos pasividad para los casos en los que se agregaba un nuevo valor de enumeración, pero no todos los clientes eran conscientes de inmediato del nuevo valor. En estos casos, el StringEnumConverter
empaquetado con Newtonsoft JSON arroja un JsonSerializationException
similar a "Error al convertir el valor SomeString para escribir EnumType" y luego el todo El proceso de deserialización falla. Esto fue un factor decisivo para nosotros, porque incluso si el cliente planeaba ignorar / descartar el valor de la propiedad que no entendía, ¡aún tenía que ser capaz de deserializar el resto de la carga útil!
Respondido 06 ago 19, 19:08
Todavía es relativamente nuevo en .NET, pero me han dicho que evite las expresiones de captura de prueba por razones de rendimiento. ¿No sería un serializador un mal lugar para usar uno si ese es el caso? - laventnc
@laventnc El try ... catch en sí mismo no afectará el rendimiento, pero si se genera una excepción, hay una sobrecarga de rendimiento para eso. El objetivo de esta implementación es la tolerancia a fallas ... no permitir que un solo valor de enumeración desconocido evite que se deserialice toda la carga útil JSON. Compara la base StringEnumConveter
: la excepción aún se generaría, pero hará que todo el proceso de deserialización falle (y es probable que quede atrapado en algún lugar más arriba de la pila). Si necesita este tipo de tolerancia a fallas es un artefacto de su (s) caso (s) de uso. - Polvoriento
-4
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();
Respondido el 26 de diciembre de 19 a las 03:12
-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]
);
Respondido 19 Abr '16, 16:04
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c# asp.net json enums javascriptserializer or haz tu propia pregunta.
¿Cambiar a cuál? La respuesta más votada a favor no responde a la pregunta: sí, es útil en otros contextos, de ahí los votos, pero no tiene ningún uso práctico si está atascado con MS JavaScriptSerializer, ya que esencialmente lo está si usa métodos de página y , lo más importante, como lo requiere la pregunta. La respuesta aceptada dice que no es posible. Mi respuesta, mientras que un poco de truco hace el trabajo. - Stephen Kennedy