2010-01-28 41 views
14

Estoy tratando de convertir JSON en objeto C# utilizando Json.NET. El objeto se parece a esto en C#:Json.NET, no se puede deserializar tipo nulable

public class MyObject 
{ 
    public int? integerValue {get;set;} 
    public DateTime? dateTimeValue {get;set;} 
} 

Pero cuando corro JsonConvert.DeserializeObject() en el JSON entrante, me sale el siguiente excepción:

incapaz de encontrar un constructor de usar para el tipo sistema. Nullable`1 [System.Int32]. Una clase debe tener un constructor predeterminado o solo un constructor con argumentos.

--- ---- EDITAR

Pues resulta que después de hacer muchas pruebas, el problema se reduce a que mi entrada para mi JSON fue así:

{integerValue:{}, dateTimeValue: {} } 

en lugar de:

{integerValue: null, dateTimeValue: null} 

resulta que el {} es una forma válida de representar un objeto nulo en JSON, pero el analizador JSON.Net no sabía para tratar a {} kens de la misma manera que 'null' cuando se deserializa.

¡Gracias a todos por su colaboración!

+0

¿Puedes agregar el JSON que intentas deserializar? – Amy

+0

Sí. ver mi edición :) – 7wp

+0

Tuve el mismo problema, excepto {value: "null"} en lugar de {value: null}. – craastad

Respuesta

13

El error le indica que no puede encontrar un constructor que pueda usar para la deserialización.

trate de añadir un constructor por defecto a la clase:

public class MyObject 
    { 
     public int? integerValue { get; set; } 
     public DateTime? dateTimeValue { get; set; } 

     public MyObject(){} 
    } 

Patrick.

--EDIT--

Así que acaba de crear una aplicación de consola sencilla de utilizar su MiObjeto, con y sin un constructor por defecto y me estoy poniendo ningún error. Aquí está mi ejemplo:

class Program 
    { 
     static void Main(string[] args) 
     { 
      var mo = new MyObject { integerValue = null, dateTimeValue = null }; 
      var ser = Newtonsoft.Json.JsonConvert.SerializeObject(mo); 
      var deser = Newtonsoft.Json.JsonConvert.DeserializeObject(ser, typeof(MyObject)); 
     } 
    } 

    public class MyObject 
    { 
     public int? integerValue { get; set; } 
     public DateTime? dateTimeValue { get; set; }   
    } 

llego sin excepciones ...

puedo mostrar un ejemplo de la JSON que intenta deserializar?

+1

Disculpe, Sergey, ya lo he comentado sobre el constructor predeterminado ... – Patrick

+1

Patrick, no creo que sea tan simple como eso. El error no es que no haya un constructor predeterminado para MyObject. El error es decir que no hay un constructor predeterminado para el tipo System.Nullable! Cada clase definida por el usuario obtiene un constructor implícito predeterminado sin parámetros por el compilador. A menos que el constructor esté marcado como privado. – 7wp

+0

Tiene razón, el constructor sin parámetros es agregado por el compilador - Pero he tenido muchas instancias en el pasado al desarrollar servicios REST de WCF (XML y JSON) donde obtendría las ediciones de serialización si no agregué específicamente un constructor sin parámetros. Entonces, en teoría, lo que dices debería funcionar, pero en la práctica, he tenido una experiencia diferente. Voy a tratar de configurar un proyecto con las mismas herramientas que tiene que ver si se me ocurre una mejor opción. – Patrick

3

No sé si es la respuesta correcta o no, pero al menos Usted puede crear un convertidor personalizado para Nullable <>, me ayuda mucho con la serialización/deserialización de DataRow que tampoco tiene un constructor predeterminado. Aquí está sample

+0

Sergey. Gracias por ayudar. Pero resulta que el problema fue algo diferente. Ver mis ediciones en mi pregunta publicada. – 7wp

6

La solución para mí fue la creación de convertidor de acuerdo con this answer

public class BoolConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     writer.WriteValue(((bool)value) ? 1 : 0); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.Value == null || reader.Value.ToString() == "False") 
     { 
      return false; 
     } 
     return true; 
    } 

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

Y que especifique en el modelo

[JsonConverter(typeof(BoolConverter))] 
public Boolean bold; 
0

Una versión de la respuesta @Patrick completado:

static void Main(string[] args) 
{ 
    var mo = new MyObject(); 
    var ser = Newtonsoft.Json.JsonConvert.SerializeObject(mo); 
    var myStr = "{}"; 
    var myStr1 = "{tITi: 10}"; 
    var myStr2 = "{integerValue: 10}"; 
    var deser0 = Newtonsoft.Json.JsonConvert.DeserializeObject(ser, typeof(MyObject)); 
    var deser1 = Newtonsoft.Json.JsonConvert.DeserializeObject(myStr, typeof(MyObject)); 
    var deser2 = Newtonsoft.Json.JsonConvert.DeserializeObject(myStr1, typeof(MyObject)); 
    var deser3 = Newtonsoft.Json.JsonConvert.DeserializeObject(myStr2, typeof(MyObject)); 
} 

public class MyObject 
{ 
    public int? integerValue { get; set; } 
    public DateTime? dateTimeValue { get; set; } 
    public int toto { get; set; } = 5; 
    public int Titi; 
} 

Salida:

?deser0 
{ConsoleApplication1.MyObject} 
    Titi: 0 
    dateTimeValue: null 
    integerValue: null 
    toto: 5 
?deser1 
{ConsoleApplication1.MyObject} 
    Titi: 0 
    dateTimeValue: null 
    integerValue: null 
    toto: 5 
?deser2 
{ConsoleApplication1.MyObject} 
    Titi: 10 
    dateTimeValue: null 
    integerValue: null 
    toto: 5 
?deser3 
{ConsoleApplication1.MyObject} 
    Titi: 0 
    dateTimeValue: null 
    integerValue: 10 
    toto: 5 
Cuestiones relacionadas