在 XML 或 JSON 中输出 Java 堆栈跟踪

output Java stack trace in XML or JSON

标准堆栈跟踪格式适用于人类。 如何以 XML/JSON 等结构化格式输出 Java 堆栈跟踪供机器使用?

你可以

package stack43542547;

import java.io.StringWriter;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

public class HowToConvertStackTraceToJson {
    @Test
    public void convertStackTraceToJson() throws Exception {
        try {
            throw new NullPointerException();
        } catch (Exception e) {
            System.out.println(asJson(e));
        }
    }

    private String asJson(Object obj) throws Exception {
            StringWriter w = new StringWriter();
            new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true).writeValue(w, obj);
            String result = w.toString();
            return result;  }
}

给予

 {
  "cause" : null,
  "stackTrace" : [ {
    "methodName" : "convertStackTraceToJson",
    "fileName" : "HowToConvertStackTraceToJson.java",
    "lineNumber" : 12,
    "className" : "stack43542547.HowToConvertStackTraceToJson",
    "nativeMethod" : false
  }, {
    "methodName" : "invoke0",
    "fileName" : "NativeMethodAccessorImpl.java",
    "lineNumber" : -2,
    "className" : "sun.reflect.NativeMethodAccessorImpl",
    "nativeMethod" : true
  }, {
    "methodName" : "invoke",
    "fileName" : "NativeMethodAccessorImpl.java",
    "lineNumber" : 62,
    "className" : "sun.reflect.NativeMethodAccessorImpl",
    "nativeMethod" : false
  }, {
    "methodName" : "invoke",
    "fileName" : "DelegatingMethodAccessorImpl.java",
    "lineNumber" : 43,
    "className" : "sun.reflect.DelegatingMethodAccessorImpl",
    "nativeMethod" : false
  }, {
    "methodName" : "invoke",
    "fileName" : "Method.java",
    "lineNumber" : 483,
    "className" : "java.lang.reflect.Method",
    "nativeMethod" : false
  }, {
    "methodName" : "runReflectiveCall",
    "fileName" : "FrameworkMethod.java",
    "lineNumber" : 50,
    "className" : "org.junit.runners.model.FrameworkMethod",
    "nativeMethod" : false
  }, {
    "methodName" : "run",
    "fileName" : "ReflectiveCallable.java",
    "lineNumber" : 12,
    "className" : "org.junit.internal.runners.model.ReflectiveCallable",
    "nativeMethod" : false
  }, {
    "methodName" : "invokeExplosively",
    "fileName" : "FrameworkMethod.java",
    "lineNumber" : 47,
    "className" : "org.junit.runners.model.FrameworkMethod",
    "nativeMethod" : false
  }, {
    "methodName" : "evaluate",
    "fileName" : "InvokeMethod.java",
    "lineNumber" : 17,
    "className" : "org.junit.internal.runners.statements.InvokeMethod",
    "nativeMethod" : false
  }, {
    "methodName" : "runLeaf",
    "fileName" : "ParentRunner.java",
    "lineNumber" : 325,
    "className" : "org.junit.runners.ParentRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "runChild",
    "fileName" : "BlockJUnit4ClassRunner.java",
    "lineNumber" : 78,
    "className" : "org.junit.runners.BlockJUnit4ClassRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "runChild",
    "fileName" : "BlockJUnit4ClassRunner.java",
    "lineNumber" : 57,
    "className" : "org.junit.runners.BlockJUnit4ClassRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "run",
    "fileName" : "ParentRunner.java",
    "lineNumber" : 290,
    "className" : "org.junit.runners.ParentRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "schedule",
    "fileName" : "ParentRunner.java",
    "lineNumber" : 71,
    "className" : "org.junit.runners.ParentRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "runChildren",
    "fileName" : "ParentRunner.java",
    "lineNumber" : 288,
    "className" : "org.junit.runners.ParentRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "access[=11=]0",
    "fileName" : "ParentRunner.java",
    "lineNumber" : 58,
    "className" : "org.junit.runners.ParentRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "evaluate",
    "fileName" : "ParentRunner.java",
    "lineNumber" : 268,
    "className" : "org.junit.runners.ParentRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "run",
    "fileName" : "ParentRunner.java",
    "lineNumber" : 363,
    "className" : "org.junit.runners.ParentRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "run",
    "fileName" : "JUnit4TestReference.java",
    "lineNumber" : 86,
    "className" : "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference",
    "nativeMethod" : false
  }, {
    "methodName" : "run",
    "fileName" : "TestExecution.java",
    "lineNumber" : 38,
    "className" : "org.eclipse.jdt.internal.junit.runner.TestExecution",
    "nativeMethod" : false
  }, {
    "methodName" : "runTests",
    "fileName" : "RemoteTestRunner.java",
    "lineNumber" : 459,
    "className" : "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "runTests",
    "fileName" : "RemoteTestRunner.java",
    "lineNumber" : 678,
    "className" : "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "run",
    "fileName" : "RemoteTestRunner.java",
    "lineNumber" : 382,
    "className" : "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    "nativeMethod" : false
  }, {
    "methodName" : "main",
    "fileName" : "RemoteTestRunner.java",
    "lineNumber" : 192,
    "className" : "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
    "nativeMethod" : false
  } ],
  "localizedMessage" : null,
  "message" : null,
  "suppressed" : [ ]
}