web-dev-qa-db-ja.com

Json.NET、null許容型を逆シリアル化できません

Json.NETを使用してJSONをC#オブジェクトに変換しようとしています。オブジェクトはC#では次のようになります。

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

しかし、着信JSONでJsonConvert.DeserializeObject()を実行すると、次の例外が発生します。

タイプSystem.Nullable`1 [System.Int32]に使用するコンストラクターが見つかりません。クラスは、デフォルトのコンストラクターを持つか、引数を持つコンストラクターを1つだけ持つ必要があります。

---編集----

さて、多くのテストを行った後、問題は結局、私のJSONへの入力が次のようになったことがわかります。

_{integerValue:{}, dateTimeValue: {} }
_

の代わりに:

_{integerValue: null, dateTimeValue: null}
_

{}はJSONでnullオブジェクトを表す有効な方法であることがわかりましたが、JSON.Netパーサーは{}トークンを逆シリアル化するときに 'null'と同じように処理することを認識していませんでした。

皆様のご意見ありがとうございます!

20
7wp

このエラーは、逆シリアル化に使用できるコンストラクターが見つからないことを示しています。

クラスにデフォルトのコンストラクタを追加してみてください:

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

        public MyObject(){}
    } 

パトリック。

-編集-

したがって、MyObjectを使用して、デフォルトのコンストラクターの有無にかかわらず、単純なコンソールアプリを作成したところ、エラーは発生しません。これが私の例です:

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

例外はありません...

逆シリアル化しようとしているJSONの例を示すことができますか?

15
Patrick

私にとっての解決策は、 この答え に従ってコンバータを作成することでした

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

そしてモデルで指定するより

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

私はそれが正しい答えかどうかはわかりませんが、少なくともNullable <>のカスタムコンバーターを作成できます。これは、DataRowのシリアル化/非シリアル化に役立ち、デフォルトのコンストラクターもありません。これが sample です

3
Sergey Mirvoda

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

出力:

?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