21:17 0 0
Deserializar Json cuando tienes un Enum utilizando un convertidor personalizado en CSHARP

Deserializar Json cuando tienes un Enum utilizando un convertidor personalizado en CSHARP

  DrUalcman |  febrero 52022

No se a cuántos les ha pasado que tenemos un objeto que utiliza una enumeración para definir algun tipo de propiedad. Pero cuando lo almacenamos, no nos interesa almacenar su valor entero, si no su valor descriptivo. Yo utilizao mucho eso, sobre todo cuando ya conviero a JSON para ver, por ejemplo, el nivel del usuario como Manager, User y no como 1 o 2.

Bueno, en un principio esto no es un gran problema si trabajamos directamente con los objetos, pero si estamos utilizando System.Text.Json para serializar, nos va a mostrar el valor numérico, y cuando lo descerializamos toma desde ese valor numérico. Así que si nuestro JSON nos viene con el valor como una cadena de caracteres, ya que estamos mostrando Manager, pues la descerialización nos provoca un error, o directamente no puede descerializar el objeto.

Bien, hoy te traigo como solucionar este problema utilizando un convertidor personalizado o lo que es lo mismo en ingés un CustomConverter para que así podamos descerializar correctamente nuestros objetos, ya desa desde el valor numérico como por el valor literal.

Entremos en materia viendo un ejemplo

Tenemos dos enumeraciones y un objeto de usuario que utiliza dos propiedades con estas enumeraciones.

public enum UserDepartment
{
All,
CST,
Couriers,
Suppliers,
Packing,
Marketing,
Web,
Development,
Accountant
}

public enum UserView
{
Dashboard,
Customers,
Couriers,
Suppliers,
Reports,
Accountant,
Web
}

public class UserDemo
{
public string Name { get; set; }
public UserDepartment Department { get; set; }
public UserView Dashboard { get; set; }
}

Ahora vamos a crear una cadena de texto con el JSON que debe de crear el objeto UserDemo.

string jsonString = @"{""Name"":""Sergi"",""Department"":""Development"",""Dashboard"":4}";

Para que se vea mas claro el ejemplo, en una enumeracion he definidi su valor literal y en la segunda su valor numerico, por lo que prara la propiedad Dashboard el usuario esta definido como Reports.

Si intentamos ejecutar direcamente el descerializador desde esta cadena, nos va a arrojar una excepcion ya que no puede convertir Development en un entero. Para solucionar esto es donde entra en juego la posibilidad que nos brinda .NET de crear un JsonConverter.

Vamos con la solución

Para solucionar voy a hacer uso de la clase JsonConverterFactory que está en el espacio de nombres System.Text.Json.Serialization

public class CustomJsonStringEnumConverter : JsonConverterFactory
{
private readonly JsonStringEnumConverter baseConverter;

public CustomJsonStringEnumConverter(JsonNamingPolicy namingPolicy = null, bool allowIntegerValues = true)
{
baseConverter = new JsonStringEnumConverter(namingPolicy, allowIntegerValues);
}

public override bool CanConvert(Type typeToConvert) => baseConverter.CanConvert(typeToConvert);

public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
return baseConverter.CreateConverter(typeToConvert, options);
}
}

1. Primero estoy creando un constructor que puede recibir un par de paramétros de configuración. Pero son opcionales como se aprecia.

2. Hago uso del la calse JsonStringEnumConverter y hago una instancia pasánsole las posibles configuraciones. Esta clase nos el mismo espacio de nombres y es la que nos va a dar la posibilidad de convertir un Enum desde su valor o desde su nombre literal.

3. Luego implemento la clase abstracta y compruebo si la propiedad puede ser convertida o no.

3. Cuando no puede ser convertida directamente entonces es cuando invoicamos al convertidor de la clase JsonStringEnumConverter para que realice el trabajo.

Conclusiones

Listo, en internet podeis ver muchas mas opciones, y la verdad que algunas bastante elavoradas y complejas, pero tras hacer muchas pruebas esta es la mejor opcion y con menos código, ya que .NET 6 ya nos ofrece todas las herramientas necesarias. Creo que en .NET 5 deberia de funcionar, pero no lo he probado.

Espero que esto les ayude como siempre y or haga ahorrar tiempo. Yo invertí mas de 2 dias entre leer documentación, como siempre os dejo los enlaces más relevantes, y hacer mis pruebas.

Happy coding.

#CSHARP #utilidades #JSON

0 Comentarios

 
 
 

Archivo