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); }