23

I'm trying to convert JSON to C# object using Json.NET. The object looks like this in C#:

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

But when I run JsonConvert.DeserializeObject() on the incoming JSON, I get the following Exception:

Unable to find a constructor to use for type System.Nullable`1[System.Int32]. A class should either have a default constructor or only one constructor with arguments.

--- EDIT ----

Well it turns out that after doing many tests, the problem boils down to that my input for my JSON was like this:

{integerValue:{}, dateTimeValue: {} }

instead of:

{integerValue: null, dateTimeValue: null}

It turns out that the {} is a valid way of representing a null object in JSON but the JSON.Net parser did not know to treat {} tokens the same way as 'null' when de-serializing.

Thanks everyone for your input!

7wp
  • 12,505
  • 20
  • 77
  • 103
  • Can you add the JSON you're trying to deserialize? –  Jan 28 '10 at 21:14
  • I had the same problem, except {value:"null"} instead of {value:null}. – craastad Mar 25 '13 at 16:25
  • I just want to add this link to a related question that helped me solved this same problem: http://stackoverflow.com/questions/6507889/how-to-ignore-a-property-in-class-if-null-using-json-net Add: [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] – Yogi Nov 03 '16 at 05:51
  • have same issue with Newtonsoft.Json 6.0.0 rv v4.0.30319 – user1005462 Sep 15 '17 at 11:18

5 Answers5

18

The error is telling you that it cant find a a constructor that it can use for the deserialization.

Try adding a default constructor to the class:

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

    public MyObject(){}
} 

Patrick.

--EDIT--

So I've just created a simple console app using your MyObject, with and without a default constructor and I'm getting no errors. Here is my example:

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

I get no exceptions...

Can you show an example of the JSON that you are trying to deserialize?

Milo
  • 3,365
  • 9
  • 30
  • 44
Patrick
  • 1,137
  • 1
  • 10
  • 23
  • 1
    Patrick, I do not think it is as simple as that. The error is not that there is no default constructor for MyObject. The error is saying that there is no default constructor for type System.Nullable ! Every class that is user defined gets an implicit default parameter-less constructor by the compiler. Unless the constructor is marked private. – 7wp Jan 28 '10 at 20:43
  • You're right, the parameter-less constructor is added by the compiler - But I've had many instances in that past when developing WCF REST services (XML and JSON) where I would get serialization isses if I didn't specifically add a parameterless constructor. So in theory, what you say should work but in practice, I've had a different experience. I'll try to set up a project using the same tools you have to see if I can come up with a better option. – Patrick Jan 28 '10 at 20:56
  • 2
    Thanks for your efforts. I just found out what the problem was. Turns out my JSON input sring had {} instead of null for the null values. Although {} is still valid in JSON, the JSON.Net converter did not understand to handle {} the same way as null. – 7wp Jan 28 '10 at 22:35
  • I'll accept your answer as accepted since it is the one that triggered me to find the solution. – 7wp Jan 28 '10 at 22:41
  • Just to help someone who might have overlooked the the access modifier of the property - if you specify this: `public DateTime? dateTimeValue { get; private set; }` you will end up not having the date time set due to protection level. Man, I felt stupid after starring at my own code for hours when I discovered this... – Henning Winter Mar 24 '20 at 17:04
11

The solution for me was to create Converter according to this answer

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

And than specify in model

[JsonConverter(typeof(BoolConverter))]
public Boolean bold;
Community
  • 1
  • 1
Kateryna Gridina
  • 834
  • 9
  • 13
3

I dont know is it right answer or not, but at least You can create custom converter for Nullable<>, it helps me a lot with DataRow serializing/deserializing it also does not have default constructor. Here is sample

Sergey Mirvoda
  • 3,209
  • 2
  • 26
  • 30
  • Sergey. Thanks for helping. But it turns out the problem was something different. See my edits in my posted question. – 7wp Jan 28 '10 at 22:39
0

A completed version of the @Patrick answer:

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

Output:

?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
serge
  • 13,940
  • 35
  • 121
  • 205
0

Also make sure your properties have public setters in order for deserialization to work.

Neurion
  • 379
  • 6
  • 15