Json.NET, Невозможно дезацинировать тип с нулевым значением

Я пытаюсь преобразовать JSON в объект С# с помощью Json.NET. Объект выглядит так на С#:

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

Но когда я запускаю JsonConvert.DeserializeObject() на входящем JSON, я получаю следующее исключение:

Невозможно найти конструктор для использования для типа System.Nullable`1 [System.Int32]. класс должен либо иметь значение по умолчанию конструктор или только один конструктор с аргументами.

--- EDIT ----

Ну, получается, что после многих тестов проблема сводится к тому, что мой ввод для моего JSON был таким:

{integerValue:{}, dateTimeValue: {} }

вместо:

{integerValue: null, dateTimeValue: null}

Оказывается, что {} является допустимым способом представления нулевого объекта в JSON, но парсер JSON.Net не знал, чтобы лечить {} токены так же, как "null" при де-сериализации.

Спасибо всем за ваш вклад!

Ответы

Ответ 1

Ошибка говорит вам, что он не может найти конструктор, который он может использовать для десериализации.

Попробуйте добавить к классу конструктор по умолчанию:

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

        public MyObject(){}
    } 

Патрик.

- EDIT -

Итак, я только что создал простое консольное приложение, использующее 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, который вы пытаетесь десериализовать?

Ответ 2

Решением для меня было создание Конвертера в соответствии с этим ответом

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;

Ответ 3

Я не знаю, это правильный ответ или нет, но по крайней мере вы можете создать собственный конвертер для Nullable < > , он очень помогает мне с сериализацией/десериализацией DataRow, а также не имеет конструктора по умолчанию. Вот образец

Ответ 4

Готовая версия ответа @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