001package com.identityworksllc.iiq.common.vo;
002
003import com.fasterxml.jackson.core.JsonGenerator;
004import com.fasterxml.jackson.databind.SerializerProvider;
005import com.fasterxml.jackson.databind.ser.std.StdSerializer;
006
007import java.io.IOException;
008import java.io.PrintWriter;
009import java.io.StringWriter;
010
011/**
012 * A custom Jackson serializer for transforming a Throwable into a standard
013 * Map format, including type, message, and stack trace.
014 *
015 * This is primarily intended for REST API usage.
016 */
017public class ThrowableSerializer extends StdSerializer<Throwable> {
018    /**
019     * Constructs a new StampedMessageSerializer
020     */
021    public ThrowableSerializer() {
022        this(null);
023    }
024
025    /**
026     * Constructs a new serializer
027     * @param t The input type
028     */
029    public ThrowableSerializer(Class<Throwable> t) {
030        super(t);
031    }
032
033    /**
034     * Serializes the given Throwable object, if not null, into a map containing
035     * a string type (the class name), the string message, and a stack trace.
036     *
037     * @param value The value to serialize
038     * @param gen The JsonGenerator supplied by Jackson
039     * @param provider The Jackson serialization provider
040     * @throws IOException if serialization fails, especially of the stack trace
041     */
042    @Override
043    public void serialize(Throwable value, JsonGenerator gen, SerializerProvider provider) throws IOException {
044        if (value != null) {
045            gen.writeStartObject();
046            gen.writeStringField("type", value.getClass().getName());
047            gen.writeStringField("message", value.getMessage());
048            try (StringWriter target = new StringWriter()) {
049                try (PrintWriter printWriter = new PrintWriter(target)) {
050                    value.printStackTrace(printWriter);
051                }
052                gen.writeStringField("stacktrace", target.toString());
053            }
054            gen.writeEndObject();
055        } else {
056            gen.writeNull();
057        }
058    }
059}