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

Golang Gin框架:如何移除请求Body中的空格与换行符

在Gin中间件中压缩JSON请求体日志(去除空格与换行)

因为直接通过字符串替换去除所有空格和换行可能会破坏JSON字符串内部的有效空格(比如示例中的"a "),所以推荐使用JSON标准库的工具来处理,既保证语法正确性,又能得到紧凑格式。

方法一:使用json.Compact(高效推荐)

json.Compact会直接压缩JSON字节流,仅移除JSON语法层面的空白字符(包括空格、换行、制表符等),保留字符串内部的空格,且性能比先解码再编码更好。

import (
    "bytes"
    "encoding/json"
    "io"
    "log"

    "github.com/gin-gonic/gin"
)

func RequestLogMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 读取并备份请求Body(Body只能读取一次,需重置)
        var rawBody []byte
        if c.Request.Body != nil {
            var err error
            rawBody, err = io.ReadAll(c.Request.Body)
            if err == nil {
                // 将读取后的Body重新放回,确保后续处理器能正常读取
                c.Request.Body = io.NopCloser(bytes.NewBuffer(rawBody))
            }
        }

        // 处理JSON压缩
        var compactBody []byte
        if len(rawBody) > 0 {
            compactBody = make([]byte, 0, len(rawBody))
            // 尝试压缩JSON,失败则使用原内容(兼容非JSON请求)
            if err := json.Compact(&compactBody, rawBody); err != nil {
                compactBody = rawBody
            }
        }

        // 打印日志(替换为你的实际日志调用)
        log.Printf("request_in||traceid=xx||spanid=xxx||path=%s||body=%s", c.Request.URL.Path, string(compactBody))

        c.Next()
    }
}

方法二:先解码再重新编码(通用兼容)

如果需要对JSON做额外处理(比如过滤敏感字段),可以先将JSON解码为interface{},再用json.Marshal编码(默认生成紧凑格式):

import (
    "bytes"
    "encoding/json"
    "io"
    "log"

    "github.com/gin-gonic/gin"
)

func RequestLogMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        var rawBody []byte
        if c.Request.Body != nil {
            var err error
            rawBody, err = io.ReadAll(c.Request.Body)
            if err == nil {
                c.Request.Body = io.NopCloser(bytes.NewBuffer(rawBody))
            }
        }

        var compactBody []byte
        if len(rawBody) > 0 {
            var temp interface{}
            // 尝试解码JSON,失败则用原内容
            if err := json.Unmarshal(rawBody, &temp); err == nil {
                compactBody, _ = json.Marshal(temp)
            } else {
                compactBody = rawBody
            }
        }

        log.Printf("request_in||traceid=xx||spanid=xxx||path=%s||body=%s", c.Request.URL.Path, string(compactBody))

        c.Next()
    }
}

关键注意点

  1. 重置请求Body:读取Body后必须用io.NopCloser重新包装并赋值回c.Request.Body,否则后续的Gin控制器无法读取请求参数。
  2. 兼容非JSON请求:加入错误判断,当请求Body不是JSON格式时,直接使用原始内容,避免日志打印报错。
  3. 保留有效空格:两种方法都不会修改JSON字符串内部的空格(比如示例中的"a "),仅去除语法层面的空白,保证日志数据的准确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:45:17