2010-01-28 14 views
14

Sto provando a convertire JSON in oggetto C# utilizzando Json.NET. L'oggetto si presenta come questo in C#:Json.NET, Impossibile declassificare il tipo nullable

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

Ma quando ho eseguito JsonConvert.DeserializeObject() sul JSON in entrata, ottengo la seguente eccezione:

in grado di trovare un costruttore di utilizzare per il tipo sistema. Nullable`1 [System.Int32]. Una classe deve avere un costruttore predefinito o un solo costruttore con argomenti.

--- EDIT ----

Ebbene si scopre che dopo aver fatto molti test, il problema si riduce a che il mio ingresso per la mia JSON era come questo:

{integerValue:{}, dateTimeValue: {} } 

invece di:

{integerValue: null, dateTimeValue: null} 

Si scopre che il {} è un modo valido di rappresentare un oggetto nullo in JSON, ma il parser JSON.Net non sapeva per il trattamento {} per kens allo stesso modo di 'null' durante la de-serializzazione.

Grazie a tutti per il vostro contributo!

+0

Puoi aggiungere il JSON si sta cercando di deserializzare? – Amy

+0

Sì. vedere la mia modifica :) – 7wp

+0

Ho avuto lo stesso problema, tranne {valore: "null"} invece di {valore: null}. – craastad

risposta

13

L'errore sta dicendo che non è possibile trovare un costruttore che possa utilizzare per la deserializzazione.

provare ad aggiungere un costruttore predefinito alla classe:

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

     public MyObject(){} 
    } 

Patrick.

--EDIT--

Così ho appena creato una semplice applicazione console utilizzando il vostro MyObject, con e senza un costruttore di default e sto ottenendo nessun errore. Ecco il mio esempio:

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; }   
    } 

ottengo non si smentisce mai ...

si può mostrare un esempio di JSON che si sta tentando di deserializzare?

+1

Mi dispiace Sergey, vedo che hai già commentato il costruttore predefinito ... – Patrick

+1

Patrick, non penso sia così semplice. L'errore non è che non esiste un costruttore predefinito per MyObject. L'errore sta dicendo che non esiste un costruttore predefinito per il tipo System.Nullable! Ogni classe definita dall'utente ottiene dal compilatore un costruttore implicito senza parametri predefinito. A meno che il costruttore non sia contrassegnato come privato. – 7wp

+0

Hai ragione, il costruttore parametrico è stato aggiunto dal compilatore - Ma in passato ho avuto molte istanze nello sviluppo di servizi REST di WCF (XML e JSON) in cui avrei ricevuto la serializzazione se non aggiungessi specificamente un costruttore senza parametri. Quindi, in teoria, quello che dici dovrebbe funzionare ma, in pratica, ho avuto un'esperienza diversa. Proverò a impostare un progetto utilizzando gli stessi strumenti che devi vedere se riesco a trovare un'opzione migliore. – Patrick

3

Non so è la risposta giusta o meno, ma almeno è possibile creare un convertitore personalizzato per Nullable <>, mi aiuta molto con DataRow serializzazione/deserializzazione anche non ha costruttore predefinito. Ecco sample

+0

Sergey. Grazie dell'aiuto. Ma si scopre che il problema era qualcosa di diverso. Vedi le mie modifiche nella mia domanda postata. – 7wp

6

La soluzione per me era quella di creare Convertitore come da 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); 
    } 
} 

E di specificare nel modello

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

Una versione della risposta @Patrick completato:

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; 
} 

Uscita:

?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 
Problemi correlati