web-dev-qa-db-fra.com

Json.NET, impossible de désérialiser le type nullable

J'essaie de convertir un objet JSON en objet C # à l'aide de Json.NET. L'objet ressemble à ceci en C #:

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

Mais lorsque j'exécute JsonConvert.DeserializeObject() sur le JSON entrant, j'obtiens l'exception suivante:

Impossible de trouver un constructeur qui utilise Pour le type System.Nullable`1 [System.Int32]. Une classe Doit avoir un constructeur par défaut Ou un seul constructeur Avec des arguments.

--- MODIFIER ----

Eh bien, il se trouve qu'après de nombreux tests, le problème se résume à ce que mon entrée pour mon JSON était comme suit:

{integerValue:{}, dateTimeValue: {} }

au lieu de:

{integerValue: null, dateTimeValue: null}

Il s’avère que le {} est un moyen valide de représenter un objet null en JSON, mais l’analyseur JSON.Net ne savait pas traiter les jetons {} de la même manière que "null" lors de la désérialisation.

Merci à tous pour votre contribution!

20
7wp

L'erreur vous indique qu'il est impossible de trouver un constructeur qu'il peut utiliser pour la désérialisation.

Essayez d'ajouter un constructeur par défaut à la classe:

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

        public MyObject(){}
    } 

Patrick.

--MODIFIER--

Je viens donc de créer une application console simple en utilisant votre MyObject, avec et sans constructeur par défaut, et je n’obtiens aucune erreur. Voici mon exemple:

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

Je n'ai aucune exception ...

Pouvez-vous montrer un exemple du JSON que vous essayez de désérialiser?

15
Patrick

La solution pour moi était de créer un convertisseur en fonction de cette réponse

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

Et que spécifier dans le modèle 

[JsonConverter(typeof(BoolConverter))]
public Boolean bold;
9
Kateryna Gridina

Je ne sais pas si c'est la bonne réponse ou non, mais au moins, vous pouvez créer un convertisseur personnalisé pour Nullable <>, cela m'aide beaucoup avec la sérialisation/désérialisation de DataRow. De plus, il n'a pas de constructeur par défaut. Voici échantillon

3
Sergey Mirvoda

Une version complète de la réponse @Patrick: 

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

Sortie:

?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
0
Serge