You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java将slf4j.Logger生成的日志文件解析为JSON数组?

解析SLF4J日志到JSON数组的可行方案

核心思路是利用正则表达式的正向预查识别日志条目边界,同时通过精准的字段匹配提取内容,避开日志消息含空格、换行的干扰。

步骤说明

  1. 识别日志条目边界:每条日志的开头都遵循「日期 时间 模式 日志名 - 」的固定格式,用正向预查正则匹配这个开头,将整个日志文件分割为完整的单条日志(包含多行消息)。
  2. 提取单条日志的字段:对每条日志,用正则匹配出日期、时间、模式、日志名和消息,其中消息部分包含所有后续换行内容。
  3. 组装JSON数组:将每条日志的字段转换为JSON对象,最后组合成数组输出。

正则表达式示例

假设你的日志日期格式为yyyy-MM-dd、时间为HH:mm:ss.SSS、模式为大写单词(如INFO/DEBUG/ERROR),可使用以下正则:

1. 分割日志条目(匹配每条日志的起始标记)

(?=^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} [A-Z]+ .*? - )

这个正则用正向预查,找到所有符合日志开头格式的位置,以此分割出完整的单条日志(包括多行消息)。

2. 提取单条日志的字段

^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}\.\d{3}) ([A-Z]+) (.*?) - (.*)$
  • 启用DOTALL模式(Java)或re.DOTALL(Python),让.*匹配换行符,确保消息部分包含所有多行内容。
  • 分组说明:
    • 第1组:日期
    • 第2组:时间
    • 第3组:模式(如INFO)
    • 第4组:日志名(允许含空格)
    • 第5组:日志消息(含换行、空格等任意内容)

Java实现示例

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LogParser {
    public static void main(String[] args) throws IOException {
        // 读取日志文件内容
        String logContent = Files.readString(Paths.get("your-log-file.log"));

        // 分割日志条目的正则
        String splitRegex = "(?=^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3} [A-Z]+ .*? - )";
        String[] logEntries = logContent.split(splitRegex);

        // 提取字段的正则,启用DOTALL模式
        Pattern fieldPattern = Pattern.compile("^(\\d{4}-\\d{2}-\\d{2}) (\\d{2}:\\d{2}:\\d{2}\\.\\d{3}) ([A-Z]+) (.*?) - (.*)$", Pattern.DOTALL | Pattern.MULTILINE);

        List<LogEntry> logList = new ArrayList<>();
        for (String entry : logEntries) {
            if (entry.isBlank()) continue;
            Matcher matcher = fieldPattern.matcher(entry);
            if (matcher.find()) {
                LogEntry logEntry = new LogEntry();
                logEntry.setDate(matcher.group(1));
                logEntry.setTime(matcher.group(2));
                logEntry.setMode(matcher.group(3));
                logEntry.setLoggerName(matcher.group(4).trim());
                logEntry.setMessage(matcher.group(5).trim());
                logList.add(logEntry);
            }
        }

        // 转换为JSON数组
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonOutput = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(logList);
        System.out.println(jsonOutput);
    }

    // 日志条目实体类
    static class LogEntry {
        private String date;
        private String time;
        private String mode;
        private String loggerName;
        private String message;

        // Getter和Setter
        public String getDate() { return date; }
        public void setDate(String date) { this.date = date; }
        public String getTime() { return time; }
        public void setTime(String time) { this.time = time; }
        public String getMode() { return mode; }
        public void setMode(String mode) { this.mode = mode; }
        public String getLoggerName() { return loggerName; }
        public void setLoggerName(String loggerName) { this.loggerName = loggerName; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
    }
}

Python实现示例

import re
import json

def parse_log_to_json(log_file_path):
    # 读取日志文件
    with open(log_file_path, 'r', encoding='utf-8') as f:
        log_content = f.read()

    # 分割日志条目
    split_regex = r'(?=^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} [A-Z]+ .*? - )'
    log_entries = re.split(split_regex, log_content)
    log_entries = [entry.strip() for entry in log_entries if entry.strip()]

    # 提取字段的正则,启用DOTALL模式
    field_regex = r'^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}\.\d{3}) ([A-Z]+) (.*?) - (.*)$'
    log_list = []

    for entry in log_entries:
        match = re.match(field_regex, entry, re.DOTALL)
        if match:
            log_item = {
                "date": match.group(1),
                "time": match.group(2),
                "mode": match.group(3),
                "loggerName": match.group(4).strip(),
                "message": match.group(5).strip()
            }
            log_list.append(log_item)

    # 转换为JSON数组
    return json.dumps(log_list, indent=2, ensure_ascii=False)

# 使用示例
json_result = parse_log_to_json("your-log-file.log")
print(json_result)

注意事项

  • 如果你的日期、时间或模式格式不同,只需调整正则中的对应部分即可(比如日期是MM/dd/yyyy就把\d{4}-\d{2}-\d{2}改成\d{2}/\d{2}/\d{4})。
  • 若日志名包含特殊字符,可适当放宽正则中匹配日志名的部分(比如把.*?换成更精准的规则,避免误匹配)。
  • 大日志文件建议分批读取处理,避免内存溢出。

内容的提问来源于stack exchange,提问作者Nilanka Manoj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 12:30:53