96

I have the following code:

return (DataTable)JsonConvert.DeserializeObject(_data, (typeof(DataTable)));

Then, I tried:

var jsonSettings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore
};

return (DataTable)JsonConvert.DeserializeObject<DataTable>(_data, jsonSettings);

The return line is throwing the error:

{"Error converting value \"\" to type 'System.Double'."}

Lots of solutions online suggesting creating custom Class with nullable types but this won't work for me. I can't expect the json to be in a certain format. I have no control over the column count, column type, or column names.

Kyle
  • 5,407
  • 6
  • 32
  • 47
  • 1
    Perhaps you should just use LINQ to JSON instead, and get a `JObject` instead of creating a `DataTable`? – Jon Skeet Aug 04 '15 at 15:22
  • If you need to convert `DataTable` use the dedicated converter [DataTableConverter](https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Converters/DataTableConverter.cs#L25) – Candide Aug 04 '15 at 15:26
  • 2
    Can you share an example of the JSON that is causing the problem? – dbc Aug 04 '15 at 15:42
  • @Candide Same error when using `return JsonConvert.DeserializeObject(_data, new DataTableConverter());` – Kyle Aug 04 '15 at 16:27

4 Answers4

255

You can supply settings to JsonConvert.DeserializeObject to tell it how to handle null values, in this case, and much more:

var settings = new JsonSerializerSettings
                    {
                        NullValueHandling = NullValueHandling.Ignore,
                        MissingMemberHandling = MissingMemberHandling.Ignore
                    };
var jsonModel = JsonConvert.DeserializeObject<Customer>(jsonString, settings);
Thomas Hagström
  • 4,371
  • 1
  • 21
  • 27
  • 1
    This is the perfect answer - I've been scouring solutions and finally one that works. Hero status. – iTrout Nov 19 '16 at 04:34
  • 6
    MissingMemberHandling = MissingMemberHandling.Ignore is default. No need to add it. – Uylenburgh Sep 25 '18 at 08:47
  • I got an error when deserializing the primitive type (long, int) properties in my class. The json comes from different api which i cannot control. The generic solution worked for me. Thank you Thomas – Satheesh K Jun 24 '20 at 13:21
  • 3
    imo these should be the default settings for the Deserializer. It shouldn't bug out and break your code by default just because a null value was encountered – SendETHToThisAddress Mar 12 '21 at 06:26
33

An alternative solution for Thomas Hagström, which is my prefered, is to use the property attribute on the member variables.

For example when we invoke an API, it may or may not return the error message, so we can set the NullValueHandling property for ErrorMessage:


    public class Response
    {
        public string Status;

        public string ErrorCode;

        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string ErrorMessage;
    }


    var response = JsonConvert.DeserializeObject<Response>(data);

The benefit of this is to isolate the data definition (what) and deserialization (use), the deserilazation needn’t to care about the data property, so that two persons can work together, and the deserialize statement will be clean and simple.

Eynzhang
  • 341
  • 3
  • 6
5

You can subscribe to the 'Error' event and ignore the serialization error(s) as required.

    static void Main(string[] args)
    {
        var a = JsonConvert.DeserializeObject<DataTable>("-- JSON STRING --", new JsonSerializerSettings
        {
            Error = HandleDeserializationError
        });
    }

    public static void HandleDeserializationError(object sender, ErrorEventArgs errorArgs)
    {
        var currentError = errorArgs.ErrorContext.Error.Message;
        errorArgs.ErrorContext.Handled = true;
    }
DotNetHitMan
  • 931
  • 8
  • 20
4

ASP.NET CORE: The accepted answer works perfectly. But in order to make the answer apply globally, in startup.cs file inside ConfigureServices method write the following:

    services.AddControllers().AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    });

The answer has been tested in a .Net Core 3.1 project.

M Fuat
  • 1,330
  • 3
  • 12
  • 24
  • 1
    without context about what **services** you are accessing, the answer would be both incomplete and wrong. – vivek86 Dec 25 '20 at 22:38
  • This is actually very good answer for contemporary code since the problem of setting global JSON deserialization options keeps surfacing up a lot. – ZXX May 20 '22 at 03:26