How to ignore JSON deserialization errors in C#

By FoxLearn 3/13/2025 3:05:04 AM   23
A single deserialization error can cause the entire process to fail.

Consider the following JSON. The second object has invalid data (can't convert string to float), which will result in deserialization failure:

[
   {
      "Name": "Alice",
      "Salary": 50000.0
   },
   {
      "Name": "Bob",
      "Salary": "invalid"
   }
]

Using Newtonsoft.Json, you can choose to ignore deserialization errors by passing an error handling lambda in the settings:

using Newtonsoft.Json;

var employees = JsonConvert.DeserializeObject<List<Employee>>(employeeJson, new JsonSerializerSettings()
{
     Error = (sender, error) => error.ErrorContext.Handled = true
});

Console.WriteLine($"How many valid employees? {employees?.Count()}");

This will output:

How many valid employees? 1

In this case, all deserialization errors are ignored, and the object with the error is excluded. Therefore, the "invalid" entry (Bob) is removed from the result, leaving only valid entries in the list.

System.Text.Json Does Not Have This Functionality

System.Text.Json does not currently support ignoring deserialization errors out-of-the-box. If you need this feature, I recommend using Newtonsoft.Json. Alternatively, you'd have to implement a custom JSON converter to handle such errors manually.

What Happens When an Object Has an Error?

When an object encounters a deserialization error:

  • The object with the error is excluded from the result.
  • The parent object containing the error will also be excluded (recursively affecting the hierarchy).
  • Arrays containing the faulty object will not be excluded entirely.

This is particularly useful when deserializing JSON arrays because each object in the array is independent. You can filter out faulty objects while retaining the valid ones.

It also allows you to avoid exceptions when deserializing a single object, especially if you do not want to wrap the deserialization in a try/catch block.

Example - Child Object with an Error

Consider this array of employee data, where one employee has an invalid project ID:

[
   {
      "Id": 101,
      "Project": { "Id": 1, "Name": "Project X" }
   },
   {
      "Id": 102,
      "Project": { "Id": null, "Name": "Project Y" }
   }
]

For example, How you would deserialize and ignore errors:

var employees = JsonConvert.DeserializeObject<List<Employee>>(employeeJson, new JsonSerializerSettings()
{
    Error = (sender, error) => error.ErrorContext.Handled = true
});

Console.WriteLine($"Valid employees count: {employees?.Count()}");

This will output:

Valid employees count: 0

In this case, the child object (Project) had an error (with a null ID), which caused the parent object (Employee) to be excluded, resulting in an empty list.

Example - Error in an Object Within an Array

Consider the following list of products where one item has a bad price:

[
  {
    "ProductName": "Laptop",
    "Price": 1200.50
  },
  {
    "ProductName": "Phone",
    "Price": "invalid"
  }
]

You can deserialize and ignore errors like this:

var products = JsonConvert.DeserializeObject<List<Product>>(productsJson, new JsonSerializerSettings()
{
    Error = (sender, error) => error.ErrorContext.Handled = true
});

foreach (var product in products ?? Enumerable.Empty<Product>())
{
    Console.WriteLine($"{product.ProductName}: {product.Price}");
}

This will output:

Laptop: 1200.5

The second product (Phone) had a deserialization error and was excluded. Only the valid objects are included in the result.

Example - Malformed JSON Returning Null

If the JSON is malformed, such as containing a stray character like a #, deserialization might return null:

[
   { 
      # 
      "Id": 1,
      "Project": { "Id": 1, "Name": "Project Z" }
   }
]

Now, when deserializing with error handling:

var employees = JsonConvert.DeserializeObject<List<Employee>>(employeeJson, new JsonSerializerSettings()
{
    Error = (sender, error) => error.ErrorContext.Handled = true
});

Console.WriteLine($"Employees is null? {employees is null}");

This will output:

Employees is null? True

In this case, the malformed JSON caused deserialization to fail, resulting in null. Always remember to null-check the results.

Reporting Errors

Besides ignoring errors, you can also use the error handler to log or report errors. For instance, you can collect error messages and display them to the user:

[
   { 
      "Id": 1,
      "Project": { "Id": null, "Name": "Project A" }
   },
   { 
      "Id": "invalid",
      "Project": { "Id": 2, "Name": "Project B" }
   }
]

You can capture errors like this:

var errorMessages = new List<string>();

var employees = JsonConvert.DeserializeObject<List<Employee>>(employeeJson, new JsonSerializerSettings()
{
    Error = (sender, error) =>
    {
        errorMessages.Add(error.ErrorContext.Error.Message);
        error.ErrorContext.Handled = true;
    }
});

foreach (var message in errorMessages)
{
    Console.WriteLine(message);
    Console.WriteLine();
}

This will output:

Error converting value {null} to type 'System.Int32'. Path '[0].Project.Id', line 4, position 26.
Could not convert string to integer: invalid. Path '[1].Id', line 7, position 20.

By capturing and reporting these errors, you can provide better feedback to the user or log them for further investigation.