Пользовательский JSON Marshaller с поддержкой кодировки Base64 | ошибка при вызове MarshalJSON для маршрутов типа.Temp: недопустимый символ 'e'

Я хочу написать собственный Marshaller. Я сделал реализации следующим образом.

      type Temp struct {
    Time time.Time
}

func (t Temp) MarshalJSON() ([]byte, error) {
    type __ Temp
    var x = __(t)
    var buff bytes.Buffer
    if err := json.NewEncoder(&buff).Encode(x); err != nil {
        return nil, err
    }
    raw := buff.Bytes()
    dst := make([]byte, base64.StdEncoding.EncodedLen(len(raw)))
    base64.StdEncoding.Encode(dst, raw)
    return dst, nil
}

Логика роутера следующая.

      func health(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "token": Temp{time.Now()},
    })
}

После запуска я получаю ошибку вроде.

      2022/08/06 00:36:53 [Recovery] 2022/08/06 - 00:36:53 panic recovered:
GET /health HTTP/1.1
Host: localhost:9000
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Sec-Ch-Ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "macOS"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36


json: error calling MarshalJSON for type routes.Temp: invalid character 'e' looking for beginning of value
/Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/render/json.go:56 (0x19448bd)
    JSON.Render: panic(err)
/Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:915 (0x194fd3c)
    (*Context).Render: if err := r.Render(c.Writer); err != nil {
/Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:958 (0x19502f3)
    (*Context).JSON: c.Render(code, render.JSON{Data: obj})
/Users/vajahat/work/dotpe/order/routes/routes.go:43 (0x1f61b9c)
    health: c.JSON(200, gin.H{
/Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:165 (0x194a0bc)
    (*Context).Next: c.handlers[c.index](c)
/Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/recovery.go:99 (0x195c437)
    CustomRecoveryWithWriter.func1: c.Next()
/Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:165 (0x194a0bc)
    (*Context).Next: c.handlers[c.index](c)
/Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/logger.go:241 (0x195ae31)
    LoggerWithConfig.func1: c.Next()
/Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:165 (0x194a0bc)
    (*Context).Next: c.handlers[c.index](c)
/Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/gin.go:489 (0x1958a7b)
    (*Engine).handleHTTPRequest: c.Next()
/Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/gin.go:445 (0x1958584)
    (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/local/go/src/net/http/server.go:2947 (0x14ca5d3)
    serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/local/go/src/net/http/server.go:1991 (0x14c413b)
    (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/local/go/src/runtime/asm_amd64.s:1594 (0x1072640)
    goexit: BYTE    $0x90   // NOP

[GIN] 2022/08/06 - 00:36:53 | 500 |   5.20548072s |             ::1 | GET      "/health"

Ошибкаjson: error calling MarshalJSON for type routes.Temp: invalid character 'e' looking for beginning of valueбеспокоит меня очень давно.

Я ожидаю вывода следующим образом.

      {
    "token":"eyJUaW1lIjoiMjAyMi0wOC0wNlQwMDo0ODoyOS4yNDEzNTUrMDU6MzAifQo="
}

В отладчике работает. Проблема во время рендеринга, я верю. Я хочу получить выше в качестве вывода.

Любое предложение или помощь высоко ценятся.

1 ответ

ТвойMarshalJSON()функция должна возвращать допустимое значение JSON; однако ваш пример создает необработанную строку Base64, которая не является допустимой JSON.

Вы можете исправить это, просто заключив текущее возвращаемое значение в кавычки, чтобы сделать его действительной строкой JSON!

      b64len := base64.StdEncoding.EncodedLen(len(raw))
dst := make([]byte, b64len+2)
base64.StdEncoding.Encode(dst[1:], raw)
dst[0], dst[b64len+1] = '"', '"'
return dst, nil
Другие вопросы по тегам