web-dev-qa-db-ja.com

Json.NETのJsonConvertクラスを使用して、逆シリアル化されたオブジェクトにフィールドがないかどうかを検出します

私はJson.NETを使用していくつかのJSONオブジェクトをデシリアライズしようとしています。しかし、プロパティを持たないオブジェクトを逆シリアル化すると、エラーがスローされず、プロパティにアクセスするとデフォルト値が返されることがわかりました。間違ったタイプのオブジェクトをデシリアライズしたときを検出できることが重要です。サンプルコード:

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

このプログラムの出力は次のとおりです。42 0

静かに失敗するよりも例外をスローする方がいいでしょう。それの手前に、シリアル化がパラメーターを見つけられなかったかどうかを検出する方法がありますか?

私はJsonオブジェクトでデータを解析し、キー値ルックアップでパラメータをチェックできることを知っていますが、私がいるコードベースは上記のパターンを使用し、可能な場合は一貫性を保ちたいと思います。

39
DubiousPusher

Json.NetシリアライザーにはMissingMemberHandling設定があり、Errorに設定できます。 (デフォルトはIgnoreです。)これにより、ターゲットクラスに対応するプロパティがないJSONプロパティが検出されると、デシリアライズ中にシリアライザーがJsonSerializationExceptionをスローします。

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

結果:

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

参照: MissingMemberHandling設定

48
Brian Rogers

必要なプロパティに[JsonProperty(Required = Required.Always)]を追加するだけで、逆シリアル化中にプロパティが存在しない場合は例外がスローされます。

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

必要なプロパティに次の属性を設定します。

[DataMember(IsRequired = true)]

メンバーが存在しない場合、Newtonsoft.Json.JsonSerializationExceptionがスローされます。

以下にブライアンが提案したように、クラスにもこの属性が必要です。

[DataContract]
3
Adam Modlin

定義クラスのメンバーを疑問符「?」で定義するだけです。 int?

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

初期化されていない場合は、単にnullになります。それ以外の場合は、有効な値になります。これにより、設定をオプションにし、設定ごとに評価することができます。

2
isgoed