es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

JsonConvert.DeserializeObject genera un error después de usar el resultado de JsonConvert.SerializeObject.

Cuando uso Newtonsoft.Json en C#, encuentro un problema como este

var dataDict = new Dictionary<string, List<double>>();

dataDict["$id"] = new List<double>() { 0.1, 0.9 };

var jsonStr = JsonConvert.SerializeObject(dataDict);

var back = JsonConvert.DeserializeObject<Dictionary<string, List<double>>>(jsonStr);

Entonces, aparece un error

Newtonsoft.Json.JsonSerializationException: ‘Token inesperado al deserializar el objeto: Float. Ruta ‘$id[0]’, línea 1, posición 11.’

Si quito el carácter “$”, funciona.

Reconozco que “$” es un token especial, mi pregunta es: si se puede SerializeObject, ¿por qué no se puede DeserializeObject?

¿Alguna solución alternativa aquí? ¡Cualquier consejo es bienvenido! Gracias.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Cuando se utiliza Newtonsoft.Json en C#, puede ocurrir el error “Token inesperado al deserializar objeto: Float” si la cadena JSON que se está deserializando contiene un token especial como “$”. En este caso, es posible serializar el objeto utilizando JsonConvert.SerializeObject() pero no deserializarlo usando JsonConvert.DeserializeObject().

    Para solucionar este problema, una solución es utilizar un JsonConverter personalizado para manejar el token especial durante la serialización y deserialización. A continuación se muestra un ejemplo de un JsonConverter personalizado que maneja el token “$”:

    public class CustomConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(Dictionary<string,></string,><double>>);
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var dataDict = (Dictionary<string,></string,><double>>)value;
    
            writer.WriteStartObject();
    
            foreach (var kvp in dataDict)
            {
                writer.WritePropertyName(kvp.Key.Replace("$", ""));
                serializer.Serialize(writer, kvp.Value);
            }
    
            writer.WriteEndObject();
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var dataDict = new Dictionary<string,></string,><double>>();
    
            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.PropertyName)
                {
                    var propName = ((string)reader.Value).Replace("$", "");
    
                    reader.Read();
    
                    var values = serializer.Deserialize<><double>>(reader);
    
                    dataDict[propName] = values;
                }
                else if (reader.TokenType == JsonToken.EndObject)
                {
                    break;
                }
            }
    
            return dataDict;
        }
    }
    

    Para utilizar este convertidor personalizado, simplemente páselo como parámetro a los métodos JsonConvert.SerializeObject() y JsonConvert.DeserializeObject():

    var dataDict = new Dictionary<string,></string,><double>>();
    
    dataDict["$id"] = new List<double>() { 0.1, 0.9 };
    
    var jsonStr = JsonConvert.SerializeObject(dataDict, new CustomConverter());
    
    var back = JsonConvert.DeserializeObject<><string,></string,><double>>>(jsonStr, new CustomConverter());
    

    Utilizando este convertidor personalizado, el token especial “$” se reemplaza por una cadena vacía durante la serialización y deserialización, lo que permite deserializar correctamente el objeto sin errores.

Comments are closed.