3

When serializing a System.ArgumentNullException to JSON using JSON.NET, part of the message appears lost:

var json = JsonConvert.SerializeObject(new ArgumentNullException("argument", "Some Message"));

returns:

{
"ClassName":"System.ArgumentNullException",
"Message":"Some Message",
"Data":null,
"InnerException":null,
"HelpURL":null,
"StackTraceString":null,
"RemoteStackTraceString":null,
"RemoteStackIndex":0,
"ExceptionMethod":null,
"HResult":-2147467261,
"Source":null,
"WatsonBuckets":null
}

I expected the Message token to be:

"Some Message\r\nParameter name: argument"

As noted by codefuller, the ArgumentNullException implements ISerializable and is the culprit. I can disable this by using custom JsonSerializerSettings.

However, the application needs to serialize any objects, including objects with an ArgumentNullException property. I'd prefer to avoid ignoring ISerialiable unless it presents a problem.

Both of my solutions include a custom JsonConverter.

Solution 1: Centralized JsonSerializer

  • Create a static list of JsonConverters to add to JsonSerializer.Converters
  • Include an ExceptionConverter that handles ArgumentNullException explicitly
  • Everywhere I need to serialize, ensure my JsonSerializer includes these converters

Cons: other developers must rigorously ensure they are including these converters with any serialization they do.

Solution 2: Override ArgumentNullException

I can create a CustomArgumentNullException class, and tag it with a JsonConvert attribute to leverage my custom converter.

Cons: other developers must rigorously ensure they are raising a CustomArgumentNullException instead of an ArgumentNullExcpetion.

Wished-for Solution

I'd love to somehow tag the existing ArgumentNullException with a JsonConverter attribute pointing to my custom converter. Is there some way to achieve this in the Json.NET code base?

Eric Patrick
  • 2,097
  • 2
  • 20
  • 31
  • I can work around the issue by creating a custom JsonConverter for the ArgumentNullException class, and explicitly adding it to a JsonSerializer, but this seems ... ugly. – Eric Patrick Nov 30 '17 at 02:44

1 Answers1

1

Exception classes implement ISerializable interface. By the default for such objects Json.Net uses ISerializable.GetObjectData() method for data serialization. In other words ArgumentNullException class controls by itself how its data will be serialized. And somewhere inside it has a logic that serializes only actual message that was passed to constructor without Parameter name: argument part.

You could change this Json.Net behavior and avoid using of GetObjectData() with following JsonSerializerSettings:

var settings = new JsonSerializerSettings()
{
    ContractResolver = new DefaultContractResolver()
    {
        IgnoreSerializableInterface = true,
    },
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};

var json = JsonConvert.SerializeObject(new ArgumentNullException("argument", "Some Message"), settings);

However in this case set of serialized fields will differ from original json. Check whether it actually suits your needs.

CodeFuller
  • 30,317
  • 3
  • 63
  • 79
  • Yes, that gives me a reasonable serialization. However, my challenge is a bit broader than my question poses: what is a reasonable way to apply that throughout an application stack when serializing objects that may include an ArgumentNullException property? I'll edit the question appropriately. Thanks! – Eric Patrick Nov 30 '17 at 13:22