Golang解析Nginx日志中非法URL字符串失败的解决方法咨询
问题根源
你的JSON字符串解析失败,是因为URI字段中包含非法的JSON转义序列。JSON规范要求\x后面必须紧跟两个合法的十六进制字符(0-9、a-f、A-F),但示例中的\xG8、\xQ1等序列里,G、Q并非十六进制字符,导致json.Unmarshal无法识别,抛出invalid character 'x' in string escape code错误。
解决方案
1. 从日志生成源头修复(推荐)
如果能控制Nginx的日志输出配置,直接让Nginx生成合法的JSON格式日志:
在Nginx的log_format中添加escape=json参数,它会自动将URI中的特殊字符转成符合JSON规范的转义序列:
log_format json_log '{"time":"$time_iso8601","method":"$request_method","uri":"$uri"}'; access_log /var/log/nginx/access.log json_log escape=json;
这样生成的日志不会出现非法转义,Golang的标准json.Unmarshal可以直接解析。
2. 预处理非法JSON字符串(适用于已生成的日志)
如果日志已经存在,无法修改生成逻辑,可以在解析前预处理字符串,修复非法的\x转义:
import ( "log" "regexp" "strconv" "encoding/json" ) type Data map[string]interface{} func fixInvalidJSONEscapes(s string) string { // 匹配所有 \x 后跟非十六进制字符的序列 re := regexp.MustCompile(`\\x([0-9a-fA-F]{0,2}|[^0-9a-fA-F]{2})`) return re.ReplaceAllStringFunc(s, func(m string) string { if len(m) != 4 { return m } chars := m[2:] // 尝试将字符转成合法的UTF-8转义 var result string for _, c := range chars { if c < 128 { result += string(c) } else { // 转成 \u 开头的Unicode转义 result += "\\u" + strconv.FormatInt(int64(c), 16) } } return result }) } func main() { str := "{\"time\":\"2023-07-20T10:11:29+08:00\",\"method\":\"GET\",\"uri\":\"/www.baidu.com/eu\\\\xG8\\\\xB8\\\\xE9\\\\xQ1\\\\x9F\\\\xZ7\\\\xE8\\\\xAE\\\\xCF\\\\xF9\\\\xB5\\\\x12\"}" data := make(Data) fixedStr := fixInvalidJSONEscapes(str) if err := json.Unmarshal([]byte(fixedStr), &data); err == nil { log.Printf("json success, %#v", data) } else { log.Print(err) } }
3. 使用宽松的JSON解析库
如果预处理逻辑复杂,可以选择支持非严格JSON解析的第三方库,比如gjson,它能直接提取字段值,忽略非法转义:
import ( "log" "github.com/tidwall/gjson" ) func main() { str := "{\"time\":\"2023-07-20T10:11:29+08:00\",\"method\":\"GET\",\"uri\":\"/www.baidu.com/eu\\\\xG8\\\\xB8\\\\xE9\\\\xQ1\\\\x9F\\\\xZ7\\\\xE8\\\\xAE\\\\xCF\\\\xF9\\\\xB5\\\\x12\"}" result := gjson.Parse(str) time := result.Get("time").String() method := result.Get("method").String() uri := result.Get("uri").String() log.Printf("time: %s, method: %s, uri: %s", time, method, uri) }
内容的提问来源于stack exchange,提问作者moluzhui
相关产品推荐
相关产品推荐

