Custom JSON Marshaller Supporting Base64 encoding | error calling MarshalJSON for type routes.Temp: invalid character 'e'

huangapple go评论132阅读模式
英文:

Custom JSON Marshaller Supporting Base64 encoding | error calling MarshalJSON for type routes.Temp: invalid character 'e'

问题

我想编写一个自定义的Marshaller。我已经按照以下方式实现了代码。

  1. type Temp struct {
  2. Time time.Time
  3. }
  4. func (t Temp) MarshalJSON() ([]byte, error) {
  5. type __ Temp
  6. var x = __(t)
  7. var buff bytes.Buffer
  8. if err := json.NewEncoder(&buff).Encode(x); err != nil {
  9. return nil, err
  10. }
  11. raw := buff.Bytes()
  12. dst := make([]byte, base64.StdEncoding.EncodedLen(len(raw)))
  13. base64.StdEncoding.Encode(dst, raw)
  14. return dst, nil
  15. }

路由逻辑如下。

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

运行后,我得到了以下错误。

  1. 2022/08/06 00:36:53 [Recovery] 2022/08/06 - 00:36:53 panic recovered:
  2. GET /health HTTP/1.1
  3. Host: localhost:9000
  4. 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
  5. Accept-Encoding: gzip, deflate, br
  6. Accept-Language: en-US,en;q=0.9
  7. Cache-Control: max-age=0
  8. Connection: keep-alive
  9. Sec-Ch-Ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"
  10. Sec-Ch-Ua-Mobile: ?0
  11. Sec-Ch-Ua-Platform: "macOS"
  12. Sec-Fetch-Dest: document
  13. Sec-Fetch-Mode: navigate
  14. Sec-Fetch-Site: none
  15. Sec-Fetch-User: ?1
  16. Upgrade-Insecure-Requests: 1
  17. 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
  18. json: error calling MarshalJSON for type routes.Temp: invalid character 'e' looking for beginning of value
  19. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/render/json.go:56 (0x19448bd)
  20. JSON.Render: panic(err)
  21. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:915 (0x194fd3c)
  22. (*Context).Render: if err := r.Render(c.Writer); err != nil {
  23. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:958 (0x19502f3)
  24. (*Context).JSON: c.Render(code, render.JSON{Data: obj})
  25. /Users/vajahat/work/dotpe/order/routes/routes.go:43 (0x1f61b9c)
  26. health: c.JSON(200, gin.H{
  27. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:165 (0x194a0bc)
  28. (*Context).Next: c.handlers[c.index](c)
  29. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/recovery.go:99 (0x195c437)
  30. CustomRecoveryWithWriter.func1: c.Next()
  31. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:165 (0x194a0bc)
  32. (*Context).Next: c.handlers[c.index](c)
  33. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/logger.go:241 (0x195ae31)
  34. LoggerWithConfig.func1: c.Next()
  35. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:165 (0x194a0bc)
  36. (*Context).Next: c.handlers[c.index](c)
  37. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/gin.go:489 (0x1958a7b)
  38. (*Engine).handleHTTPRequest: c.Next()
  39. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/gin.go:445 (0x1958584)
  40. (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
  41. /usr/local/go/src/net/http/server.go:2947 (0x14ca5d3)
  42. serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
  43. /usr/local/go/src/net/http/server.go:1991 (0x14c413b)
  44. (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
  45. /usr/local/go/src/runtime/asm_amd64.s:1594 (0x1072640)
  46. goexit: BYTE $0x90 // NOP
  47. [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困扰了我很长时间。

我期望的输出如下所示。

  1. {
  2. "token":"eyJUaW1lIjoiMjAyMi0wOC0wNlQwMDo0ODoyOS4yNDEzNTUrMDU6MzAifQo="
  3. }

在调试器中,它是正常工作的。
问题可能出现在渲染时,我希望得到上述输出。

非常感谢您的任何建议或帮助。

英文:

I want to write a custom Marshaller. I have done the implementations as Following.

  1. type Temp struct {
  2. Time time.Time
  3. }
  4. func (t Temp) MarshalJSON() ([]byte, error) {
  5. type __ Temp
  6. var x = __(t)
  7. var buff bytes.Buffer
  8. if err := json.NewEncoder(&buff).Encode(x); err != nil {
  9. return nil, err
  10. }
  11. raw := buff.Bytes()
  12. dst := make([]byte, base64.StdEncoding.EncodedLen(len(raw)))
  13. base64.StdEncoding.Encode(dst, raw)
  14. return dst, nil
  15. }

The router logic is as follow.

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

After running, I get the error like.

  1. 2022/08/06 00:36:53 [Recovery] 2022/08/06 - 00:36:53 panic recovered:
  2. GET /health HTTP/1.1
  3. Host: localhost:9000
  4. 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
  5. Accept-Encoding: gzip, deflate, br
  6. Accept-Language: en-US,en;q=0.9
  7. Cache-Control: max-age=0
  8. Connection: keep-alive
  9. Sec-Ch-Ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"
  10. Sec-Ch-Ua-Mobile: ?0
  11. Sec-Ch-Ua-Platform: "macOS"
  12. Sec-Fetch-Dest: document
  13. Sec-Fetch-Mode: navigate
  14. Sec-Fetch-Site: none
  15. Sec-Fetch-User: ?1
  16. Upgrade-Insecure-Requests: 1
  17. 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
  18. json: error calling MarshalJSON for type routes.Temp: invalid character 'e' looking for beginning of value
  19. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/render/json.go:56 (0x19448bd)
  20. JSON.Render: panic(err)
  21. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:915 (0x194fd3c)
  22. (*Context).Render: if err := r.Render(c.Writer); err != nil {
  23. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:958 (0x19502f3)
  24. (*Context).JSON: c.Render(code, render.JSON{Data: obj})
  25. /Users/vajahat/work/dotpe/order/routes/routes.go:43 (0x1f61b9c)
  26. health: c.JSON(200, gin.H{
  27. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:165 (0x194a0bc)
  28. (*Context).Next: c.handlers[c.index](c)
  29. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/recovery.go:99 (0x195c437)
  30. CustomRecoveryWithWriter.func1: c.Next()
  31. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:165 (0x194a0bc)
  32. (*Context).Next: c.handlers[c.index](c)
  33. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/logger.go:241 (0x195ae31)
  34. LoggerWithConfig.func1: c.Next()
  35. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/context.go:165 (0x194a0bc)
  36. (*Context).Next: c.handlers[c.index](c)
  37. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/gin.go:489 (0x1958a7b)
  38. (*Engine).handleHTTPRequest: c.Next()
  39. /Users/vajahat/go/pkg/mod/github.com/gin-gonic/gin@v1.7.0/gin.go:445 (0x1958584)
  40. (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
  41. /usr/local/go/src/net/http/server.go:2947 (0x14ca5d3)
  42. serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
  43. /usr/local/go/src/net/http/server.go:1991 (0x14c413b)
  44. (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
  45. /usr/local/go/src/runtime/asm_amd64.s:1594 (0x1072640)
  46. goexit: BYTE $0x90 // NOP
  47. [GIN] 2022/08/06 - 00:36:53 | 500 | 5.20548072s | ::1 | GET "/health"

The error json: error calling MarshalJSON for type routes.Temp: invalid character 'e' looking for beginning of value is troubling me for very long.

I am expecting an output as following.

  1. {
  2. "token":"eyJUaW1lIjoiMjAyMi0wOC0wNlQwMDo0ODoyOS4yNDEzNTUrMDU6MzAifQo="
  3. }

While in debugger, It is working.
The problem is at rendering time, i belive. I want to get above as output.

Any suggestion or help is highly appreciated.

Custom JSON Marshaller Supporting Base64 encoding | error calling MarshalJSON for type routes.Temp: invalid character 'e'

答案1

得分: 2

你的MarshalJSON()函数必须返回一个有效的JSON值;然而,你的示例生成了一个原始的Base64字符串,这不是有效的JSON。

你可以通过简单地在当前的返回值外面添加引号来修复它,使其成为一个有效的JSON字符串!

  1. b64len := base64.StdEncoding.EncodedLen(len(raw))
  2. dst := make([]byte, b64len+2)
  3. base64.StdEncoding.Encode(dst[1:], raw)
  4. dst[0], dst[b64len+1] = '"', '"'
  5. return dst, nil
英文:

Your MarshalJSON() function must return a valid JSON value; however, your example produces a raw Base64 string, which is not valid JSON.

You can fix it by simply wrapping your current return value in quotes to make it a valid JSON string!

<!-- language: lang-go -->

  1. b64len := base64.StdEncoding.EncodedLen(len(raw))
  2. dst := make([]byte, b64len+2)
  3. base64.StdEncoding.Encode(dst[1:], raw)
  4. dst[0], dst[b64len+1] = &#39;&quot;&#39;, &#39;&quot;&#39;
  5. return dst, nil

huangapple
  • 本文由 发表于 2022年8月6日 03:28:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/73254490.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定