Spring Boot中如何便捷地以JSON格式记录自定义对象日志?
便捷输出自定义对象为JSON日志的方案
针对你遇到的问题,这里提供几个实用且低侵入的解决方案:
方案一:自定义Logback日志转换器(全局生效)
通过自定义Logback的日志参数转换器,让所有日志中的非基础类型对象自动转为JSON格式,无需手动调用ObjectMapper。
步骤1:实现自定义转换器类
import ch.qos.logback.classic.pattern.ClassicConverter; import ch.qos.logback.classic.spi.ILoggingEvent; import com.fasterxml.jackson.databind.ObjectMapper; public class JsonObjectConverter extends ClassicConverter { // 复用ObjectMapper实例,避免重复创建 private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @Override public String convert(ILoggingEvent event) { StringBuilder sb = new StringBuilder(); for (Object arg : event.getArgumentArray()) { if (arg != null && !(arg instanceof String || arg instanceof Number || arg instanceof Boolean)) { try { sb.append(OBJECT_MAPPER.writeValueAsString(arg)); } catch (Exception e) { // 转换失败时 fallback 到默认toString sb.append(arg.toString()); } } else { sb.append(arg); } sb.append(" "); } return sb.toString().trim(); } }
步骤2:配置Logback
在logback-spring.xml或logback.xml中添加转换器规则,并修改日志输出格式:
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <!-- 用自定义转换器替换原有的%s占位符 --> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %customJsonConverter%n</pattern> <!-- 注册自定义转换器 --> <conversionRule conversionWord="customJsonConverter" converterClass="com.your.package.JsonObjectConverter"/> </encoder> </appender>
之后直接用常规方式打日志即可:
log.info("获取到用户信息:{}", userInfo);
转换器会自动把userInfo转为JSON格式输出。
方案二:封装全局日志工具类
如果不想修改日志框架配置,可以封装一个工具类,统一处理对象转JSON的逻辑,同时规避异常和NPE问题。
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper; public class LogUtil { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); // 封装info级别日志 public static void info(Class<?> clazz, String message, Object... args) { Logger logger = LoggerFactory.getLogger(clazz); if (logger.isInfoEnabled()) { Object[] processedArgs = processArgs(args); logger.info(message, processedArgs); } } // 统一处理日志参数 private static Object[] processArgs(Object[] args) { if (args == null) return new Object[0]; for (int i = 0; i < args.length; i++) { Object arg = args[i]; if (arg != null && !(arg instanceof String || arg instanceof Number || arg instanceof Boolean)) { try { args[i] = OBJECT_MAPPER.writeValueAsString(arg); } catch (Exception e) { args[i] = arg.toString(); } } } return args; } // 可按需封装warn/error等其他级别日志 public static void error(Class<?> clazz, String message, Object... args) { Logger logger = LoggerFactory.getLogger(clazz); if (logger.isErrorEnabled()) { Object[] processedArgs = processArgs(args); logger.error(message, processedArgs); } } }
调用示例:
LogUtil.info(UserController.class, "更新用户:{}", userInfo);
方案三:基于抽象类统一实体类toString
如果实体类数量不多,可以定义一个抽象类,让所有需要JSON输出的实体类继承它,统一实现JSON格式的toString方法。
步骤1:定义抽象基类
import com.fasterxml.jackson.databind.ObjectMapper; public abstract class JsonToString { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @Override public String toString() { try { return OBJECT_MAPPER.writeValueAsString(this); } catch (Exception e) { // 转换失败时使用父类默认toString return super.toString(); } } }
步骤2:实体类继承基类
import lombok.Data; import com.fasterxml.jackson.annotation.JsonInclude; @Data @JsonInclude(JsonInclude.Include.NON_NULL) // 忽略null字段,优化日志输出 public class UserInfo extends JsonToString { private Long id; private String name; private String email; }
之后直接打印对象即可输出JSON:
log.info("用户详情:{}", userInfo);
内容的提问来源于stack exchange,提问作者Roberto
相关产品推荐
相关产品推荐

