web-dev-qa-db-fra.com

Détecter si un objet désérialisé manque un champ avec la classe JsonConvert dans Json.NET

J'essaie de désérialiser certains objets JSON à l'aide de Json.NET. J'ai cependant constaté que lorsque je désérialise un objet qui n'a pas les propriétés que je recherche, aucune erreur n'est renvoyée, mais une valeur par défaut est renvoyée pour les propriétés lorsque j'y accède. Il est important que je puisse détecter quand j'ai désérialisé le mauvais type d'objet. Exemple de code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Json_Fail_Test
{
    class Program
    {
        [JsonObject(MemberSerialization.OptOut)]
        private class MyJsonObjView
        {
            [JsonProperty("MyJsonInt")]
            public int MyJsonInt { get; set; }
        }

        const string correctData = @"
        {
            'MyJsonInt': 42
        }";

        const string wrongData = @"
        {
            'SomeOtherProperty': 'fbe8c20b'
        }";

        static void Main(string[] args)
        {
            var goodObj = JsonConvert.DeserializeObject<MyJsonObjView>(correctData);
            System.Console.Out.WriteLine(goodObj.MyJsonInt.ToString());

            var badObj = JsonConvert.DeserializeObject<MyJsonObjView>(wrongData);
            System.Console.Out.WriteLine(badObj.MyJsonInt.ToString());
        }
    }
}

Le résultat de ce programme est: 42 0

Je préférerais qu'une exception soit levée à l'échec silencieux. Autrement, existe-t-il un moyen de détecter si la sérialisation n'a pas réussi à trouver un paramètre?

Je sais que je peux analyser les données avec un objet Json, puis vérifier le paramètre avec une recherche de valeur clé, mais la base de code dans laquelle j'utilise utilise le modèle ci-dessus et j'aimerais garder cela cohérent si c'est possible.

39
DubiousPusher

Le sérialiseur Json.Net a un paramètre MissingMemberHandling que vous pouvez définir sur Error. (La valeur par défaut est Ignore.) Cela entraînera le sérialiseur à lancer un JsonSerializationException pendant la désérialisation chaque fois qu'il rencontre une propriété JSON pour laquelle il n'y a pas de propriété correspondante dans la classe cible.

static void Main(string[] args)
{
    try
    {
        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.MissingMemberHandling = MissingMemberHandling.Error;

        var goodObj = JsonConvert.DeserializeObject<MyJsonObjView>(correctData, settings);
        System.Console.Out.WriteLine(goodObj.MyJsonInt.ToString());

        var badObj = JsonConvert.DeserializeObject<MyJsonObjView>(wrongData, settings);
        System.Console.Out.WriteLine(badObj.MyJsonInt.ToString());
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.GetType().Name + ": " + ex.Message);
    }
}

Résultat:

42
JsonSerializationException: Could not find member 'SomeOtherProperty' on object
of type 'MyJsonObjView'. Path 'SomeOtherProperty', line 3, position 33.

Voir: paramètre MissingMemberHandling .

48
Brian Rogers

Ajoutez simplement [JsonProperty(Required = Required.Always)] aux propriétés requises et cela lèvera une exception si la propriété n'est pas là pendant la désérialisation.

[JsonProperty(Required = Required.Always)]
 public int MyJsonInt { get; set; }
11
JerryGoyal

Mettez l'attribut suivant sur les propriétés requises:

[DataMember(IsRequired = true)]

Si le membre n'est pas présent, il lèvera une exception Newtonsoft.Json.JsonSerializationException.

Comme Brian l'a suggéré ci-dessous, vous aurez également besoin de cet attribut dans votre classe:

[DataContract]
3
Adam Modlin

Définissez simplement vos membres dans votre classe de définition avec un point d'interrogation '?' int?:

private class MyJsonObjView
{
    [JsonProperty("MyJsonInt")]
    public int? MyJsonInt { get; set; }
}

Lorsqu'il n'est pas initialisé, ce sera simplement null, sinon ce sera une valeur valide. Cela vous permet d'avoir des paramètres facultatifs et de les évaluer par paramètre.

2
isgoed