Saltar al contenido

Newtonsoft.Json.JsonSerializationException (Error al obtener el valor de ‘Valor’ en ‘System.Data.SqlTypes.SqlDouble) serializando SqlGeography

Este team de especialistas despúes de ciertos días de investigación y recopilar de datos, han obtenido los datos necesarios, queremos que te sea de gran utilidad en tu proyecto.

Solución:

Parece que los tipos primitivos como SqlDouble de System.Data.SqlTypes Json.NET no puede serializarlos de inmediato porque no implementan sus propios TypeConverter. De los documentos:

Tipos primitivos

.Neto: TypeConverter (convertible a String)
JSON: cadena

Para ello será necesario implementar un personalizado JsonConverter para serializar estos tipos. Json.NET tiene varios convertidores integrados, como KeyValuePairConverter para los tipos .Net incorporados, por lo que esto no es inusual.

El hecho de que SqlBoolean, SqlBinary, SqlDouble y así sucesivamente, no comparten una clase base o interfaz común que no sea INullable requiere un código de aspecto duplicado:

public static class SqlPrimitiveConverters

    public static JsonSerializerSettings AddSqlConverters(this JsonSerializerSettings settings)
    
        foreach (var converter in converters)
            settings.Converters.Add(converter);
        return settings;
    

    static readonly JsonConverter[] converters = new JsonConverter[]
    
        new SqlBinaryConverter(),
        new SqlBooleanConverter(),
        new SqlByteConverter(),
        new SqlDateTimeConverter(),
        new SqlDecimalConverter(),
        new SqlDoubleConverter(),
        new SqlGuidConverter(),
        new SqlInt16Converter(),
        new SqlInt32Converter(),
        new SqlInt64Converter(),
        new SqlMoneyConverter(),
        new SqlSingleConverter(),
        new SqlStringConverter(),
        // TODO: converters for primitives from System.Data.SqlTypes that are classes not structs:
        // SqlBytes, SqlChars, SqlXml
        // Maybe SqlFileStream
    ;


abstract class SqlPrimitiveConverterBase : JsonConverter where T : struct, INullable, IComparable

    protected abstract object GetValue(T sqlValue);

    public override bool CanConvert(Type objectType)
    
        return typeof(T) == objectType;
    

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    
        T sqlValue = (T)value;
        if (sqlValue.IsNull)
            writer.WriteNull();
        else
        
            serializer.Serialize(writer, GetValue(sqlValue));
        
    


class SqlBinaryConverter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlBinary sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlBinary.Null;
        return (SqlBinary)serializer.Deserialize(reader);
    


class SqlBooleanConverter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlBoolean sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlBoolean.Null;
        return (SqlBoolean)serializer.Deserialize(reader);
    


class SqlByteConverter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlByte sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlByte.Null;
        return (SqlByte)serializer.Deserialize(reader);
    


class SqlDateTimeConverter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlDateTime sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlDateTime.Null;
        return (SqlDateTime)serializer.Deserialize(reader);
    


class SqlDecimalConverter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlDecimal sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlDecimal.Null;
        return (SqlDecimal)serializer.Deserialize(reader);
    


class SqlDoubleConverter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlDouble sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlDouble.Null;
        return (SqlDouble)serializer.Deserialize(reader);
    


class SqlGuidConverter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlGuid sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlGuid.Null;
        return (SqlGuid)serializer.Deserialize(reader);
    


class SqlInt16Converter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlInt16 sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlInt16.Null;
        return (SqlInt16)serializer.Deserialize(reader);
    


class SqlInt32Converter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlInt32 sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlInt32.Null;
        return (SqlInt32)serializer.Deserialize(reader);
    


class SqlInt64Converter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlInt64 sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlInt64.Null;
        return (SqlInt64)serializer.Deserialize(reader);
    


class SqlMoneyConverter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlMoney sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlMoney.Null;
        return (SqlMoney)serializer.Deserialize(reader);
    


class SqlSingleConverter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlSingle sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlSingle.Null;
        return (SqlSingle)serializer.Deserialize(reader);
    


class SqlStringConverter : SqlPrimitiveConverterBase

    protected override object GetValue(SqlString sqlValue)  return sqlValue.Value; 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
            return SqlString.Null;
        return (SqlString)serializer.Deserialize(reader);
    

Trabajo .Net violín bifurcado de los suyos.

Si necesita deserializar el JSON así creado, tiene dos problemas adicionales. En primer lugar, algunas de las propiedades de SqlGeography tal como Lat y Long son solo para obtener. Necesitará crear un personalizado JsonConverter para deserializar completamente este tipo.

En segundo lugar, Json.NET no tiene la capacidad de deserializar JSON con objetos complejos para valores de fila a un tipo sin tipo DataTable. Por lo tanto, si necesita deserializar JSON que contiene un objeto complejo (como su serializado SqlGeography), tiene las siguientes opciones:

  1. Crear y deserializar a un tipo DataTable.

  2. Usar DataTableConverter directamente para poblar un preexistente DataTable con columnas asignadas previamente, como se muestra aquí.

  3. Deserializar a una lista de DTOs como los siguientes:

    public class TableRowDTO
    
        [JsonConverter(typeof(SqlGeographyConverter))]
        public SqlGeography f1  get; set; 
        public int id  get; set; 
    
    

    Dónde SqlGeographyConverter es, según sea necesario, una costumbre JsonConverter por SqlGeography.

    Y luego haz:

    var settings = new JsonSerializerSettings().AddSqlConverters();
    var list = JsonConvert.DeserializeObject>(jsonString, settings);
    

Si te animas, tienes el poder dejar una noticia acerca de qué te ha gustado de este escrito.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *