1

I try to implement code for error handling from Newtonsoft Documentation

I am using the following JsonSerializerSettings

errors = new JsonErrors();
jsonSerializerSettings = new JsonSerializerSettings
{
    Error = delegate (object sender, ErrorEventArgs args)
    {
        errors.Add(args.ErrorContext.Error.Message);
        args.ErrorContext.Handled = true;
    }

};

I use the following code to deserialize the response.

try
{
    deserializedObject = JsonConvert.DeserializeObject(response, jsonSerializerSettings);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
    throw;
}

If add some extra chars at the end of the response string i expect to catch deserialize exception but actually i see relevant error added to JsonErrors object.

Can i be sure that any error raised by de-serialization/serialization will be catched by JsonSerializerSettings mechanism. Can i remove the try a catch in code?

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
Alexander Gorelik
  • 3,985
  • 6
  • 37
  • 53
  • 2
    If value passed do deserialization will be null, then you'll get ArgumentNullException from constructor of StringReader, which is created by JsonConvert.DeserializeObject method. So without at least one additional check, you cannot remove try catch block. – tekado Jul 19 '16 at 11:58

2 Answers2

2

In theory all exceptions should be caught and passed to the handler (other than exceptions that cannot be caught such as StackOverflowException.) If you go to the github source and search for IsErrorHandled you will see that all types of exception are caught, for instance here:

        catch (Exception ex)
        {
            if (IsErrorHandled(null, contract, null, reader as IJsonLineInfo, reader.Path, ex))
            {
                HandleError(reader, false, 0);
                return null;
            }
            else
            {
                // clear context in case serializer is being used inside a converter
                // if the converter wraps the error then not clearing the context will cause this error:
                // "Current error context error is different to requested error."
                ClearErrorContext();
                throw;
            }
        }

That being said, in practice there may be edge cases where this does not work. For instance, in a previous answer I noted that exceptions thrown from the OnSerializing event of the root object cannot be handled -- though this seems not to be reproducible in the current version (9.0) of Json.NET. But even in the current version, if an exception is thrown trying to create a contract for the root object, Json.NET will not catch and handle it. This could happen because of a buggy custom contract resolver, or because of a mistake in applying serialization attributes to the root object. For instance, trying to serialize or deserialize the following as the root object:

public class BadExtensionData
{
    Dictionary<string, object> extensionData;

    [JsonExtensionData]
    public Dictionary<string, object> ExtensionData { set { extensionData = value; } }
}

will result in an unhandled exception:

Newtonsoft.Json.JsonException: Invalid extension data attribute on 'BadExtensionData'. Member 'ExtensionData' must have a getter.

Thus you may want to leave the outer try/catch just in case (and even report an issue for exceptions that cannot be handled).

Finally, do be aware that catching and swallowing all exceptions is considered bad practice.

dbc
  • 104,963
  • 20
  • 228
  • 340
1

After quick source code inspection I tend to say that following sentence is true:

If JsonSerializerSettings is proper (ie. without nasty null references and with configured error handler with Handled property set to true) and input string is not null (only for deserialization), then try-catch block is redundant.

tekado
  • 123
  • 6