Newtonsoft.Jsonでnullをnull非許容型にデシリアライズしたらどうなるのか実験してみる[C#][nuget]

2023-03-14

Newtonsoft.Jsonはnullをデシリアライズできます。ただ、そのnullの格納先がnull型を許容していなかったら?エラーになるのか、問題ない形に置き換わるのか、調べてみました。

実験用のコード

using Newtonsoft.Json;
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;

namespace JsonSample
{
    class Program
    {
        static void Main()
        {
            List<Person> person = new List<Person>();

            using (var reader = new StreamReader(@"C:\jikken\jikken.json",
                Encoding.GetEncoding("utf-8")))
            {
                person = JsonConvert.DeserializeObject<List<Person>>(reader.ReadToEnd());
            }

        }

        public class Person
        {
            public int _id { get; set; }
        }
    }
}
JSON処理用のライブラリについて検証してみる。
mikan-tech.info

上の記事で使用したコードとほぼ同じです。25行目の型を今回は変えていきます。

[
  {
    "_id": null
  }
]

データはこんな感じ。『null』ではなく『Null』だったりするとエラーになります。

stringにNullを設定する

まずは動作確認のためにnullを許容する型に格納してみます。

無事nullが設定されました。

intにNullを設定する

Newtonsoft.Json.JsonSerializationExceptionが発生しました。

int?にnullを設定する

null許容型にしてnullを設定してみました。
問題なく動きました。

nullのエラーを無視するように設定する

JsonSerializerSettingsの中のjsonSerializerSettingsを設定するとnullのときもエラーを吐かなくなるんだとか。

using Newtonsoft.Json;
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;

namespace JsonSample
{
    class Program
    {
        static void Main()
        {
            List<Person> person = new List<Person>();

            using (var reader = new StreamReader(@"C:\jikken\jikken.json",
                Encoding.GetEncoding("utf-8")))
            {
                JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
                jsonSerializerSettings.NullValueHandling = NullValueHandling.Ignore;
                person = JsonConvert.DeserializeObject<List<Person>>(reader.ReadToEnd(), jsonSerializerSettings);
            }
        }

        public class Person
        {
            public int _id { get; set; }

            public Person() {
                _id = 10;
            }   
        }
    }
}

実際に動かしてみたらこんな感じです。nullが無視されてint型変数は初期値の10のままでした!

この設定はnullを設定後、エラーを握りつぶすわけではなく入力値がnullであれば無視する(デシリアライズしない)ということなので注意が必要です。
この設定をすると、例えば本来ならばnullが設定可能なstring変数もnullになるのではなく初期値のままになります。設定を外すとstring変数はnullで上書きされます。その辺りは念入りにテストをした方がよさそうです。