Serialize Exceptions as JSON
Serialize Exceptions Using Newtonsoft.Json
public class CustomException : Exception
{
public string Mitigation { get; }
public CustomException(string message, string mitigation)
: this(message, mitigation, null)
{ }
public CustomException(string message, string mitigation, Exception? innerException)
: base(message, innerException)
{
Mitigation = mitigation;
}
}
[Serializable]
public class CustomVerboseException : CustomException
{
public CustomVerboseException(string message, string mitigation)
: base(message, mitigation) { }
}
try
{
throw new CustomException("Custom error", "Try later");
}
catch (CustomException ex)
{
var json = JsonConvert.SerializeObject(ex)!;
Assert.Contains("Mitigation", json);
}
Serialize Exceptions By Custom JsonConverter
public class SimpleExceptionConverter : JsonConverter<Exception>
{
public override Exception? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return new NotImplementedException();
}
public override void Write(Utf8JsonWriter writer, Exception value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteString("Error", value.Message);
writer.WriteString("Type", value.GetType().Name);
if (value.InnerException is { } innerException)
{
writer.WritePropertyName("InnerException");
Write(writer, innerException, options);
}
writer.WriteEndObject();
}
}
public class DetailExceptionConverter : JsonConverter<Exception>
{
public override void Write(Utf8JsonWriter writer, Exception value, JsonSerializerOptions options)
{
writer.WriteStartObject();
var exceptionType = value.GetType();
writer.WriteString("ClassName", exceptionType.FullName);
var properties = exceptionType.GetProperties()
.Where(e => e.PropertyType != typeof(Type))
.Where(e => e.PropertyType.Namespace != typeof(MemberInfo).Namespace)
.ToList();
foreach (var property in properties)
{
var propertyValue = property.GetValue(value, null);
if (options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull && propertyValue == null)
continue;
writer.WritePropertyName(property.Name);
JsonSerializer.Serialize(writer, propertyValue, property.PropertyType, options);
}
writer.WriteEndObject();
}
}
try
{
var innerException = new InvalidOperationException("Bad operation");
throw new CustomException("Custom error", "Try later", innerException);
}
catch (Exception ex)
{
JsonSerializerOptions options = new(JsonSerializerOptions.Default);
options.Converters.Add(new SimpleExceptionConverter());
var json = JsonSerializer.Serialize(ex, options);
Assert.NotEmpty(json);
}
Serialize Exceptions By Object Transformation
public class ExceptionObject
{
public string Message { get; set; }
public string? StackTrace { get; set; }
public ExceptionObject? InnerException { get; set; }
public ExceptionObject(Exception exception)
{
Message = exception.Message;
StackTrace = exception.StackTrace;
if (exception.InnerException is { } innerException)
InnerException = new ExceptionObject(innerException);
}
}
try
{
var innerException = new InvalidOperationException("Bad operation");
throw new CustomException("Custom error", "Try later", innerException);
}
catch (Exception ex)
{
var interimObject = new ExceptionObject(ex);
var json = JsonSerializer.Serialize(interimObject);
Assert.NotEmpty(json);
}